// Instantiate the object
var I18n = I18n || {};

// Set default locale to english
I18n.defaultLocale = "en";

// Set default separator
I18n.defaultSeparator = ".";

// Set current locale to null
I18n.locale = null;

// Set the placeholder format. Accepts `{{placeholder}}` and `%{placeholder}`.
I18n.PLACEHOLDER = /(?:\{\{|%\{)(.*?)(?:\}\}?)/gm;

I18n.isValidNode = function(obj, node) {
    // local undefined variable in case another library corrupts window.undefined
    var undef;
    return obj[node] !== null && obj[node] !== undef;
}

I18n.lookup = function(scope, options) {
  var translations = this.prepareOptions(I18n.translations);
  var messages = translations[I18n.currentLocale()];
  options = this.prepareOptions(options);

  if (!messages) {
    return;
  }

  if (typeof(scope) == "object") {
    scope = scope.join(this.defaultSeparator);
  }

  if (options.scope) {
    scope = options.scope.toString() + this.defaultSeparator + scope;
  }

  scope = scope.split(this.defaultSeparator);

  while (scope.length > 0) {
    var currentScope = scope.shift();
    messages = messages[currentScope];

    if (!messages) {
      break;
    }
  }

  if (!messages && this.isValidNode(options, "defaultValue")) {
    messages = options.defaultValue;
  }

  return messages;
};

// Merge serveral hash options, checking if value is set before
// overwriting any value. The precedence is from left to right.
//
//   I18n.prepareOptions({name: "John Doe"}, {name: "Mary Doe", role: "user"});
//   #=> {name: "John Doe", role: "user"}
//
I18n.prepareOptions = function() {
  var options = {};
  var opts;
  var count = arguments.length;

  for (var i = 0; i < count; i++) {
    opts = arguments[i];

    if (!opts) {
      continue;
    }

    for (var key in opts) {
      if (!this.isValidNode(options, key)) {
        options[key] = opts[key];
      }
    }
  }

  return options;
};

I18n.interpolate = function(message, options) {
  options = this.prepareOptions(options);
  var matches = message.match(this.PLACEHOLDER);

  if (!matches) {
    return message;
  }

  var placeholder, value, name;

  for (var i = 0; placeholder = matches[i]; i++) {
    name = placeholder.replace(this.PLACEHOLDER, "$1");

    value = options[name];

    if (!this.isValidNode(options, name)) {
      value = "[missing " + placeholder + " value]";
    }

    regex = new RegExp(placeholder.replace(/\{/gm, "\\{").replace(/\}/gm, "\\}"));
    message = message.replace(regex, value);
  }

  return message;
};

I18n.translate = function(scope, options) {
  options = this.prepareOptions(options);
  var translation = this.lookup(scope, options);

  try {
    if (typeof(translation) == "object") {
      if (typeof(options.count) == "number") {
        return this.pluralize(options.count, scope, options);
      } else {
        return translation;
      }
    } else {
      return this.interpolate(translation, options);
    }
  } catch(err) {
    return this.missingTranslation(scope);
  }
};

I18n.localize = function(scope, value) {
  switch (scope) {
    case "currency":
      return this.toCurrency(value);
    case "number":
      scope = this.lookup("number.format");
      return this.toNumber(value, scope);
    case "percentage":
      return this.toPercentage(value);
    default:
      if (scope.match(/^(date|time)/)) {
        return this.toTime(scope, value);
      } else {
        return value.toString();
      }
  }
};

I18n.parseDate = function(date) {
  var matches, convertedDate;

  // we have a date, so just return it.
  if (typeof(date) == "object") {
    return date;
  };

  // it matches the following formats:
  //   yyyy-mm-dd
  //   yyyy-mm-dd[ T]hh:mm::ss
  //   yyyy-mm-dd[ T]hh:mm::ss
  //   yyyy-mm-dd[ T]hh:mm::ssZ
  //   yyyy-mm-dd[ T]hh:mm::ss+0000
  //
  matches = date.toString().match(/(\d{4})-(\d{2})-(\d{2})(?:[ T](\d{2}):(\d{2}):(\d{2}))?(Z|\+0000)?/);

  if (matches) {
    for (var i = 1; i <= 6; i++) {
      matches[i] = parseInt(matches[i], 10) || 0;
    }

    // month starts on 0
    matches[2] -= 1;

    if (matches[7]) {
      convertedDate = new Date(Date.UTC(matches[1], matches[2], matches[3], matches[4], matches[5], matches[6]));
    } else {
      convertedDate = new Date(matches[1], matches[2], matches[3], matches[4], matches[5], matches[6]);
    }
  } else if (typeof(date) == "number") {
    // UNIX timestamp
    convertedDate = new Date();
    convertedDate.setTime(date);
  } else if (date.match(/\d+ \d+:\d+:\d+ [+-]\d+ \d+/)) {
    // a valid javascript format with timezone info
    convertedDate = new Date();
    convertedDate.setTime(Date.parse(date))
  } else {
    // an arbitrary javascript string
    convertedDate = new Date();
    convertedDate.setTime(Date.parse(date));
  }

  return convertedDate;
};

I18n.toTime = function(scope, d) {
  var date = this.parseDate(d);
  var format = this.lookup(scope);

  if (date.toString().match(/invalid/i)) {
    return date.toString();
  }

  if (!format) {
    return date.toString();
  }

  return this.strftime(date, format);
};

I18n.strftime = function(date, format) {
  var options = this.lookup("date");

  if (!options) {
    return date.toString();
  }
  options.meridian = options.meridian || ["AM", "PM"];

  var weekDay = date.getDay();
  var day = date.getDate();
  var year = date.getFullYear();
  var month = date.getMonth() + 1;
  var hour = date.getHours();
  var hour12 = hour;
  var meridian = hour > 11 ? 1 : 0;
  var secs = date.getSeconds();
  var mins = date.getMinutes();
  var offset = date.getTimezoneOffset();
  var absOffsetHours = Math.floor(Math.abs(offset / 60));
  var absOffsetMinutes = Math.abs(offset) - (absOffsetHours * 60);
  var timezoneoffset = (offset > 0 ? "-" : "+") + (absOffsetHours.toString().length < 2 ? "0" + absOffsetHours : absOffsetHours) + (absOffsetMinutes.toString().length < 2 ? "0" + absOffsetMinutes : absOffsetMinutes);

  if (hour12 > 12) {
    hour12 = hour12 - 12;
  } else if (hour12 === 0) {
    hour12 = 12;
  }

  var padding = function(n) {
    var s = "0" + n.toString();
    return s.substr(s.length - 2);
  };

  var f = format;
  f = f.replace("%a", options.abbr_day_names[weekDay]);
  f = f.replace("%A", options.day_names[weekDay]);
  f = f.replace("%b", options.abbr_month_names[month]);
  f = f.replace("%B", options.month_names[month]);
  f = f.replace("%d", padding(day));
  f = f.replace("%e", day);
  f = f.replace("%-d", day);
  f = f.replace("%H", padding(hour));
  f = f.replace("%-H", hour);
  f = f.replace("%I", padding(hour12));
  f = f.replace("%-I", hour12);
  f = f.replace("%m", padding(month));
  f = f.replace("%-m", month);
  f = f.replace("%M", padding(mins));
  f = f.replace("%-M", mins);
  f = f.replace("%p", options.meridian[meridian]);
  f = f.replace("%S", padding(secs));
  f = f.replace("%-S", secs);
  f = f.replace("%w", weekDay);
  f = f.replace("%y", padding(year));
  f = f.replace("%-y", padding(year).replace(/^0+/, ""));
  f = f.replace("%Y", year);
  f = f.replace("%z", timezoneoffset);

  return f;
};

I18n.toNumber = function(number, options) {
  options = this.prepareOptions(
    options,
    this.lookup("number.format"),
    {precision: 3, separator: ".", delimiter: ",", strip_insignificant_zeros: false}
  );

  var negative = number < 0;
  var string = Math.abs(number).toFixed(options.precision).toString();
  var parts = string.split(".");

  number = parts[0];
  var precision = parts[1];

  var n = [];

  while (number.length > 0) {
    n.unshift(number.substr(Math.max(0, number.length - 3), 3));
    number = number.substr(0, number.length -3);
  }

  var formattedNumber = n.join(options.delimiter);

  if (options.precision > 0) {
    formattedNumber += options.separator + parts[1];
  }

  if (negative) {
    formattedNumber = "-" + formattedNumber;
  }

  if (options.strip_insignificant_zeros) {
    var regex = {
        separator: new RegExp(options.separator.replace(/\./, "\\.") + "$")
      , zeros: /0+$/
    };

    formattedNumber = formattedNumber
      .replace(regex.zeros, "")
      .replace(regex.separator, "");
  }

  return formattedNumber;
};

I18n.toCurrency = function(number, options) {
  options = this.prepareOptions(
    options,
    this.lookup("number.currency.format"),
    this.lookup("number.format"),
    {unit: "$", precision: 2, format: "%u%n", delimiter: ",", separator: "."}
  );

  number = this.toNumber(number, options);
  number = options.format
    .replace("%u", options.unit)
    .replace("%n", number);

  return number;
};

I18n.toHumanSize = function(number, options) {
  var kb = 1024
    , size = number
    , iterations = 0
    , unit
    , precision
  ;

  while (size >= kb && iterations < 4) {
    size = size / kb;
    iterations += 1;
  }

  if (iterations === 0) {
    unit = this.t("number.human.storage_units.units.byte", {count: size});
    precision = 0;
  } else {
    unit = this.t("number.human.storage_units.units." + [null, "kb", "mb", "gb", "tb"][iterations]);
    precision = (size - Math.floor(size) === 0) ? 0 : 1;
  }

  options = this.prepareOptions(
    options,
    {precision: precision, format: "%n%u", delimiter: ""}
  );

  number = this.toNumber(size, options);
  number = options.format
    .replace("%u", unit)
    .replace("%n", number);

  return number;
};

I18n.toPercentage = function(number, options) {
  options = this.prepareOptions(
    options,
    this.lookup("number.percentage.format"),
    this.lookup("number.format"),
    {precision: 3, separator: ".", delimiter: ""}
  );

  number = this.toNumber(number, options);
  return number + "%";
};

I18n.pluralize = function(count, scope, options) {
  var translation;

  try {
    translation = this.lookup(scope, options);
  } catch (error) {}

  if (!translation) {
    return this.missingTranslation(scope);
  }

  var message;
  options = this.prepareOptions(options);
  options.count = count.toString();

  switch(Math.abs(count)) {
    case 0:
      message = this.isValidNode(translation, "zero") ? translation.zero :
                this.isValidNode(translation, "none") ? translation.none :
                this.isValidNode(translation, "other") ? translation.other :
                this.missingTranslation(scope, "zero");
      break;
    case 1:
      message = this.isValidNode(translation, "one") ? translation.one : this.missingTranslation(scope, "one");
      break;
    default:
      message = this.isValidNode(translation, "other") ? translation.other : this.missingTranslation(scope, "other");
  }

  return this.interpolate(message, options);
};

I18n.missingTranslation = function() {
  var message = '[missing "' + this.currentLocale();
  var count = arguments.length;

  for (var i = 0; i < count; i++) {
    message += "." + arguments[i];
  }

  message += '" translation]';

  return message;
};

I18n.currentLocale = function() {
  return (I18n.locale || I18n.defaultLocale);
};

// shortcuts
I18n.t = I18n.translate;
I18n.l = I18n.localize;
I18n.p = I18n.pluralize;
var I18n = I18n || {};
I18n.translations = {"en":{"date":{"formats":{"default":"%Y-%m-%d","short":"%b %d","long":"%B %d, %Y"},"day_names":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"abbr_day_names":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"month_names":[null,"January","February","March","April","May","June","July","August","September","October","November","December"],"abbr_month_names":[null,"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],"order":["year","month","day"]},"time":{"formats":{"default":"%a, %d %b %Y %H:%M:%S %z","short":"%d %b %H:%M","long":"%B %d, %Y %H:%M"},"am":"am","pm":"pm"},"chat":{"status_label":null,"online_statuses":{"online":"Online","offline":"Offline","away":"Away","available":"Available"},"status":null}},"de":{"date":{"formats":{"default":"%d.%m.%Y","short":"%e. %b","long":"%e. %B %Y","only_day":"%e"},"day_names":["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],"abbr_day_names":["So","Mo","Di","Mi","Do","Fr","Sa"],"month_names":[null,"Januar","Februar","M\u00e4rz","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],"abbr_month_names":[null,"Jan","Feb","M\u00e4r","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],"order":["year","month","day"]},"time":{"formats":{"default":"%A, %d. %B %Y, %H:%M Uhr","short":"%d. %B, %H:%M Uhr","long":"%A, %d. %B %Y, %H:%M Uhr","time":"%H:%M","chat_short":"%H:%M","chat_long":"%d. %B, %H:%M","messages_short":"%d.%m.%y, %H:%M Uhr","messages_long":"%d. %B, %H:%M Uhr"},"am":"vormittags","pm":"nachmittags"},"chat":{"status":{"status":"Chat-Status: ","online":"Online","offline":"Offline","abwesend":"Gerade im Stress","lust":"Lust auf Chatten"},"status_label":"Chat-Status: ","online_statuses":{"online":"Online","offline":"Offline","away":"Gerade im Stress","available":"Lust auf Chatten"},"chat_request":{"notification":{"title":"Neue Chat-Anfrage","message":"Neue Chat-Anfrage von %{user_name}","link":"Chat \u00f6ffnen"}},"chat_message":{"notification":{"title":"Neue Chat-Nachricht","message":"Neue Chat-Nachricht von %{user_name}","link":"Chat \u00f6ffnen"}},"chat_box_empty":{"none_selected":"Kein Chatpartner ausgew\u00e4hlt","person_to_chat":"Bitte klicke im rechten Bereich auf eine Person, mit der du chatten m\u00f6chtest.","message_blink":"Wenn du eine Nachricht erhalten hast, blinkt der Personstatus rechts auf."},"video_chat":{"flash_fallback":"Sie ben\u00f6tigen das Flash Plugin in einer aktuellen Version, um den Videochat nutzen zu k\u00f6nnen."},"video_chat_request":{"request":{"title":"Videochat-Anfrage","message":"Ihre Anfrage wurde gesendet"},"notification":{"title":"Videochat-Anfrage","message":"Neue Videochat-Anfrage von %{user_name}","link":"Videochat \u00f6ffnen","accept":"Videochat starten","deny":"Ablehnen"},"accepted":{"title":"Ihre Anfrage wurde akzeptiert!","link":"zum Videochat"},"denied":{"title":"Ihre Anfrage wurde abgelehnt","link":"schliessen"}},"flash":{"me_deactivated":"Du hast den Audio/Video-Chat deaktiviert","other_deactivated":"%{user_name} hat den Audio/Video-Chat deaktiviert"}}}};
(function() {
  window.AppConfig = {
    "faye_uri": "http://meandyou.com:9292/faye",
    "js_logging": false
  };
  if (window.I18n) {
    I18n.defaultLocale = "de";
    I18n.locale = "de";
    I18n.fallbacks = true;
  }
}).call(this);
(function() {
  window.log = function() {
    if (this.console && AppConfig.js_logging) {
      log.history = log.history || [];
      return log.history.push(arguments);
    }
  };
  window.FayeLogger = {
    incoming: function(message, callback) {
      log("Faye: " + message.channel, message);
      return callback(message);
    }
  };
}).call(this);
/* Modernizr 2.0.6 (Custom Build) | MIT & BSD
 * Build: http://www.modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-iepp-respond-mq-cssclasses-addtest-prefixed-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-load
 */

;window.Modernizr=function(a,b,c){function I(){e.input=function(a){for(var b=0,c=a.length;b<c;b++)t[a[b]]=a[b]in l;return t}("autocomplete autofocus list placeholder max min multiple pattern required step".split(" ")),e.inputtypes=function(a){for(var d=0,e,f,h,i=a.length;d<i;d++)l.setAttribute("type",f=a[d]),e=l.type!=="text",e&&(l.value=m,l.style.cssText="position:absolute;visibility:hidden;",/^range$/.test(f)&&l.style.WebkitAppearance!==c?(g.appendChild(l),h=b.defaultView,e=h.getComputedStyle&&h.getComputedStyle(l,null).WebkitAppearance!=="textfield"&&l.offsetHeight!==0,g.removeChild(l)):/^(search|tel)$/.test(f)||(/^(url|email)$/.test(f)?e=l.checkValidity&&l.checkValidity()===!1:/^color$/.test(f)?(g.appendChild(l),g.offsetWidth,e=l.value!=m,g.removeChild(l)):e=l.value!=m)),s[a[d]]=!!e;return s}("search tel url email datetime date month week time datetime-local number range color".split(" "))}function G(a,b){var c=a.charAt(0).toUpperCase()+a.substr(1),d=(a+" "+p.join(c+" ")+c).split(" ");return F(d,b)}function F(a,b){for(var d in a)if(k[a[d]]!==c)return b=="pfx"?a[d]:!0;return!1}function E(a,b){return!!~(""+a).indexOf(b)}function D(a,b){return typeof a===b}function C(a,b){return B(o.join(a+";")+(b||""))}function B(a){k.cssText=a}var d="2.0.6",e={},f=!0,g=b.documentElement,h=b.head||b.getElementsByTagName("head")[0],i="modernizr",j=b.createElement(i),k=j.style,l=b.createElement("input"),m=":)",n=Object.prototype.toString,o=" -webkit- -moz- -o- -ms- -khtml- ".split(" "),p="Webkit Moz O ms Khtml".split(" "),q={svg:"http://www.w3.org/2000/svg"},r={},s={},t={},u=[],v=function(a,c,d,e){var f,h,j,k=b.createElement("div");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:i+(d+1),k.appendChild(j);f=["&shy;","<style>",a,"</style>"].join(""),k.id=i,k.innerHTML+=f,g.appendChild(k),h=c(k,a),k.parentNode.removeChild(k);return!!h},w=function(b){if(a.matchMedia)return matchMedia(b).matches;var c;v("@media "+b+" { #"+i+" { position: absolute; } }",function(b){c=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle).position=="absolute"});return c},x=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=D(e[d],"function"),D(e[d],c)||(e[d]=c),e.removeAttribute(d))),e=null;return f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),y,z={}.hasOwnProperty,A;!D(z,c)&&!D(z.call,c)?A=function(a,b){return z.call(a,b)}:A=function(a,b){return b in a&&D(a.constructor.prototype[b],c)};var H=function(c,d){var f=c.join(""),g=d.length;v(f,function(c,d){var f=b.styleSheets[b.styleSheets.length-1],h=f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"",i=c.childNodes,j={};while(g--)j[i[g].id]=i[g];e.touch="ontouchstart"in a||j.touch.offsetTop===9,e.csstransforms3d=j.csstransforms3d.offsetLeft===9,e.generatedcontent=j.generatedcontent.offsetHeight>=1,e.fontface=/src/i.test(h)&&h.indexOf(d.split(" ")[0])===0},g,d)}(['@font-face {font-family:"font";src:url("https://")}',["@media (",o.join("touch-enabled),("),i,")","{#touch{top:9px;position:absolute}}"].join(""),["@media (",o.join("transform-3d),("),i,")","{#csstransforms3d{left:9px;position:absolute}}"].join(""),['#generatedcontent:after{content:"',m,'";visibility:hidden}'].join("")],["fontface","touch","csstransforms3d","generatedcontent"]);r.flexbox=function(){function c(a,b,c,d){a.style.cssText=o.join(b+":"+c+";")+(d||"")}function a(a,b,c,d){b+=":",a.style.cssText=(b+o.join(c+";"+b)).slice(0,-b.length)+(d||"")}var d=b.createElement("div"),e=b.createElement("div");a(d,"display","box","width:42px;padding:0;"),c(e,"box-flex","1","width:10px;"),d.appendChild(e),g.appendChild(d);var f=e.offsetWidth===42;d.removeChild(e),g.removeChild(d);return f},r.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},r.canvastext=function(){return!!e.canvas&&!!D(b.createElement("canvas").getContext("2d").fillText,"function")},r.webgl=function(){return!!a.WebGLRenderingContext},r.touch=function(){return e.touch},r.geolocation=function(){return!!navigator.geolocation},r.postmessage=function(){return!!a.postMessage},r.websqldatabase=function(){var b=!!a.openDatabase;return b},r.indexedDB=function(){for(var b=-1,c=p.length;++b<c;)if(a[p[b].toLowerCase()+"IndexedDB"])return!0;return!!a.indexedDB},r.hashchange=function(){return x("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},r.history=function(){return!!a.history&&!!history.pushState},r.draganddrop=function(){return x("dragstart")&&x("drop")},r.websockets=function(){for(var b=-1,c=p.length;++b<c;)if(a[p[b]+"WebSocket"])return!0;return"WebSocket"in a},r.rgba=function(){B("background-color:rgba(150,255,150,.5)");return E(k.backgroundColor,"rgba")},r.hsla=function(){B("background-color:hsla(120,40%,100%,.5)");return E(k.backgroundColor,"rgba")||E(k.backgroundColor,"hsla")},r.multiplebgs=function(){B("background:url(https://),url(https://),red url(https://)");return/(url\s*\(.*?){3}/.test(k.background)},r.backgroundsize=function(){return G("backgroundSize")},r.borderimage=function(){return G("borderImage")},r.borderradius=function(){return G("borderRadius")},r.boxshadow=function(){return G("boxShadow")},r.textshadow=function(){return b.createElement("div").style.textShadow===""},r.opacity=function(){C("opacity:.55");return/^0.55$/.test(k.opacity)},r.cssanimations=function(){return G("animationName")},r.csscolumns=function(){return G("columnCount")},r.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";B((a+o.join(b+a)+o.join(c+a)).slice(0,-a.length));return E(k.backgroundImage,"gradient")},r.cssreflections=function(){return G("boxReflect")},r.csstransforms=function(){return!!F(["transformProperty","WebkitTransform","MozTransform","OTransform","msTransform"])},r.csstransforms3d=function(){var a=!!F(["perspectiveProperty","WebkitPerspective","MozPerspective","OPerspective","msPerspective"]);a&&"webkitPerspective"in g.style&&(a=e.csstransforms3d);return a},r.csstransitions=function(){return G("transitionProperty")},r.fontface=function(){return e.fontface},r.generatedcontent=function(){return e.generatedcontent},r.video=function(){var a=b.createElement("video"),c=!1;try{if(c=!!a.canPlayType){c=new Boolean(c),c.ogg=a.canPlayType('video/ogg; codecs="theora"');var d='video/mp4; codecs="avc1.42E01E';c.h264=a.canPlayType(d+'"')||a.canPlayType(d+', mp4a.40.2"'),c.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"')}}catch(e){}return c},r.audio=function(){var a=b.createElement("audio"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('audio/ogg; codecs="vorbis"'),c.mp3=a.canPlayType("audio/mpeg;"),c.wav=a.canPlayType('audio/wav; codecs="1"'),c.m4a=a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")}catch(d){}return c},r.localstorage=function(){try{return!!localStorage.getItem}catch(a){return!1}},r.sessionstorage=function(){try{return!!sessionStorage.getItem}catch(a){return!1}},r.webworkers=function(){return!!a.Worker},r.applicationcache=function(){return!!a.applicationCache},r.svg=function(){return!!b.createElementNS&&!!b.createElementNS(q.svg,"svg").createSVGRect},r.inlinesvg=function(){var a=b.createElement("div");a.innerHTML="<svg/>";return(a.firstChild&&a.firstChild.namespaceURI)==q.svg},r.smil=function(){return!!b.createElementNS&&/SVG/.test(n.call(b.createElementNS(q.svg,"animate")))},r.svgclippaths=function(){return!!b.createElementNS&&/SVG/.test(n.call(b.createElementNS(q.svg,"clipPath")))};for(var J in r)A(r,J)&&(y=J.toLowerCase(),e[y]=r[J](),u.push((e[y]?"":"no-")+y));e.input||I(),e.addTest=function(a,b){if(typeof a=="object")for(var d in a)A(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return;b=typeof b=="boolean"?b:!!b(),g.className+=" "+(b?"":"no-")+a,e[a]=b}return e},B(""),j=l=null,a.attachEvent&&function(){var a=b.createElement("div");a.innerHTML="<elem></elem>";return a.childNodes.length!==1}()&&function(a,b){function s(a){var b=-1;while(++b<g)a.createElement(f[b])}a.iepp=a.iepp||{};var d=a.iepp,e=d.html5elements||"abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",f=e.split("|"),g=f.length,h=new RegExp("(^|\\s)("+e+")","gi"),i=new RegExp("<(/*)("+e+")","gi"),j=/^\s*[\{\}]\s*$/,k=new RegExp("(^|[^\\n]*?\\s)("+e+")([^\\n]*)({[\\n\\w\\W]*?})","gi"),l=b.createDocumentFragment(),m=b.documentElement,n=m.firstChild,o=b.createElement("body"),p=b.createElement("style"),q=/print|all/,r;d.getCSS=function(a,b){if(a+""===c)return"";var e=-1,f=a.length,g,h=[];while(++e<f){g=a[e];if(g.disabled)continue;b=g.media||b,q.test(b)&&h.push(d.getCSS(g.imports,b),g.cssText),b="all"}return h.join("")},d.parseCSS=function(a){var b=[],c;while((c=k.exec(a))!=null)b.push(((j.exec(c[1])?"\n":c[1])+c[2]+c[3]).replace(h,"$1.iepp_$2")+c[4]);return b.join("\n")},d.writeHTML=function(){var a=-1;r=r||b.body;while(++a<g){var c=b.getElementsByTagName(f[a]),d=c.length,e=-1;while(++e<d)c[e].className.indexOf("iepp_")<0&&(c[e].className+=" iepp_"+f[a])}l.appendChild(r),m.appendChild(o),o.className=r.className,o.id=r.id,o.innerHTML=r.innerHTML.replace(i,"<$1font")},d._beforePrint=function(){p.styleSheet.cssText=d.parseCSS(d.getCSS(b.styleSheets,"all")),d.writeHTML()},d.restoreHTML=function(){o.innerHTML="",m.removeChild(o),m.appendChild(r)},d._afterPrint=function(){d.restoreHTML(),p.styleSheet.cssText=""},s(b),s(l);d.disablePP||(n.insertBefore(p,n.firstChild),p.media="print",p.className="iepp-printshim",a.attachEvent("onbeforeprint",d._beforePrint),a.attachEvent("onafterprint",d._afterPrint))}(a,b),e._version=d,e._prefixes=o,e._domPrefixes=p,e.mq=w,e.hasEvent=x,e.testProp=function(a){return F([a])},e.testAllProps=G,e.testStyles=v,e.prefixed=function(a){return G(a,"pfx")},g.className=g.className.replace(/\bno-js\b/,"")+(f?" js "+u.join(" "):"");return e}(this,this.document),function(a,b){function u(){r(!0)}a.respond={},respond.update=function(){},respond.mediaQueriesSupported=b;if(!b){var c=a.document,d=c.documentElement,e=[],f=[],g=[],h={},i=30,j=c.getElementsByTagName("head")[0]||d,k=j.getElementsByTagName("link"),l=[],m=function(){var b=k,c=b.length,d=0,e,f,g,i;for(;d<c;d++)e=b[d],f=e.href,g=e.media,i=e.rel&&e.rel.toLowerCase()==="stylesheet",!!f&&i&&!h[f]&&(!/^([a-zA-Z]+?:(\/\/)?(www\.)?)/.test(f)||f.replace(RegExp.$1,"").split("/")[0]===a.location.host?l.push({href:f,media:g}):h[f]=!0);n()},n=function(){if(l.length){var a=l.shift();s(a.href,function(b){o(b,a.href,a.media),h[a.href]=!0,n()})}},o=function(a,b,c){var d=a.match(/@media[^\{]+\{([^\{\}]+\{[^\}\{]+\})+/gi),g=d&&d.length||0,b=b.substring(0,b.lastIndexOf("/")),h=function(a){return a.replace(/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,"$1"+b+"$2$3")},i=!g&&c,j=0,k,l,m,n,o;b.length&&(b+="/"),i&&(g=1);for(;j<g;j++){k=0,i?(l=c,f.push(h(a))):(l=d[j].match(/@media ([^\{]+)\{([\S\s]+?)$/)&&RegExp.$1,f.push(RegExp.$2&&h(RegExp.$2))),n=l.split(","),o=n.length;for(;k<o;k++)m=n[k],e.push({media:m.match(/(only\s+)?([a-zA-Z]+)(\sand)?/)&&RegExp.$2,rules:f.length-1,minw:m.match(/\(min\-width:[\s]*([\s]*[0-9]+)px[\s]*\)/)&&parseFloat(RegExp.$1),maxw:m.match(/\(max\-width:[\s]*([\s]*[0-9]+)px[\s]*\)/)&&parseFloat(RegExp.$1)})}r()},p,q,r=function(a){var b="clientWidth",h=d[b],l=c.compatMode==="CSS1Compat"&&h||c.body[b]||h,m={},n=c.createDocumentFragment(),o=k[k.length-1],s=(new Date).getTime();if(a&&p&&s-p<i)clearTimeout(q),q=setTimeout(r,i);else{p=s;for(var t in e){var u=e[t];if(!u.minw&&!u.maxw||(!u.minw||u.minw&&l>=u.minw)&&(!u.maxw||u.maxw&&l<=u.maxw))m[u.media]||(m[u.media]=[]),m[u.media].push(f[u.rules])}for(var t in g)g[t]&&g[t].parentNode===j&&j.removeChild(g[t]);for(var t in m){var v=c.createElement("style"),w=m[t].join("\n");v.type="text/css",v.media=t,v.styleSheet?v.styleSheet.cssText=w:v.appendChild(c.createTextNode(w)),n.appendChild(v),g.push(v)}j.insertBefore(n,o.nextSibling)}},s=function(a,b){var c=t();if(!!c){c.open("GET",a,!0),c.onreadystatechange=function(){c.readyState==4&&(c.status==200||c.status==304)&&b(c.responseText)};if(c.readyState==4)return;c.send()}},t=function(){var a=!1,b=[function(){return new ActiveXObject("Microsoft.XMLHTTP")},function(){return new XMLHttpRequest}],c=b.length;while(c--){try{a=b[c]()}catch(d){continue}break}return function(){return a}}();m(),respond.update=m,a.addEventListener?a.addEventListener("resize",u,!1):a.attachEvent&&a.attachEvent("onresize",u)}}(this,Modernizr.mq("only all")),function(a,b,c){function k(a){return!a||a=="loaded"||a=="complete"}function j(){var a=1,b=-1;while(p.length- ++b)if(p[b].s&&!(a=p[b].r))break;a&&g()}function i(a){var c=b.createElement("script"),d;c.src=a.s,c.onreadystatechange=c.onload=function(){!d&&k(c.readyState)&&(d=1,j(),c.onload=c.onreadystatechange=null)},m(function(){d||(d=1,j())},H.errorTimeout),a.e?c.onload():n.parentNode.insertBefore(c,n)}function h(a){var c=b.createElement("link"),d;c.href=a.s,c.rel="stylesheet",c.type="text/css";if(!a.e&&(w||r)){var e=function(a){m(function(){if(!d)try{a.sheet.cssRules.length?(d=1,j()):e(a)}catch(b){b.code==1e3||b.message=="security"||b.message=="denied"?(d=1,m(function(){j()},0)):e(a)}},0)};e(c)}else c.onload=function(){d||(d=1,m(function(){j()},0))},a.e&&c.onload();m(function(){d||(d=1,j())},H.errorTimeout),!a.e&&n.parentNode.insertBefore(c,n)}function g(){var a=p.shift();q=1,a?a.t?m(function(){a.t=="c"?h(a):i(a)},0):(a(),j()):q=0}function f(a,c,d,e,f,h){function i(){!o&&k(l.readyState)&&(r.r=o=1,!q&&j(),l.onload=l.onreadystatechange=null,m(function(){u.removeChild(l)},0))}var l=b.createElement(a),o=0,r={t:d,s:c,e:h};l.src=l.data=c,!s&&(l.style.display="none"),l.width=l.height="0",a!="object"&&(l.type=d),l.onload=l.onreadystatechange=i,a=="img"?l.onerror=i:a=="script"&&(l.onerror=function(){r.e=r.r=1,g()}),p.splice(e,0,r),u.insertBefore(l,s?null:n),m(function(){o||(u.removeChild(l),r.r=r.e=o=1,j())},H.errorTimeout)}function e(a,b,c){var d=b=="c"?z:y;q=0,b=b||"j",C(a)?f(d,a,b,this.i++,l,c):(p.splice(this.i++,0,a),p.length==1&&g());return this}function d(){var a=H;a.loader={load:e,i:0};return a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=r&&!s,u=s?l:n.parentNode,v=a.opera&&o.call(a.opera)=="[object Opera]",w="webkitAppearance"in l.style,x=w&&"async"in b.createElement("script"),y=r?"object":v||x?"img":"script",z=w?"img":y,A=Array.isArray||function(a){return o.call(a)=="[object Array]"},B=function(a){return Object(a)===a},C=function(a){return typeof a=="string"},D=function(a){return o.call(a)=="[object Function]"},E=[],F={},G,H;H=function(a){function f(a){var b=a.split("!"),c=E.length,d=b.pop(),e=b.length,f={url:d,origUrl:d,prefixes:b},g,h;for(h=0;h<e;h++)g=F[b[h]],g&&(f=g(f));for(h=0;h<c;h++)f=E[h](f);return f}function e(a,b,e,g,h){var i=f(a),j=i.autoCallback;if(!i.bypass){b&&(b=D(b)?b:b[a]||b[g]||b[a.split("/").pop().split("?")[0]]);if(i.instead)return i.instead(a,b,e,g,h);e.load(i.url,i.forceCSS||!i.forceJS&&/css$/.test(i.url)?"c":c,i.noexec),(D(b)||D(j))&&e.load(function(){d(),b&&b(i.origUrl,h,g),j&&j(i.origUrl,h,g)})}}function b(a,b){function c(a){if(C(a))e(a,h,b,0,d);else if(B(a))for(i in a)a.hasOwnProperty(i)&&e(a[i],h,b,i,d)}var d=!!a.test,f=d?a.yep:a.nope,g=a.load||a.both,h=a.callback,i;c(f),c(g),a.complete&&b.load(a.complete)}var g,h,i=this.yepnope.loader;if(C(a))e(a,0,i,0);else if(A(a))for(g=0;g<a.length;g++)h=a[g],C(h)?e(h,0,i,0):A(h)?H(h):B(h)&&b(h,i);else B(a)&&b(a,i)},H.addPrefix=function(a,b){F[a]=b},H.addFilter=function(a){E.push(a)},H.errorTimeout=1e4,b.readyState==null&&b.addEventListener&&(b.readyState="loading",b.addEventListener("DOMContentLoaded",G=function(){b.removeEventListener("DOMContentLoaded",G,0),b.readyState="complete"},0)),a.yepnope=d()}(this,this.document),Modernizr.load=function(){yepnope.apply(window,[].slice.call(arguments,0))};
//     Underscore.js 1.2.2
//     (c) 2011 Jeremy Ashkenas, DocumentCloud Inc.
//     Underscore is freely distributable under the MIT license.
//     Portions of Underscore are inspired or borrowed from Prototype,
//     Oliver Steele's Functional, and John Resig's Micro-Templating.
//     For all details and documentation:
//     http://documentcloud.github.com/underscore

(function() {

  // Baseline setup
  // --------------

  // Establish the root object, `window` in the browser, or `global` on the server.
  var root = this;

  // Save the previous value of the `_` variable.
  var previousUnderscore = root._;

  // Establish the object that gets returned to break out of a loop iteration.
  var breaker = {};

  // Save bytes in the minified (but not gzipped) version:
  var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;

  // Create quick reference variables for speed access to core prototypes.
  var slice            = ArrayProto.slice,
      unshift          = ArrayProto.unshift,
      toString         = ObjProto.toString,
      hasOwnProperty   = ObjProto.hasOwnProperty;

  // All **ECMAScript 5** native function implementations that we hope to use
  // are declared here.
  var
    nativeForEach      = ArrayProto.forEach,
    nativeMap          = ArrayProto.map,
    nativeReduce       = ArrayProto.reduce,
    nativeReduceRight  = ArrayProto.reduceRight,
    nativeFilter       = ArrayProto.filter,
    nativeEvery        = ArrayProto.every,
    nativeSome         = ArrayProto.some,
    nativeIndexOf      = ArrayProto.indexOf,
    nativeLastIndexOf  = ArrayProto.lastIndexOf,
    nativeIsArray      = Array.isArray,
    nativeKeys         = Object.keys,
    nativeBind         = FuncProto.bind;

  // Create a safe reference to the Underscore object for use below.
  var _ = function(obj) { return new wrapper(obj); };

  // Export the Underscore object for **Node.js** and **"CommonJS"**, with
  // backwards-compatibility for the old `require()` API. If we're not in
  // CommonJS, add `_` to the global object.
  if (typeof exports !== 'undefined') {
    if (typeof module !== 'undefined' && module.exports) {
      exports = module.exports = _;
    }
    exports._ = _;
  } else if (typeof define === 'function' && define.amd) {
    // Register as a named module with AMD.
    define('underscore', function() {
      return _;
    });
  } else {
    // Exported as a string, for Closure Compiler "advanced" mode.
    root['_'] = _;
  }

  // Current version.
  _.VERSION = '1.2.2';

  // Collection Functions
  // --------------------

  // The cornerstone, an `each` implementation, aka `forEach`.
  // Handles objects with the built-in `forEach`, arrays, and raw objects.
  // Delegates to **ECMAScript 5**'s native `forEach` if available.
  var each = _.each = _.forEach = function(obj, iterator, context) {
    if (obj == null) return;
    if (nativeForEach && obj.forEach === nativeForEach) {
      obj.forEach(iterator, context);
    } else if (obj.length === +obj.length) {
      for (var i = 0, l = obj.length; i < l; i++) {
        if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return;
      }
    } else {
      for (var key in obj) {
        if (hasOwnProperty.call(obj, key)) {
          if (iterator.call(context, obj[key], key, obj) === breaker) return;
        }
      }
    }
  };

  // Return the results of applying the iterator to each element.
  // Delegates to **ECMAScript 5**'s native `map` if available.
  _.map = function(obj, iterator, context) {
    var results = [];
    if (obj == null) return results;
    if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
    each(obj, function(value, index, list) {
      results[results.length] = iterator.call(context, value, index, list);
    });
    return results;
  };

  // **Reduce** builds up a single result from a list of values, aka `inject`,
  // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
  _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
    var initial = memo !== void 0;
    if (obj == null) obj = [];
    if (nativeReduce && obj.reduce === nativeReduce) {
      if (context) iterator = _.bind(iterator, context);
      return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
    }
    each(obj, function(value, index, list) {
      if (!initial) {
        memo = value;
        initial = true;
      } else {
        memo = iterator.call(context, memo, value, index, list);
      }
    });
    if (!initial) throw new TypeError("Reduce of empty array with no initial value");
    return memo;
  };

  // The right-associative version of reduce, also known as `foldr`.
  // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
  _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
    if (obj == null) obj = [];
    if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
      if (context) iterator = _.bind(iterator, context);
      return memo !== void 0 ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
    }
    var reversed = (_.isArray(obj) ? obj.slice() : _.toArray(obj)).reverse();
    return _.reduce(reversed, iterator, memo, context);
  };

  // Return the first value which passes a truth test. Aliased as `detect`.
  _.find = _.detect = function(obj, iterator, context) {
    var result;
    any(obj, function(value, index, list) {
      if (iterator.call(context, value, index, list)) {
        result = value;
        return true;
      }
    });
    return result;
  };

  // Return all the elements that pass a truth test.
  // Delegates to **ECMAScript 5**'s native `filter` if available.
  // Aliased as `select`.
  _.filter = _.select = function(obj, iterator, context) {
    var results = [];
    if (obj == null) return results;
    if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
    each(obj, function(value, index, list) {
      if (iterator.call(context, value, index, list)) results[results.length] = value;
    });
    return results;
  };

  // Return all the elements for which a truth test fails.
  _.reject = function(obj, iterator, context) {
    var results = [];
    if (obj == null) return results;
    each(obj, function(value, index, list) {
      if (!iterator.call(context, value, index, list)) results[results.length] = value;
    });
    return results;
  };

  // Determine whether all of the elements match a truth test.
  // Delegates to **ECMAScript 5**'s native `every` if available.
  // Aliased as `all`.
  _.every = _.all = function(obj, iterator, context) {
    var result = true;
    if (obj == null) return result;
    if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
    each(obj, function(value, index, list) {
      if (!(result = result && iterator.call(context, value, index, list))) return breaker;
    });
    return result;
  };

  // Determine if at least one element in the object matches a truth test.
  // Delegates to **ECMAScript 5**'s native `some` if available.
  // Aliased as `any`.
  var any = _.some = _.any = function(obj, iterator, context) {
    iterator = iterator || _.identity;
    var result = false;
    if (obj == null) return result;
    if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
    each(obj, function(value, index, list) {
      if (result || (result = iterator.call(context, value, index, list))) return breaker;
    });
    return !!result;
  };

  // Determine if a given value is included in the array or object using `===`.
  // Aliased as `contains`.
  _.include = _.contains = function(obj, target) {
    var found = false;
    if (obj == null) return found;
    if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
    found = any(obj, function(value) {
      return value === target;
    });
    return found;
  };

  // Invoke a method (with arguments) on every item in a collection.
  _.invoke = function(obj, method) {
    var args = slice.call(arguments, 2);
    return _.map(obj, function(value) {
      return (method.call ? method || value : value[method]).apply(value, args);
    });
  };

  // Convenience version of a common use case of `map`: fetching a property.
  _.pluck = function(obj, key) {
    return _.map(obj, function(value){ return value[key]; });
  };

  // Return the maximum element or (element-based computation).
  _.max = function(obj, iterator, context) {
    if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
    if (!iterator && _.isEmpty(obj)) return -Infinity;
    var result = {computed : -Infinity};
    each(obj, function(value, index, list) {
      var computed = iterator ? iterator.call(context, value, index, list) : value;
      computed >= result.computed && (result = {value : value, computed : computed});
    });
    return result.value;
  };

  // Return the minimum element (or element-based computation).
  _.min = function(obj, iterator, context) {
    if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
    if (!iterator && _.isEmpty(obj)) return Infinity;
    var result = {computed : Infinity};
    each(obj, function(value, index, list) {
      var computed = iterator ? iterator.call(context, value, index, list) : value;
      computed < result.computed && (result = {value : value, computed : computed});
    });
    return result.value;
  };

  // Shuffle an array.
  _.shuffle = function(obj) {
    var shuffled = [], rand;
    each(obj, function(value, index, list) {
      if (index == 0) {
        shuffled[0] = value;
      } else {
        rand = Math.floor(Math.random() * (index + 1));
        shuffled[index] = shuffled[rand];
        shuffled[rand] = value;
      }
    });
    return shuffled;
  };

  // Sort the object's values by a criterion produced by an iterator.
  _.sortBy = function(obj, iterator, context) {
    return _.pluck(_.map(obj, function(value, index, list) {
      return {
        value : value,
        criteria : iterator.call(context, value, index, list)
      };
    }).sort(function(left, right) {
      var a = left.criteria, b = right.criteria;
      return a < b ? -1 : a > b ? 1 : 0;
    }), 'value');
  };

  // Groups the object's values by a criterion. Pass either a string attribute
  // to group by, or a function that returns the criterion.
  _.groupBy = function(obj, val) {
    var result = {};
    var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };
    each(obj, function(value, index) {
      var key = iterator(value, index);
      (result[key] || (result[key] = [])).push(value);
    });
    return result;
  };

  // Use a comparator function to figure out at what index an object should
  // be inserted so as to maintain order. Uses binary search.
  _.sortedIndex = function(array, obj, iterator) {
    iterator || (iterator = _.identity);
    var low = 0, high = array.length;
    while (low < high) {
      var mid = (low + high) >> 1;
      iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
    }
    return low;
  };

  // Safely convert anything iterable into a real, live array.
  _.toArray = function(iterable) {
    if (!iterable)                return [];
    if (iterable.toArray)         return iterable.toArray();
    if (_.isArray(iterable))      return slice.call(iterable);
    if (_.isArguments(iterable))  return slice.call(iterable);
    return _.values(iterable);
  };

  // Return the number of elements in an object.
  _.size = function(obj) {
    return _.toArray(obj).length;
  };

  // Array Functions
  // ---------------

  // Get the first element of an array. Passing **n** will return the first N
  // values in the array. Aliased as `head`. The **guard** check allows it to work
  // with `_.map`.
  _.first = _.head = function(array, n, guard) {
    return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
  };

  // Returns everything but the last entry of the array. Especcialy useful on
  // the arguments object. Passing **n** will return all the values in
  // the array, excluding the last N. The **guard** check allows it to work with
  // `_.map`.
  _.initial = function(array, n, guard) {
    return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
  };

  // Get the last element of an array. Passing **n** will return the last N
  // values in the array. The **guard** check allows it to work with `_.map`.
  _.last = function(array, n, guard) {
    if ((n != null) && !guard) {
      return slice.call(array, Math.max(array.length - n, 0));
    } else {
      return array[array.length - 1];
    }
  };

  // Returns everything but the first entry of the array. Aliased as `tail`.
  // Especially useful on the arguments object. Passing an **index** will return
  // the rest of the values in the array from that index onward. The **guard**
  // check allows it to work with `_.map`.
  _.rest = _.tail = function(array, index, guard) {
    return slice.call(array, (index == null) || guard ? 1 : index);
  };

  // Trim out all falsy values from an array.
  _.compact = function(array) {
    return _.filter(array, function(value){ return !!value; });
  };

  // Return a completely flattened version of an array.
  _.flatten = function(array, shallow) {
    return _.reduce(array, function(memo, value) {
      if (_.isArray(value)) return memo.concat(shallow ? value : _.flatten(value));
      memo[memo.length] = value;
      return memo;
    }, []);
  };

  // Return a version of the array that does not contain the specified value(s).
  _.without = function(array) {
    return _.difference(array, slice.call(arguments, 1));
  };

  // Produce a duplicate-free version of the array. If the array has already
  // been sorted, you have the option of using a faster algorithm.
  // Aliased as `unique`.
  _.uniq = _.unique = function(array, isSorted, iterator) {
    var initial = iterator ? _.map(array, iterator) : array;
    var result = [];
    _.reduce(initial, function(memo, el, i) {
      if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) {
        memo[memo.length] = el;
        result[result.length] = array[i];
      }
      return memo;
    }, []);
    return result;
  };

  // Produce an array that contains the union: each distinct element from all of
  // the passed-in arrays.
  _.union = function() {
    return _.uniq(_.flatten(arguments, true));
  };

  // Produce an array that contains every item shared between all the
  // passed-in arrays. (Aliased as "intersect" for back-compat.)
  _.intersection = _.intersect = function(array) {
    var rest = slice.call(arguments, 1);
    return _.filter(_.uniq(array), function(item) {
      return _.every(rest, function(other) {
        return _.indexOf(other, item) >= 0;
      });
    });
  };

  // Take the difference between one array and another.
  // Only the elements present in just the first array will remain.
  _.difference = function(array, other) {
    return _.filter(array, function(value){ return !_.include(other, value); });
  };

  // Zip together multiple lists into a single array -- elements that share
  // an index go together.
  _.zip = function() {
    var args = slice.call(arguments);
    var length = _.max(_.pluck(args, 'length'));
    var results = new Array(length);
    for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i);
    return results;
  };

  // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
  // we need this function. Return the position of the first occurrence of an
  // item in an array, or -1 if the item is not included in the array.
  // Delegates to **ECMAScript 5**'s native `indexOf` if available.
  // If the array is large and already in sort order, pass `true`
  // for **isSorted** to use binary search.
  _.indexOf = function(array, item, isSorted) {
    if (array == null) return -1;
    var i, l;
    if (isSorted) {
      i = _.sortedIndex(array, item);
      return array[i] === item ? i : -1;
    }
    if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
    for (i = 0, l = array.length; i < l; i++) if (array[i] === item) return i;
    return -1;
  };

  // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
  _.lastIndexOf = function(array, item) {
    if (array == null) return -1;
    if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);
    var i = array.length;
    while (i--) if (array[i] === item) return i;
    return -1;
  };

  // Generate an integer Array containing an arithmetic progression. A port of
  // the native Python `range()` function. See
  // [the Python documentation](http://docs.python.org/library/functions.html#range).
  _.range = function(start, stop, step) {
    if (arguments.length <= 1) {
      stop = start || 0;
      start = 0;
    }
    step = arguments[2] || 1;

    var len = Math.max(Math.ceil((stop - start) / step), 0);
    var idx = 0;
    var range = new Array(len);

    while(idx < len) {
      range[idx++] = start;
      start += step;
    }

    return range;
  };

  // Function (ahem) Functions
  // ------------------

  // Reusable constructor function for prototype setting.
  var ctor = function(){};

  // Create a function bound to a given object (assigning `this`, and arguments,
  // optionally). Binding with arguments is also known as `curry`.
  // Delegates to **ECMAScript 5**'s native `Function.bind` if available.
  // We check for `func.bind` first, to fail fast when `func` is undefined.
  _.bind = function bind(func, context) {
    var bound, args;
    if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
    if (!_.isFunction(func)) throw new TypeError;
    args = slice.call(arguments, 2);
    return bound = function() {
      if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
      ctor.prototype = func.prototype;
      var self = new ctor;
      var result = func.apply(self, args.concat(slice.call(arguments)));
      if (Object(result) === result) return result;
      return self;
    };
  };

  // Bind all of an object's methods to that object. Useful for ensuring that
  // all callbacks defined on an object belong to it.
  _.bindAll = function(obj) {
    var funcs = slice.call(arguments, 1);
    if (funcs.length == 0) funcs = _.functions(obj);
    each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
    return obj;
  };

  // Memoize an expensive function by storing its results.
  _.memoize = function(func, hasher) {
    var memo = {};
    hasher || (hasher = _.identity);
    return function() {
      var key = hasher.apply(this, arguments);
      return hasOwnProperty.call(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
    };
  };

  // Delays a function for the given number of milliseconds, and then calls
  // it with the arguments supplied.
  _.delay = function(func, wait) {
    var args = slice.call(arguments, 2);
    return setTimeout(function(){ return func.apply(func, args); }, wait);
  };

  // Defers a function, scheduling it to run after the current call stack has
  // cleared.
  _.defer = function(func) {
    return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
  };

  // Returns a function, that, when invoked, will only be triggered at most once
  // during a given window of time.
  _.throttle = function(func, wait) {
    var context, args, timeout, throttling, more;
    var whenDone = _.debounce(function(){ more = throttling = false; }, wait);
    return function() {
      context = this; args = arguments;
      var later = function() {
        timeout = null;
        if (more) func.apply(context, args);
        whenDone();
      };
      if (!timeout) timeout = setTimeout(later, wait);
      if (throttling) {
        more = true;
      } else {
        func.apply(context, args);
      }
      whenDone();
      throttling = true;
    };
  };

  // Returns a function, that, as long as it continues to be invoked, will not
  // be triggered. The function will be called after it stops being called for
  // N milliseconds.
  _.debounce = function(func, wait) {
    var timeout;
    return function() {
      var context = this, args = arguments;
      var later = function() {
        timeout = null;
        func.apply(context, args);
      };
      clearTimeout(timeout);
      timeout = setTimeout(later, wait);
    };
  };

  // Returns a function that will be executed at most one time, no matter how
  // often you call it. Useful for lazy initialization.
  _.once = function(func) {
    var ran = false, memo;
    return function() {
      if (ran) return memo;
      ran = true;
      return memo = func.apply(this, arguments);
    };
  };

  // Returns the first function passed as an argument to the second,
  // allowing you to adjust arguments, run code before and after, and
  // conditionally execute the original function.
  _.wrap = function(func, wrapper) {
    return function() {
      var args = [func].concat(slice.call(arguments));
      return wrapper.apply(this, args);
    };
  };

  // Returns a function that is the composition of a list of functions, each
  // consuming the return value of the function that follows.
  _.compose = function() {
    var funcs = slice.call(arguments);
    return function() {
      var args = slice.call(arguments);
      for (var i = funcs.length - 1; i >= 0; i--) {
        args = [funcs[i].apply(this, args)];
      }
      return args[0];
    };
  };

  // Returns a function that will only be executed after being called N times.
  _.after = function(times, func) {
    if (times <= 0) return func();
    return function() {
      if (--times < 1) { return func.apply(this, arguments); }
    };
  };

  // Object Functions
  // ----------------

  // Retrieve the names of an object's properties.
  // Delegates to **ECMAScript 5**'s native `Object.keys`
  _.keys = nativeKeys || function(obj) {
    if (obj !== Object(obj)) throw new TypeError('Invalid object');
    var keys = [];
    for (var key in obj) if (hasOwnProperty.call(obj, key)) keys[keys.length] = key;
    return keys;
  };

  // Retrieve the values of an object's properties.
  _.values = function(obj) {
    return _.map(obj, _.identity);
  };

  // Return a sorted list of the function names available on the object.
  // Aliased as `methods`
  _.functions = _.methods = function(obj) {
    var names = [];
    for (var key in obj) {
      if (_.isFunction(obj[key])) names.push(key);
    }
    return names.sort();
  };

  // Extend a given object with all the properties in passed-in object(s).
  _.extend = function(obj) {
    each(slice.call(arguments, 1), function(source) {
      for (var prop in source) {
        if (source[prop] !== void 0) obj[prop] = source[prop];
      }
    });
    return obj;
  };

  // Fill in a given object with default properties.
  _.defaults = function(obj) {
    each(slice.call(arguments, 1), function(source) {
      for (var prop in source) {
        if (obj[prop] == null) obj[prop] = source[prop];
      }
    });
    return obj;
  };

  // Create a (shallow-cloned) duplicate of an object.
  _.clone = function(obj) {
    if (!_.isObject(obj)) return obj;
    return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
  };

  // Invokes interceptor with the obj, and then returns obj.
  // The primary purpose of this method is to "tap into" a method chain, in
  // order to perform operations on intermediate results within the chain.
  _.tap = function(obj, interceptor) {
    interceptor(obj);
    return obj;
  };

  // Internal recursive comparison function.
  function eq(a, b, stack) {
    // Identical objects are equal. `0 === -0`, but they aren't identical.
    // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
    if (a === b) return a !== 0 || 1 / a == 1 / b;
    // A strict comparison is necessary because `null == undefined`.
    if (a == null || b == null) return a === b;
    // Unwrap any wrapped objects.
    if (a._chain) a = a._wrapped;
    if (b._chain) b = b._wrapped;
    // Invoke a custom `isEqual` method if one is provided.
    if (_.isFunction(a.isEqual)) return a.isEqual(b);
    if (_.isFunction(b.isEqual)) return b.isEqual(a);
    // Compare `[[Class]]` names.
    var className = toString.call(a);
    if (className != toString.call(b)) return false;
    switch (className) {
      // Strings, numbers, dates, and booleans are compared by value.
      case '[object String]':
        // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
        // equivalent to `new String("5")`.
        return String(a) == String(b);
      case '[object Number]':
        a = +a;
        b = +b;
        // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
        // other numeric values.
        return a != a ? b != b : (a == 0 ? 1 / a == 1 / b : a == b);
      case '[object Date]':
      case '[object Boolean]':
        // Coerce dates and booleans to numeric primitive values. Dates are compared by their
        // millisecond representations. Note that invalid dates with millisecond representations
        // of `NaN` are not equivalent.
        return +a == +b;
      // RegExps are compared by their source patterns and flags.
      case '[object RegExp]':
        return a.source == b.source &&
               a.global == b.global &&
               a.multiline == b.multiline &&
               a.ignoreCase == b.ignoreCase;
    }
    if (typeof a != 'object' || typeof b != 'object') return false;
    // Assume equality for cyclic structures. The algorithm for detecting cyclic
    // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
    var length = stack.length;
    while (length--) {
      // Linear search. Performance is inversely proportional to the number of
      // unique nested structures.
      if (stack[length] == a) return true;
    }
    // Add the first object to the stack of traversed objects.
    stack.push(a);
    var size = 0, result = true;
    // Recursively compare objects and arrays.
    if (className == '[object Array]') {
      // Compare array lengths to determine if a deep comparison is necessary.
      size = a.length;
      result = size == b.length;
      if (result) {
        // Deep compare the contents, ignoring non-numeric properties.
        while (size--) {
          // Ensure commutative equality for sparse arrays.
          if (!(result = size in a == size in b && eq(a[size], b[size], stack))) break;
        }
      }
    } else {
      // Objects with different constructors are not equivalent.
      if ("constructor" in a != "constructor" in b || a.constructor != b.constructor) return false;
      // Deep compare objects.
      for (var key in a) {
        if (hasOwnProperty.call(a, key)) {
          // Count the expected number of properties.
          size++;
          // Deep compare each member.
          if (!(result = hasOwnProperty.call(b, key) && eq(a[key], b[key], stack))) break;
        }
      }
      // Ensure that both objects contain the same number of properties.
      if (result) {
        for (key in b) {
          if (hasOwnProperty.call(b, key) && !(size--)) break;
        }
        result = !size;
      }
    }
    // Remove the first object from the stack of traversed objects.
    stack.pop();
    return result;
  }

  // Perform a deep comparison to check if two objects are equal.
  _.isEqual = function(a, b) {
    return eq(a, b, []);
  };

  // Is a given array, string, or object empty?
  // An "empty" object has no enumerable own-properties.
  _.isEmpty = function(obj) {
    if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
    for (var key in obj) if (hasOwnProperty.call(obj, key)) return false;
    return true;
  };

  // Is a given value a DOM element?
  _.isElement = function(obj) {
    return !!(obj && obj.nodeType == 1);
  };

  // Is a given value an array?
  // Delegates to ECMA5's native Array.isArray
  _.isArray = nativeIsArray || function(obj) {
    return toString.call(obj) == '[object Array]';
  };

  // Is a given variable an object?
  _.isObject = function(obj) {
    return obj === Object(obj);
  };

  // Is a given variable an arguments object?
  if (toString.call(arguments) == '[object Arguments]') {
    _.isArguments = function(obj) {
      return toString.call(obj) == '[object Arguments]';
    };
  } else {
    _.isArguments = function(obj) {
      return !!(obj && hasOwnProperty.call(obj, 'callee'));
    };
  }

  // Is a given value a function?
  _.isFunction = function(obj) {
    return toString.call(obj) == '[object Function]';
  };

  // Is a given value a string?
  _.isString = function(obj) {
    return toString.call(obj) == '[object String]';
  };

  // Is a given value a number?
  _.isNumber = function(obj) {
    return toString.call(obj) == '[object Number]';
  };

  // Is the given value `NaN`?
  _.isNaN = function(obj) {
    // `NaN` is the only value for which `===` is not reflexive.
    return obj !== obj;
  };

  // Is a given value a boolean?
  _.isBoolean = function(obj) {
    return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
  };

  // Is a given value a date?
  _.isDate = function(obj) {
    return toString.call(obj) == '[object Date]';
  };

  // Is the given value a regular expression?
  _.isRegExp = function(obj) {
    return toString.call(obj) == '[object RegExp]';
  };

  // Is a given value equal to null?
  _.isNull = function(obj) {
    return obj === null;
  };

  // Is a given variable undefined?
  _.isUndefined = function(obj) {
    return obj === void 0;
  };

  // Utility Functions
  // -----------------

  // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
  // previous owner. Returns a reference to the Underscore object.
  _.noConflict = function() {
    root._ = previousUnderscore;
    return this;
  };

  // Keep the identity function around for default iterators.
  _.identity = function(value) {
    return value;
  };

  // Run a function **n** times.
  _.times = function (n, iterator, context) {
    for (var i = 0; i < n; i++) iterator.call(context, i);
  };

  // Escape a string for HTML interpolation.
  _.escape = function(string) {
    return (''+string).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#x27;').replace(/\//g,'&#x2F;');
  };

  // Add your own custom functions to the Underscore object, ensuring that
  // they're correctly added to the OOP wrapper as well.
  _.mixin = function(obj) {
    each(_.functions(obj), function(name){
      addToWrapper(name, _[name] = obj[name]);
    });
  };

  // Generate a unique integer id (unique within the entire client session).
  // Useful for temporary DOM ids.
  var idCounter = 0;
  _.uniqueId = function(prefix) {
    var id = idCounter++;
    return prefix ? prefix + id : id;
  };

  // By default, Underscore uses ERB-style template delimiters, change the
  // following template settings to use alternative delimiters.
  _.templateSettings = {
    evaluate    : /<%([\s\S]+?)%>/g,
    interpolate : /<%=([\s\S]+?)%>/g,
    escape      : /<%-([\s\S]+?)%>/g
  };

  // JavaScript micro-templating, similar to John Resig's implementation.
  // Underscore templating handles arbitrary delimiters, preserves whitespace,
  // and correctly escapes quotes within interpolated code.
  _.template = function(str, data) {
    var c  = _.templateSettings;
    var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' +
      'with(obj||{}){__p.push(\'' +
      str.replace(/\\/g, '\\\\')
         .replace(/'/g, "\\'")
         .replace(c.escape, function(match, code) {
           return "',_.escape(" + code.replace(/\\'/g, "'") + "),'";
         })
         .replace(c.interpolate, function(match, code) {
           return "'," + code.replace(/\\'/g, "'") + ",'";
         })
         .replace(c.evaluate || null, function(match, code) {
           return "');" + code.replace(/\\'/g, "'")
                              .replace(/[\r\n\t]/g, ' ') + ";__p.push('";
         })
         .replace(/\r/g, '\\r')
         .replace(/\n/g, '\\n')
         .replace(/\t/g, '\\t')
         + "');}return __p.join('');";
    var func = new Function('obj', '_', tmpl);
    return data ? func(data, _) : function(data) { return func(data, _) };
  };

  // The OOP Wrapper
  // ---------------

  // If Underscore is called as a function, it returns a wrapped object that
  // can be used OO-style. This wrapper holds altered versions of all the
  // underscore functions. Wrapped objects may be chained.
  var wrapper = function(obj) { this._wrapped = obj; };

  // Expose `wrapper.prototype` as `_.prototype`
  _.prototype = wrapper.prototype;

  // Helper function to continue chaining intermediate results.
  var result = function(obj, chain) {
    return chain ? _(obj).chain() : obj;
  };

  // A method to easily add functions to the OOP wrapper.
  var addToWrapper = function(name, func) {
    wrapper.prototype[name] = function() {
      var args = slice.call(arguments);
      unshift.call(args, this._wrapped);
      return result(func.apply(_, args), this._chain);
    };
  };

  // Add all of the Underscore functions to the wrapper object.
  _.mixin(_);

  // Add all mutator Array functions to the wrapper.
  each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
    var method = ArrayProto[name];
    wrapper.prototype[name] = function() {
      method.apply(this._wrapped, arguments);
      return result(this._wrapped, this._chain);
    };
  });

  // Add all accessor Array functions to the wrapper.
  each(['concat', 'join', 'slice'], function(name) {
    var method = ArrayProto[name];
    wrapper.prototype[name] = function() {
      return result(method.apply(this._wrapped, arguments), this._chain);
    };
  });

  // Start chaining a wrapped Underscore object.
  wrapper.prototype.chain = function() {
    this._chain = true;
    return this;
  };

  // Extracts the result from a wrapped and chained object.
  wrapper.prototype.value = function() {
    return this._wrapped;
  };

}).call(this);
/*
  mustache.js — Logic-less templates in JavaScript

  See http://mustache.github.com/ for more info.
*/


var Mustache = function() {
  var Renderer = function() {};

  Renderer.prototype = {
    otag: "{{",
    ctag: "}}",
    pragmas: {},
    buffer: [],
    pragmas_implemented: {
      "IMPLICIT-ITERATOR": true
    },
    context: {},

    render: function(template, context, partials, in_recursion) {
      // reset buffer & set context
      if(!in_recursion) {
        this.context = context;
        this.buffer = []; // TODO: make this non-lazy
      }

      // fail fast
      if(!this.includes("", template)) {
        if(in_recursion) {
          return template;
        } else {
          this.send(template);
          return;
        }
      }

      template = this.render_pragmas(template);
      var html = this.render_section(template, context, partials);
      if(in_recursion) {
        return this.render_tags(html, context, partials, in_recursion);
      }

      this.render_tags(html, context, partials, in_recursion);
    },

    /*
      Sends parsed lines
    */
    send: function(line) {
      if(line != "") {
        this.buffer.push(line);
      }
    },

    /*
      Looks for %PRAGMAS
    */
    render_pragmas: function(template) {
      // no pragmas
      if(!this.includes("%", template)) {
        return template;
      }

      var that = this;
      var regex = new RegExp(this.otag + "%([\\w-]+) ?([\\w]+=[\\w]+)?" +
            this.ctag);
      return template.replace(regex, function(match, pragma, options) {
        if(!that.pragmas_implemented[pragma]) {
          throw({message: 
            "This implementation of mustache doesn't understand the '" +
            pragma + "' pragma"});
        }
        that.pragmas[pragma] = {};
        if(options) {
          var opts = options.split("=");
          that.pragmas[pragma][opts[0]] = opts[1];
        }
        return "";
        // ignore unknown pragmas silently
      });
    },

    /*
      Tries to find a partial in the curent scope and render it
    */
    render_partial: function(name, context, partials) {
      name = this.trim(name);
      if(!partials || partials[name] === undefined) {
        throw({message: "unknown_partial '" + name + "'"});
      }
      if(typeof(context[name]) != "object") {
        return this.render(partials[name], context, partials, true);
      }
      return this.render(partials[name], context[name], partials, true);
    },

    /*
      Renders inverted (^) and normal (#) sections
    */
    render_section: function(template, context, partials) {
      if(!this.includes("#", template) && !this.includes("^", template)) {
        return template;
      }

      var that = this;
      // CSW - Added "+?" so it finds the tighest bound, not the widest
      var regex = new RegExp(this.otag + "(\\^|\\#)\\s*(.+)\\s*" + this.ctag +
              "\n*([\\s\\S]+?)" + this.otag + "\\/\\s*\\2\\s*" + this.ctag +
              "\\s*", "mg");

      // for each {{#foo}}{{/foo}} section do...
      return template.replace(regex, function(match, type, name, content) {
        var value = that.find(name, context);
        if(type == "^") { // inverted section
          if(!value || that.is_array(value) && value.length === 0) {
            // false or empty list, render it
            return that.render(content, context, partials, true);
          } else {
            return "";
          }
        } else if(type == "#") { // normal section
          if(that.is_array(value)) { // Enumerable, Let's loop!
            return that.map(value, function(row) {
              return that.render(content, that.create_context(row),
                partials, true);
            }).join("");
          } else if(that.is_object(value)) { // Object, Use it as subcontext!
            return that.render(content, that.create_context(value),
              partials, true);
          } else if(typeof value === "function") {
            // higher order section
            return value.call(context, content, function(text) {
              return that.render(text, context, partials, true);
            });
          } else if(value) { // boolean section
            return that.render(content, context, partials, true);
          } else {
            return "";
          }
        }
      });
    },

    /*
      Replace {{foo}} and friends with values from our view
    */
    render_tags: function(template, context, partials, in_recursion) {
      // tit for tat
      var that = this;

      var new_regex = function() {
        return new RegExp(that.otag + "(=|!|>|\\{|%)?([^\\/#\\^]+?)\\1?" +
          that.ctag + "+", "g");
      };

      var regex = new_regex();
      var tag_replace_callback = function(match, operator, name) {
        switch(operator) {
        case "!": // ignore comments
          return "";
        case "=": // set new delimiters, rebuild the replace regexp
          that.set_delimiters(name);
          regex = new_regex();
          return "";
        case ">": // render partial
          return that.render_partial(name, context, partials);
        case "{": // the triple mustache is unescaped
          return that.find(name, context);
        default: // escape the value
          return that.escape(that.find(name, context));
        }
      };
      var lines = template.split("\n");
      for(var i = 0; i < lines.length; i++) {
        lines[i] = lines[i].replace(regex, tag_replace_callback, this);
        if(!in_recursion) {
          this.send(lines[i]);
        }
      }

      if(in_recursion) {
        return lines.join("\n");
      }
    },

    set_delimiters: function(delimiters) {
      var dels = delimiters.split(" ");
      this.otag = this.escape_regex(dels[0]);
      this.ctag = this.escape_regex(dels[1]);
    },

    escape_regex: function(text) {
      // thank you Simon Willison
      if(!arguments.callee.sRE) {
        var specials = [
          '/', '.', '*', '+', '?', '|',
          '(', ')', '[', ']', '{', '}', '\\'
        ];
        arguments.callee.sRE = new RegExp(
          '(\\' + specials.join('|\\') + ')', 'g'
        );
      }
      return text.replace(arguments.callee.sRE, '\\$1');
    },

    /*
      find `name` in current `context`. That is find me a value
      from the view object
    */
    find: function(name, context) {
      name = this.trim(name);

      // Checks whether a value is thruthy or false or 0
      function is_kinda_truthy(bool) {
        return bool === false || bool === 0 || bool;
      }

      var value;
      if(is_kinda_truthy(context[name])) {
        value = context[name];
      } else if(is_kinda_truthy(this.context[name])) {
        value = this.context[name];
      }

      if(typeof value === "function") {
        return value.apply(context);
      }
      if(value !== undefined) {
        return value;
      }
      // silently ignore unkown variables
      return "";
    },

    // Utility methods

    /* includes tag */
    includes: function(needle, haystack) {
      return haystack.indexOf(this.otag + needle) != -1;
    },

    /*
      Does away with nasty characters
    */
    escape: function(s) {
      s = String(s === null ? "" : s);
      return s.replace(/&(?!\w+;)|["'<>\\]/g, function(s) {
        switch(s) {
        case "&": return "&amp;";
        case "\\": return "\\\\";
        case '"': return '&quot;';
        case "'": return '&#39;';
        case "<": return "&lt;";
        case ">": return "&gt;";
        default: return s;
        }
      });
    },

    // by @langalex, support for arrays of strings
    create_context: function(_context) {
      if(this.is_object(_context)) {
        return _context;
      } else {
        var iterator = ".";
        if(this.pragmas["IMPLICIT-ITERATOR"]) {
          iterator = this.pragmas["IMPLICIT-ITERATOR"].iterator;
        }
        var ctx = {};
        ctx[iterator] = _context;
        return ctx;
      }
    },

    is_object: function(a) {
      return a && typeof a == "object";
    },

    is_array: function(a) {
      return Object.prototype.toString.call(a) === '[object Array]';
    },

    /*
      Gets rid of leading and trailing whitespace
    */
    trim: function(s) {
      return s.replace(/^\s*|\s*$/g, "");
    },

    /*
      Why, why, why? Because IE. Cry, cry cry.
    */
    map: function(array, fn) {
      if (typeof array.map == "function") {
        return array.map(fn);
      } else {
        var r = [];
        var l = array.length;
        for(var i = 0; i < l; i++) {
          r.push(fn(array[i]));
        }
        return r;
      }
    }
  };

  return({
    name: "mustache.js",
    version: "0.3.1-dev",

    /*
      Turns a template and view into HTML
    */
    to_html: function(template, view, partials, send_fun) {
      var renderer = new Renderer();
      if(send_fun) {
        renderer.send = send_fun;
      }
      renderer.render(template, view, partials);
      if(!send_fun) {
        return renderer.buffer.join("\n");
      }
    }
  });
}();
(function() {
  _.mixin({
    mustache: function(template, view, partials) {
      return Mustache.to_html(template, view, partials);
    }
  });
}).call(this);
/**
 * Version: 1.0 Alpha-1 
 * Build Date: 13-Nov-2007
 * Copyright (c) 2006-2007, Coolite Inc. (http://www.coolite.com/). All rights reserved.
 * License: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/. 
 * Website: http://www.datejs.com/ or http://www.coolite.com/datejs/
 */

Date.CultureInfo={name:"en-US",englishName:"English (United States)",nativeName:"English (United States)",dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],abbreviatedDayNames:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],shortestDayNames:["Su","Mo","Tu","We","Th","Fr","Sa"],firstLetterDayNames:["S","M","T","W","T","F","S"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],abbreviatedMonthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],amDesignator:"AM",pmDesignator:"PM",firstDayOfWeek:0,twoDigitYearMax:2029,dateElementOrder:"mdy",formatPatterns:{shortDate:"M/d/yyyy",longDate:"dddd, MMMM dd, yyyy",shortTime:"h:mm tt",longTime:"h:mm:ss tt",fullDateTime:"dddd, MMMM dd, yyyy h:mm:ss tt",sortableDateTime:"yyyy-MM-ddTHH:mm:ss",universalSortableDateTime:"yyyy-MM-dd HH:mm:ssZ",rfc1123:"ddd, dd MMM yyyy HH:mm:ss GMT",monthDay:"MMMM dd",yearMonth:"MMMM, yyyy"},regexPatterns:{jan:/^jan(uary)?/i,feb:/^feb(ruary)?/i,mar:/^mar(ch)?/i,apr:/^apr(il)?/i,may:/^may/i,jun:/^jun(e)?/i,jul:/^jul(y)?/i,aug:/^aug(ust)?/i,sep:/^sep(t(ember)?)?/i,oct:/^oct(ober)?/i,nov:/^nov(ember)?/i,dec:/^dec(ember)?/i,sun:/^su(n(day)?)?/i,mon:/^mo(n(day)?)?/i,tue:/^tu(e(s(day)?)?)?/i,wed:/^we(d(nesday)?)?/i,thu:/^th(u(r(s(day)?)?)?)?/i,fri:/^fr(i(day)?)?/i,sat:/^sa(t(urday)?)?/i,future:/^next/i,past:/^last|past|prev(ious)?/i,add:/^(\+|after|from)/i,subtract:/^(\-|before|ago)/i,yesterday:/^yesterday/i,today:/^t(oday)?/i,tomorrow:/^tomorrow/i,now:/^n(ow)?/i,millisecond:/^ms|milli(second)?s?/i,second:/^sec(ond)?s?/i,minute:/^min(ute)?s?/i,hour:/^h(ou)?rs?/i,week:/^w(ee)?k/i,month:/^m(o(nth)?s?)?/i,day:/^d(ays?)?/i,year:/^y((ea)?rs?)?/i,shortMeridian:/^(a|p)/i,longMeridian:/^(a\.?m?\.?|p\.?m?\.?)/i,timezone:/^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\s*(\+|\-)\s*\d\d\d\d?)|gmt)/i,ordinalSuffix:/^\s*(st|nd|rd|th)/i,timeContext:/^\s*(\:|a|p)/i},abbreviatedTimeZoneStandard:{GMT:"-000",EST:"-0400",CST:"-0500",MST:"-0600",PST:"-0700"},abbreviatedTimeZoneDST:{GMT:"-000",EDT:"-0500",CDT:"-0600",MDT:"-0700",PDT:"-0800"}};
Date.getMonthNumberFromName=function(name){var n=Date.CultureInfo.monthNames,m=Date.CultureInfo.abbreviatedMonthNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
return-1;};Date.getDayNumberFromName=function(name){var n=Date.CultureInfo.dayNames,m=Date.CultureInfo.abbreviatedDayNames,o=Date.CultureInfo.shortestDayNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
return-1;};Date.isLeapYear=function(year){return(((year%4===0)&&(year%100!==0))||(year%400===0));};Date.getDaysInMonth=function(year,month){return[31,(Date.isLeapYear(year)?29:28),31,30,31,30,31,31,30,31,30,31][month];};Date.getTimezoneOffset=function(s,dst){return(dst||false)?Date.CultureInfo.abbreviatedTimeZoneDST[s.toUpperCase()]:Date.CultureInfo.abbreviatedTimeZoneStandard[s.toUpperCase()];};Date.getTimezoneAbbreviation=function(offset,dst){var n=(dst||false)?Date.CultureInfo.abbreviatedTimeZoneDST:Date.CultureInfo.abbreviatedTimeZoneStandard,p;for(p in n){if(n[p]===offset){return p;}}
return null;};Date.prototype.clone=function(){return new Date(this.getTime());};Date.prototype.compareTo=function(date){if(isNaN(this)){throw new Error(this);}
if(date instanceof Date&&!isNaN(date)){return(this>date)?1:(this<date)?-1:0;}else{throw new TypeError(date);}};Date.prototype.equals=function(date){return(this.compareTo(date)===0);};Date.prototype.between=function(start,end){var t=this.getTime();return t>=start.getTime()&&t<=end.getTime();};Date.prototype.addMilliseconds=function(value){this.setMilliseconds(this.getMilliseconds()+value);return this;};Date.prototype.addSeconds=function(value){return this.addMilliseconds(value*1000);};Date.prototype.addMinutes=function(value){return this.addMilliseconds(value*60000);};Date.prototype.addHours=function(value){return this.addMilliseconds(value*3600000);};Date.prototype.addDays=function(value){return this.addMilliseconds(value*86400000);};Date.prototype.addWeeks=function(value){return this.addMilliseconds(value*604800000);};Date.prototype.addMonths=function(value){var n=this.getDate();this.setDate(1);this.setMonth(this.getMonth()+value);this.setDate(Math.min(n,this.getDaysInMonth()));return this;};Date.prototype.addYears=function(value){return this.addMonths(value*12);};Date.prototype.add=function(config){if(typeof config=="number"){this._orient=config;return this;}
var x=config;if(x.millisecond||x.milliseconds){this.addMilliseconds(x.millisecond||x.milliseconds);}
if(x.second||x.seconds){this.addSeconds(x.second||x.seconds);}
if(x.minute||x.minutes){this.addMinutes(x.minute||x.minutes);}
if(x.hour||x.hours){this.addHours(x.hour||x.hours);}
if(x.month||x.months){this.addMonths(x.month||x.months);}
if(x.year||x.years){this.addYears(x.year||x.years);}
if(x.day||x.days){this.addDays(x.day||x.days);}
return this;};Date._validate=function(value,min,max,name){if(typeof value!="number"){throw new TypeError(value+" is not a Number.");}else if(value<min||value>max){throw new RangeError(value+" is not a valid value for "+name+".");}
return true;};Date.validateMillisecond=function(n){return Date._validate(n,0,999,"milliseconds");};Date.validateSecond=function(n){return Date._validate(n,0,59,"seconds");};Date.validateMinute=function(n){return Date._validate(n,0,59,"minutes");};Date.validateHour=function(n){return Date._validate(n,0,23,"hours");};Date.validateDay=function(n,year,month){return Date._validate(n,1,Date.getDaysInMonth(year,month),"days");};Date.validateMonth=function(n){return Date._validate(n,0,11,"months");};Date.validateYear=function(n){return Date._validate(n,1,9999,"seconds");};Date.prototype.set=function(config){var x=config;if(!x.millisecond&&x.millisecond!==0){x.millisecond=-1;}
if(!x.second&&x.second!==0){x.second=-1;}
if(!x.minute&&x.minute!==0){x.minute=-1;}
if(!x.hour&&x.hour!==0){x.hour=-1;}
if(!x.day&&x.day!==0){x.day=-1;}
if(!x.month&&x.month!==0){x.month=-1;}
if(!x.year&&x.year!==0){x.year=-1;}
if(x.millisecond!=-1&&Date.validateMillisecond(x.millisecond)){this.addMilliseconds(x.millisecond-this.getMilliseconds());}
if(x.second!=-1&&Date.validateSecond(x.second)){this.addSeconds(x.second-this.getSeconds());}
if(x.minute!=-1&&Date.validateMinute(x.minute)){this.addMinutes(x.minute-this.getMinutes());}
if(x.hour!=-1&&Date.validateHour(x.hour)){this.addHours(x.hour-this.getHours());}
if(x.month!==-1&&Date.validateMonth(x.month)){this.addMonths(x.month-this.getMonth());}
if(x.year!=-1&&Date.validateYear(x.year)){this.addYears(x.year-this.getFullYear());}
if(x.day!=-1&&Date.validateDay(x.day,this.getFullYear(),this.getMonth())){this.addDays(x.day-this.getDate());}
if(x.timezone){this.setTimezone(x.timezone);}
if(x.timezoneOffset){this.setTimezoneOffset(x.timezoneOffset);}
return this;};Date.prototype.clearTime=function(){this.setHours(0);this.setMinutes(0);this.setSeconds(0);this.setMilliseconds(0);return this;};Date.prototype.isLeapYear=function(){var y=this.getFullYear();return(((y%4===0)&&(y%100!==0))||(y%400===0));};Date.prototype.isWeekday=function(){return!(this.is().sat()||this.is().sun());};Date.prototype.getDaysInMonth=function(){return Date.getDaysInMonth(this.getFullYear(),this.getMonth());};Date.prototype.moveToFirstDayOfMonth=function(){return this.set({day:1});};Date.prototype.moveToLastDayOfMonth=function(){return this.set({day:this.getDaysInMonth()});};Date.prototype.moveToDayOfWeek=function(day,orient){var diff=(day-this.getDay()+7*(orient||+1))%7;return this.addDays((diff===0)?diff+=7*(orient||+1):diff);};Date.prototype.moveToMonth=function(month,orient){var diff=(month-this.getMonth()+12*(orient||+1))%12;return this.addMonths((diff===0)?diff+=12*(orient||+1):diff);};Date.prototype.getDayOfYear=function(){return Math.floor((this-new Date(this.getFullYear(),0,1))/86400000);};Date.prototype.getWeekOfYear=function(firstDayOfWeek){var y=this.getFullYear(),m=this.getMonth(),d=this.getDate();var dow=firstDayOfWeek||Date.CultureInfo.firstDayOfWeek;var offset=7+1-new Date(y,0,1).getDay();if(offset==8){offset=1;}
var daynum=((Date.UTC(y,m,d,0,0,0)-Date.UTC(y,0,1,0,0,0))/86400000)+1;var w=Math.floor((daynum-offset+7)/7);if(w===dow){y--;var prevOffset=7+1-new Date(y,0,1).getDay();if(prevOffset==2||prevOffset==8){w=53;}else{w=52;}}
return w;};Date.prototype.isDST=function(){console.log('isDST');return this.toString().match(/(E|C|M|P)(S|D)T/)[2]=="D";};Date.prototype.getTimezone=function(){return Date.getTimezoneAbbreviation(this.getUTCOffset,this.isDST());};Date.prototype.setTimezoneOffset=function(s){var here=this.getTimezoneOffset(),there=Number(s)*-6/10;this.addMinutes(there-here);return this;};Date.prototype.setTimezone=function(s){return this.setTimezoneOffset(Date.getTimezoneOffset(s));};Date.prototype.getUTCOffset=function(){var n=this.getTimezoneOffset()*-10/6,r;if(n<0){r=(n-10000).toString();return r[0]+r.substr(2);}else{r=(n+10000).toString();return"+"+r.substr(1);}};Date.prototype.getDayName=function(abbrev){return abbrev?Date.CultureInfo.abbreviatedDayNames[this.getDay()]:Date.CultureInfo.dayNames[this.getDay()];};Date.prototype.getMonthName=function(abbrev){return abbrev?Date.CultureInfo.abbreviatedMonthNames[this.getMonth()]:Date.CultureInfo.monthNames[this.getMonth()];};Date.prototype._toString=Date.prototype.toString;Date.prototype.toString=function(format){var self=this;var p=function p(s){return(s.toString().length==1)?"0"+s:s;};return format?format.replace(/dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?/g,function(format){switch(format){case"hh":return p(self.getHours()<13?self.getHours():(self.getHours()-12));case"h":return self.getHours()<13?self.getHours():(self.getHours()-12);case"HH":return p(self.getHours());case"H":return self.getHours();case"mm":return p(self.getMinutes());case"m":return self.getMinutes();case"ss":return p(self.getSeconds());case"s":return self.getSeconds();case"yyyy":return self.getFullYear();case"yy":return self.getFullYear().toString().substring(2,4);case"dddd":return self.getDayName();case"ddd":return self.getDayName(true);case"dd":return p(self.getDate());case"d":return self.getDate().toString();case"MMMM":return self.getMonthName();case"MMM":return self.getMonthName(true);case"MM":return p((self.getMonth()+1));case"M":return self.getMonth()+1;case"t":return self.getHours()<12?Date.CultureInfo.amDesignator.substring(0,1):Date.CultureInfo.pmDesignator.substring(0,1);case"tt":return self.getHours()<12?Date.CultureInfo.amDesignator:Date.CultureInfo.pmDesignator;case"zzz":case"zz":case"z":return"";}}):this._toString();};
Date.now=function(){return new Date();};Date.today=function(){return Date.now().clearTime();};Date.prototype._orient=+1;Date.prototype.next=function(){this._orient=+1;return this;};Date.prototype.last=Date.prototype.prev=Date.prototype.previous=function(){this._orient=-1;return this;};Date.prototype._is=false;Date.prototype.is=function(){this._is=true;return this;};Number.prototype._dateElement="day";Number.prototype.fromNow=function(){var c={};c[this._dateElement]=this;return Date.now().add(c);};Number.prototype.ago=function(){var c={};c[this._dateElement]=this*-1;return Date.now().add(c);};(function(){var $D=Date.prototype,$N=Number.prototype;var dx=("sunday monday tuesday wednesday thursday friday saturday").split(/\s/),mx=("january february march april may june july august september october november december").split(/\s/),px=("Millisecond Second Minute Hour Day Week Month Year").split(/\s/),de;var df=function(n){return function(){if(this._is){this._is=false;return this.getDay()==n;}
return this.moveToDayOfWeek(n,this._orient);};};for(var i=0;i<dx.length;i++){$D[dx[i]]=$D[dx[i].substring(0,3)]=df(i);}
var mf=function(n){return function(){if(this._is){this._is=false;return this.getMonth()===n;}
return this.moveToMonth(n,this._orient);};};for(var j=0;j<mx.length;j++){$D[mx[j]]=$D[mx[j].substring(0,3)]=mf(j);}
var ef=function(j){return function(){if(j.substring(j.length-1)!="s"){j+="s";}
return this["add"+j](this._orient);};};var nf=function(n){return function(){this._dateElement=n;return this;};};for(var k=0;k<px.length;k++){de=px[k].toLowerCase();$D[de]=$D[de+"s"]=ef(px[k]);$N[de]=$N[de+"s"]=nf(de);}}());Date.prototype.toJSONString=function(){return this.toString("yyyy-MM-ddThh:mm:ssZ");};Date.prototype.toShortDateString=function(){return this.toString(Date.CultureInfo.formatPatterns.shortDatePattern);};Date.prototype.toLongDateString=function(){return this.toString(Date.CultureInfo.formatPatterns.longDatePattern);};Date.prototype.toShortTimeString=function(){return this.toString(Date.CultureInfo.formatPatterns.shortTimePattern);};Date.prototype.toLongTimeString=function(){return this.toString(Date.CultureInfo.formatPatterns.longTimePattern);};Date.prototype.getOrdinal=function(){switch(this.getDate()){case 1:case 21:case 31:return"st";case 2:case 22:return"nd";case 3:case 23:return"rd";default:return"th";}};
(function(){Date.Parsing={Exception:function(s){this.message="Parse error at '"+s.substring(0,10)+" ...'";}};var $P=Date.Parsing;var _=$P.Operators={rtoken:function(r){return function(s){var mx=s.match(r);if(mx){return([mx[0],s.substring(mx[0].length)]);}else{throw new $P.Exception(s);}};},token:function(s){return function(s){return _.rtoken(new RegExp("^\s*"+s+"\s*"))(s);};},stoken:function(s){return _.rtoken(new RegExp("^"+s));},until:function(p){return function(s){var qx=[],rx=null;while(s.length){try{rx=p.call(this,s);}catch(e){qx.push(rx[0]);s=rx[1];continue;}
break;}
return[qx,s];};},many:function(p){return function(s){var rx=[],r=null;while(s.length){try{r=p.call(this,s);}catch(e){return[rx,s];}
rx.push(r[0]);s=r[1];}
return[rx,s];};},optional:function(p){return function(s){var r=null;try{r=p.call(this,s);}catch(e){return[null,s];}
return[r[0],r[1]];};},not:function(p){return function(s){try{p.call(this,s);}catch(e){return[null,s];}
throw new $P.Exception(s);};},ignore:function(p){return p?function(s){var r=null;r=p.call(this,s);return[null,r[1]];}:null;},product:function(){var px=arguments[0],qx=Array.prototype.slice.call(arguments,1),rx=[];for(var i=0;i<px.length;i++){rx.push(_.each(px[i],qx));}
return rx;},cache:function(rule){var cache={},r=null;return function(s){try{r=cache[s]=(cache[s]||rule.call(this,s));}catch(e){r=cache[s]=e;}
if(r instanceof $P.Exception){throw r;}else{return r;}};},any:function(){var px=arguments;return function(s){var r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;}
try{r=(px[i].call(this,s));}catch(e){r=null;}
if(r){return r;}}
throw new $P.Exception(s);};},each:function(){var px=arguments;return function(s){var rx=[],r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;}
try{r=(px[i].call(this,s));}catch(e){throw new $P.Exception(s);}
rx.push(r[0]);s=r[1];}
return[rx,s];};},all:function(){var px=arguments,_=_;return _.each(_.optional(px));},sequence:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;if(px.length==1){return px[0];}
return function(s){var r=null,q=null;var rx=[];for(var i=0;i<px.length;i++){try{r=px[i].call(this,s);}catch(e){break;}
rx.push(r[0]);try{q=d.call(this,r[1]);}catch(ex){q=null;break;}
s=q[1];}
if(!r){throw new $P.Exception(s);}
if(q){throw new $P.Exception(q[1]);}
if(c){try{r=c.call(this,r[1]);}catch(ey){throw new $P.Exception(r[1]);}}
return[rx,(r?r[1]:s)];};},between:function(d1,p,d2){d2=d2||d1;var _fn=_.each(_.ignore(d1),p,_.ignore(d2));return function(s){var rx=_fn.call(this,s);return[[rx[0][0],r[0][2]],rx[1]];};},list:function(p,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return(p instanceof Array?_.each(_.product(p.slice(0,-1),_.ignore(d)),p.slice(-1),_.ignore(c)):_.each(_.many(_.each(p,_.ignore(d))),px,_.ignore(c)));},set:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return function(s){var r=null,p=null,q=null,rx=null,best=[[],s],last=false;for(var i=0;i<px.length;i++){q=null;p=null;r=null;last=(px.length==1);try{r=px[i].call(this,s);}catch(e){continue;}
rx=[[r[0]],r[1]];if(r[1].length>0&&!last){try{q=d.call(this,r[1]);}catch(ex){last=true;}}else{last=true;}
if(!last&&q[1].length===0){last=true;}
if(!last){var qx=[];for(var j=0;j<px.length;j++){if(i!=j){qx.push(px[j]);}}
p=_.set(qx,d).call(this,q[1]);if(p[0].length>0){rx[0]=rx[0].concat(p[0]);rx[1]=p[1];}}
if(rx[1].length<best[1].length){best=rx;}
if(best[1].length===0){break;}}
if(best[0].length===0){return best;}
if(c){try{q=c.call(this,best[1]);}catch(ey){throw new $P.Exception(best[1]);}
best[1]=q[1];}
return best;};},forward:function(gr,fname){return function(s){return gr[fname].call(this,s);};},replace:function(rule,repl){return function(s){var r=rule.call(this,s);return[repl,r[1]];};},process:function(rule,fn){return function(s){var r=rule.call(this,s);return[fn.call(this,r[0]),r[1]];};},min:function(min,rule){return function(s){var rx=rule.call(this,s);if(rx[0].length<min){throw new $P.Exception(s);}
return rx;};}};var _generator=function(op){return function(){var args=null,rx=[];if(arguments.length>1){args=Array.prototype.slice.call(arguments);}else if(arguments[0]instanceof Array){args=arguments[0];}
if(args){for(var i=0,px=args.shift();i<px.length;i++){args.unshift(px[i]);rx.push(op.apply(null,args));args.shift();return rx;}}else{return op.apply(null,arguments);}};};var gx="optional not ignore cache".split(/\s/);for(var i=0;i<gx.length;i++){_[gx[i]]=_generator(_[gx[i]]);}
var _vector=function(op){return function(){if(arguments[0]instanceof Array){return op.apply(null,arguments[0]);}else{return op.apply(null,arguments);}};};var vx="each any all".split(/\s/);for(var j=0;j<vx.length;j++){_[vx[j]]=_vector(_[vx[j]]);}}());(function(){var flattenAndCompact=function(ax){var rx=[];for(var i=0;i<ax.length;i++){if(ax[i]instanceof Array){rx=rx.concat(flattenAndCompact(ax[i]));}else{if(ax[i]){rx.push(ax[i]);}}}
return rx;};Date.Grammar={};Date.Translator={hour:function(s){return function(){this.hour=Number(s);};},minute:function(s){return function(){this.minute=Number(s);};},second:function(s){return function(){this.second=Number(s);};},meridian:function(s){return function(){this.meridian=s.slice(0,1).toLowerCase();};},timezone:function(s){return function(){var n=s.replace(/[^\d\+\-]/g,"");if(n.length){this.timezoneOffset=Number(n);}else{this.timezone=s.toLowerCase();}};},day:function(x){var s=x[0];return function(){this.day=Number(s.match(/\d+/)[0]);};},month:function(s){return function(){this.month=((s.length==3)?Date.getMonthNumberFromName(s):(Number(s)-1));};},year:function(s){return function(){var n=Number(s);this.year=((s.length>2)?n:(n+(((n+2000)<Date.CultureInfo.twoDigitYearMax)?2000:1900)));};},rday:function(s){return function(){switch(s){case"yesterday":this.days=-1;break;case"tomorrow":this.days=1;break;case"today":this.days=0;break;case"now":this.days=0;this.now=true;break;}};},finishExact:function(x){x=(x instanceof Array)?x:[x];var now=new Date();this.year=now.getFullYear();this.month=now.getMonth();this.day=1;this.hour=0;this.minute=0;this.second=0;for(var i=0;i<x.length;i++){if(x[i]){x[i].call(this);}}
this.hour=(this.meridian=="p"&&this.hour<13)?this.hour+12:this.hour;if(this.day>Date.getDaysInMonth(this.year,this.month)){throw new RangeError(this.day+" is not a valid value for days.");}
var r=new Date(this.year,this.month,this.day,this.hour,this.minute,this.second);if(this.timezone){r.set({timezone:this.timezone});}else if(this.timezoneOffset){r.set({timezoneOffset:this.timezoneOffset});}
return r;},finish:function(x){x=(x instanceof Array)?flattenAndCompact(x):[x];if(x.length===0){return null;}
for(var i=0;i<x.length;i++){if(typeof x[i]=="function"){x[i].call(this);}}
if(this.now){return new Date();}
var today=Date.today();var method=null;var expression=!!(this.days!=null||this.orient||this.operator);if(expression){var gap,mod,orient;orient=((this.orient=="past"||this.operator=="subtract")?-1:1);if(this.weekday){this.unit="day";gap=(Date.getDayNumberFromName(this.weekday)-today.getDay());mod=7;this.days=gap?((gap+(orient*mod))%mod):(orient*mod);}
if(this.month){this.unit="month";gap=(this.month-today.getMonth());mod=12;this.months=gap?((gap+(orient*mod))%mod):(orient*mod);this.month=null;}
if(!this.unit){this.unit="day";}
if(this[this.unit+"s"]==null||this.operator!=null){if(!this.value){this.value=1;}
if(this.unit=="week"){this.unit="day";this.value=this.value*7;}
this[this.unit+"s"]=this.value*orient;}
return today.add(this);}else{if(this.meridian&&this.hour){this.hour=(this.hour<13&&this.meridian=="p")?this.hour+12:this.hour;}
if(this.weekday&&!this.day){this.day=(today.addDays((Date.getDayNumberFromName(this.weekday)-today.getDay()))).getDate();}
if(this.month&&!this.day){this.day=1;}
return today.set(this);}}};var _=Date.Parsing.Operators,g=Date.Grammar,t=Date.Translator,_fn;g.datePartDelimiter=_.rtoken(/^([\s\-\.\,\/\x27]+)/);g.timePartDelimiter=_.stoken(":");g.whiteSpace=_.rtoken(/^\s*/);g.generalDelimiter=_.rtoken(/^(([\s\,]|at|on)+)/);var _C={};g.ctoken=function(keys){var fn=_C[keys];if(!fn){var c=Date.CultureInfo.regexPatterns;var kx=keys.split(/\s+/),px=[];for(var i=0;i<kx.length;i++){px.push(_.replace(_.rtoken(c[kx[i]]),kx[i]));}
fn=_C[keys]=_.any.apply(null,px);}
return fn;};g.ctoken2=function(key){return _.rtoken(Date.CultureInfo.regexPatterns[key]);};g.h=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2]|[1-9])/),t.hour));g.hh=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2])/),t.hour));g.H=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3]|[0-9])/),t.hour));g.HH=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3])/),t.hour));g.m=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.minute));g.mm=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.minute));g.s=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.second));g.ss=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.second));g.hms=_.cache(_.sequence([g.H,g.mm,g.ss],g.timePartDelimiter));g.t=_.cache(_.process(g.ctoken2("shortMeridian"),t.meridian));g.tt=_.cache(_.process(g.ctoken2("longMeridian"),t.meridian));g.z=_.cache(_.process(_.rtoken(/^(\+|\-)?\s*\d\d\d\d?/),t.timezone));g.zz=_.cache(_.process(_.rtoken(/^(\+|\-)\s*\d\d\d\d/),t.timezone));g.zzz=_.cache(_.process(g.ctoken2("timezone"),t.timezone));g.timeSuffix=_.each(_.ignore(g.whiteSpace),_.set([g.tt,g.zzz]));g.time=_.each(_.optional(_.ignore(_.stoken("T"))),g.hms,g.timeSuffix);g.d=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1]|\d)/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.dd=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1])/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.ddd=g.dddd=_.cache(_.process(g.ctoken("sun mon tue wed thu fri sat"),function(s){return function(){this.weekday=s;};}));g.M=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d|\d)/),t.month));g.MM=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d)/),t.month));g.MMM=g.MMMM=_.cache(_.process(g.ctoken("jan feb mar apr may jun jul aug sep oct nov dec"),t.month));g.y=_.cache(_.process(_.rtoken(/^(\d\d?)/),t.year));g.yy=_.cache(_.process(_.rtoken(/^(\d\d)/),t.year));g.yyy=_.cache(_.process(_.rtoken(/^(\d\d?\d?\d?)/),t.year));g.yyyy=_.cache(_.process(_.rtoken(/^(\d\d\d\d)/),t.year));_fn=function(){return _.each(_.any.apply(null,arguments),_.not(g.ctoken2("timeContext")));};g.day=_fn(g.d,g.dd);g.month=_fn(g.M,g.MMM);g.year=_fn(g.yyyy,g.yy);g.orientation=_.process(g.ctoken("past future"),function(s){return function(){this.orient=s;};});g.operator=_.process(g.ctoken("add subtract"),function(s){return function(){this.operator=s;};});g.rday=_.process(g.ctoken("yesterday tomorrow today now"),t.rday);g.unit=_.process(g.ctoken("minute hour day week month year"),function(s){return function(){this.unit=s;};});g.value=_.process(_.rtoken(/^\d\d?(st|nd|rd|th)?/),function(s){return function(){this.value=s.replace(/\D/g,"");};});g.expression=_.set([g.rday,g.operator,g.value,g.unit,g.orientation,g.ddd,g.MMM]);_fn=function(){return _.set(arguments,g.datePartDelimiter);};g.mdy=_fn(g.ddd,g.month,g.day,g.year);g.ymd=_fn(g.ddd,g.year,g.month,g.day);g.dmy=_fn(g.ddd,g.day,g.month,g.year);g.date=function(s){return((g[Date.CultureInfo.dateElementOrder]||g.mdy).call(this,s));};g.format=_.process(_.many(_.any(_.process(_.rtoken(/^(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?)/),function(fmt){if(g[fmt]){return g[fmt];}else{throw Date.Parsing.Exception(fmt);}}),_.process(_.rtoken(/^[^dMyhHmstz]+/),function(s){return _.ignore(_.stoken(s));}))),function(rules){return _.process(_.each.apply(null,rules),t.finishExact);});var _F={};var _get=function(f){return _F[f]=(_F[f]||g.format(f)[0]);};g.formats=function(fx){if(fx instanceof Array){var rx=[];for(var i=0;i<fx.length;i++){rx.push(_get(fx[i]));}
return _.any.apply(null,rx);}else{return _get(fx);}};g._formats=g.formats(["yyyy-MM-ddTHH:mm:ss","ddd, MMM dd, yyyy H:mm:ss tt","ddd MMM d yyyy HH:mm:ss zzz","d"]);g._start=_.process(_.set([g.date,g.time,g.expression],g.generalDelimiter,g.whiteSpace),t.finish);g.start=function(s){try{var r=g._formats.call({},s);if(r[1].length===0){return r;}}catch(e){}
return g._start.call({},s);};}());Date._parse=Date.parse;Date.parse=function(s){var r=null;if(!s){return null;}
try{r=Date.Grammar.start.call({},s);}catch(e){return null;}
return((r[1].length===0)?r[0]:null);};Date.getParseFunction=function(fx){var fn=Date.Grammar.formats(fx);return function(s){var r=null;try{r=fn.call({},s);}catch(e){return null;}
return((r[1].length===0)?r[0]:null);};};Date.parseExact=function(s,fx){return Date.getParseFunction(fx)(s);};
/*!
 * Raphael 1.5.2 - JavaScript Vector Library
 *
 * Copyright (c) 2010 Dmitry Baranovskiy (http://raphaeljs.com)
 * Licensed under the MIT (http://raphaeljs.com/license.html) license.
 */

(function () {
    function R() {
        if (R.is(arguments[0], array)) {
            var a = arguments[0],
                cnv = create[apply](R, a.splice(0, 3 + R.is(a[0], nu))),
                res = cnv.set();
            for (var i = 0, ii = a[length]; i < ii; i++) {
                var j = a[i] || {};
                elements[has](j.type) && res[push](cnv[j.type]().attr(j));
            }
            return res;
        }
        return create[apply](R, arguments);
    }
    R.version = "1.5.2";
    var separator = /[, ]+/,
        elements = {circle: 1, rect: 1, path: 1, ellipse: 1, text: 1, image: 1},
        formatrg = /\{(\d+)\}/g,
        proto = "prototype",
        has = "hasOwnProperty",
        doc = document,
        win = window,
        oldRaphael = {
            was: Object[proto][has].call(win, "Raphael"),
            is: win.Raphael
        },
        Paper = function () {
            this.customAttributes = {};
        },
        paperproto,
        appendChild = "appendChild",
        apply = "apply",
        concat = "concat",
        supportsTouch = "createTouch" in doc,
        E = "",
        S = " ",
        Str = String,
        split = "split",
        events = "click dblclick mousedown mousemove mouseout mouseover mouseup touchstart touchmove touchend orientationchange touchcancel gesturestart gesturechange gestureend"[split](S),
        touchMap = {
            mousedown: "touchstart",
            mousemove: "touchmove",
            mouseup: "touchend"
        },
        join = "join",
        length = "length",
        lowerCase = Str[proto].toLowerCase,
        math = Math,
        mmax = math.max,
        mmin = math.min,
        abs = math.abs,
        pow = math.pow,
        PI = math.PI,
        nu = "number",
        string = "string",
        array = "array",
        toString = "toString",
        fillString = "fill",
        objectToString = Object[proto][toString],
        paper = {},
        push = "push",
        ISURL = /^url\(['"]?([^\)]+?)['"]?\)$/i,
        colourRegExp = /^\s*((#[a-f\d]{6})|(#[a-f\d]{3})|rgba?\(\s*([\d\.]+%?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\)|hsba?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\)|hsla?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\))\s*$/i,
        isnan = {"NaN": 1, "Infinity": 1, "-Infinity": 1},
        bezierrg = /^(?:cubic-)?bezier\(([^,]+),([^,]+),([^,]+),([^\)]+)\)/,
        round = math.round,
        setAttribute = "setAttribute",
        toFloat = parseFloat,
        toInt = parseInt,
        ms = " progid:DXImageTransform.Microsoft",
        upperCase = Str[proto].toUpperCase,
        availableAttrs = {blur: 0, "clip-rect": "0 0 1e9 1e9", cursor: "default", cx: 0, cy: 0, fill: "#fff", "fill-opacity": 1, font: '10px "Arial"', "font-family": '"Arial"', "font-size": "10", "font-style": "normal", "font-weight": 400, gradient: 0, height: 0, href: "http://raphaeljs.com/", opacity: 1, path: "M0,0", r: 0, rotation: 0, rx: 0, ry: 0, scale: "1 1", src: "", stroke: "#000", "stroke-dasharray": "", "stroke-linecap": "butt", "stroke-linejoin": "butt", "stroke-miterlimit": 0, "stroke-opacity": 1, "stroke-width": 1, target: "_blank", "text-anchor": "middle", title: "Raphael", translation: "0 0", width: 0, x: 0, y: 0},
        availableAnimAttrs = {along: "along", blur: nu, "clip-rect": "csv", cx: nu, cy: nu, fill: "colour", "fill-opacity": nu, "font-size": nu, height: nu, opacity: nu, path: "path", r: nu, rotation: "csv", rx: nu, ry: nu, scale: "csv", stroke: "colour", "stroke-opacity": nu, "stroke-width": nu, translation: "csv", width: nu, x: nu, y: nu},
        rp = "replace",
        animKeyFrames= /^(from|to|\d+%?)$/,
        commaSpaces = /\s*,\s*/,
        hsrg = {hs: 1, rg: 1},
        p2s = /,?([achlmqrstvxz]),?/gi,
        pathCommand = /([achlmqstvz])[\s,]*((-?\d*\.?\d*(?:e[-+]?\d+)?\s*,?\s*)+)/ig,
        pathValues = /(-?\d*\.?\d*(?:e[-+]?\d+)?)\s*,?\s*/ig,
        radial_gradient = /^r(?:\(([^,]+?)\s*,\s*([^\)]+?)\))?/,
        sortByKey = function (a, b) {
            return a.key - b.key;
        };

    R.type = (win.SVGAngle || doc.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") ? "SVG" : "VML");
    if (R.type == "VML") {
        var d = doc.createElement("div"),
            b;
        d.innerHTML = '<v:shape adj="1"/>';
        b = d.firstChild;
        b.style.behavior = "url(#default#VML)";
        if (!(b && typeof b.adj == "object")) {
            return R.type = null;
        }
        d = null;
    }
    R.svg = !(R.vml = R.type == "VML");
    Paper[proto] = R[proto];
    paperproto = Paper[proto];
    R._id = 0;
    R._oid = 0;
    R.fn = {};
    R.is = function (o, type) {
        type = lowerCase.call(type);
        if (type == "finite") {
            return !isnan[has](+o);
        }
        return  (type == "null" && o === null) ||
                (type == typeof o) ||
                (type == "object" && o === Object(o)) ||
                (type == "array" && Array.isArray && Array.isArray(o)) ||
                objectToString.call(o).slice(8, -1).toLowerCase() == type;
    };
    R.angle = function (x1, y1, x2, y2, x3, y3) {
        if (x3 == null) {
            var x = x1 - x2,
                y = y1 - y2;
            if (!x && !y) {
                return 0;
            }
            return ((x < 0) * 180 + math.atan(-y / -x) * 180 / PI + 360) % 360;
        } else {
            return R.angle(x1, y1, x3, y3) - R.angle(x2, y2, x3, y3);
        }
    };
    R.rad = function (deg) {
        return deg % 360 * PI / 180;
    };
    R.deg = function (rad) {
        return rad * 180 / PI % 360;
    };
    R.snapTo = function (values, value, tolerance) {
        tolerance = R.is(tolerance, "finite") ? tolerance : 10;
        if (R.is(values, array)) {
            var i = values.length;
            while (i--) if (abs(values[i] - value) <= tolerance) {
                return values[i];
            }
        } else {
            values = +values;
            var rem = value % values;
            if (rem < tolerance) {
                return value - rem;
            }
            if (rem > values - tolerance) {
                return value - rem + values;
            }
        }
        return value;
    };
    function createUUID() {
        // http://www.ietf.org/rfc/rfc4122.txt
        var s = [],
            i = 0;
        for (; i < 32; i++) {
            s[i] = (~~(math.random() * 16))[toString](16);
        }
        s[12] = 4;  // bits 12-15 of the time_hi_and_version field to 0010
        s[16] = ((s[16] & 3) | 8)[toString](16);  // bits 6-7 of the clock_seq_hi_and_reserved to 01
        return "r-" + s[join]("");
    }

    R.setWindow = function (newwin) {
        win = newwin;
        doc = win.document;
    };
    // colour utilities
    var toHex = function (color) {
        if (R.vml) {
            // http://dean.edwards.name/weblog/2009/10/convert-any-colour-value-to-hex-in-msie/
            var trim = /^\s+|\s+$/g;
            var bod;
            try {
                var docum = new ActiveXObject("htmlfile");
                docum.write("<body>");
                docum.close();
                bod = docum.body;
            } catch(e) {
                bod = createPopup().document.body;
            }
            var range = bod.createTextRange();
            toHex = cacher(function (color) {
                try {
                    bod.style.color = Str(color)[rp](trim, E);
                    var value = range.queryCommandValue("ForeColor");
                    value = ((value & 255) << 16) | (value & 65280) | ((value & 16711680) >>> 16);
                    return "#" + ("000000" + value[toString](16)).slice(-6);
                } catch(e) {
                    return "none";
                }
            });
        } else {
            var i = doc.createElement("i");
            i.title = "Rapha\xebl Colour Picker";
            i.style.display = "none";
            doc.body[appendChild](i);
            toHex = cacher(function (color) {
                i.style.color = color;
                return doc.defaultView.getComputedStyle(i, E).getPropertyValue("color");
            });
        }
        return toHex(color);
    },
    hsbtoString = function () {
        return "hsb(" + [this.h, this.s, this.b] + ")";
    },
    hsltoString = function () {
        return "hsl(" + [this.h, this.s, this.l] + ")";
    },
    rgbtoString = function () {
        return this.hex;
    };
    R.hsb2rgb = function (h, s, b, o) {
        if (R.is(h, "object") && "h" in h && "s" in h && "b" in h) {
            b = h.b;
            s = h.s;
            h = h.h;
            o = h.o;
        }
        return R.hsl2rgb(h, s, b / 2, o);
    };
    R.hsl2rgb = function (h, s, l, o) {
        if (R.is(h, "object") && "h" in h && "s" in h && "l" in h) {
            l = h.l;
            s = h.s;
            h = h.h;
        }
        if (h > 1 || s > 1 || l > 1) {
            h /= 360;
            s /= 100;
            l /= 100;
        }
        var rgb = {},
            channels = ["r", "g", "b"],
            t2, t1, t3, r, g, b;
        if (!s) {
            rgb = {
                r: l,
                g: l,
                b: l
            };
        } else {
            if (l < .5) {
                t2 = l * (1 + s);
            } else {
                t2 = l + s - l * s;
            }
            t1 = 2 * l - t2;
            for (var i = 0; i < 3; i++) {
                t3 = h + 1 / 3 * -(i - 1);
                t3 < 0 && t3++;
                t3 > 1 && t3--;
                if (t3 * 6 < 1) {
                    rgb[channels[i]] = t1 + (t2 - t1) * 6 * t3;
                } else if (t3 * 2 < 1) {
                    rgb[channels[i]] = t2;
                } else if (t3 * 3 < 2) {
                    rgb[channels[i]] = t1 + (t2 - t1) * (2 / 3 - t3) * 6;
                } else {
                    rgb[channels[i]] = t1;
                }
            }
        }
        rgb.r *= 255;
        rgb.g *= 255;
        rgb.b *= 255;
        rgb.hex = "#" + (16777216 | rgb.b | (rgb.g << 8) | (rgb.r << 16)).toString(16).slice(1);
        R.is(o, "finite") && (rgb.opacity = o);
        rgb.toString = rgbtoString;
        return rgb;
    };
    R.rgb2hsb = function (red, green, blue) {
        if (green == null && R.is(red, "object") && "r" in red && "g" in red && "b" in red) {
            blue = red.b;
            green = red.g;
            red = red.r;
        }
        if (green == null && R.is(red, string)) {
            var clr = R.getRGB(red);
            red = clr.r;
            green = clr.g;
            blue = clr.b;
        }
        if (red > 1 || green > 1 || blue > 1) {
            red /= 255;
            green /= 255;
            blue /= 255;
        }
        var max = mmax(red, green, blue),
            min = mmin(red, green, blue),
            hue,
            saturation,
            brightness = max;
        if (min == max) {
            return {h: 0, s: 0, b: max, toString: hsbtoString};
        } else {
            var delta = (max - min);
            saturation = delta / max;
            if (red == max) {
                hue = (green - blue) / delta;
            } else if (green == max) {
                hue = 2 + ((blue - red) / delta);
            } else {
                hue = 4 + ((red - green) / delta);
            }
            hue /= 6;
            hue < 0 && hue++;
            hue > 1 && hue--;
        }
        return {h: hue, s: saturation, b: brightness, toString: hsbtoString};
    };
    R.rgb2hsl = function (red, green, blue) {
        if (green == null && R.is(red, "object") && "r" in red && "g" in red && "b" in red) {
            blue = red.b;
            green = red.g;
            red = red.r;
        }
        if (green == null && R.is(red, string)) {
            var clr = R.getRGB(red);
            red = clr.r;
            green = clr.g;
            blue = clr.b;
        }
        if (red > 1 || green > 1 || blue > 1) {
            red /= 255;
            green /= 255;
            blue /= 255;
        }
        var max = mmax(red, green, blue),
            min = mmin(red, green, blue),
            h,
            s,
            l = (max + min) / 2,
            hsl;
        if (min == max) {
            hsl =  {h: 0, s: 0, l: l};
        } else {
            var delta = max - min;
            s = l < .5 ? delta / (max + min) : delta / (2 - max - min);
            if (red == max) {
                h = (green - blue) / delta;
            } else if (green == max) {
                h = 2 + (blue - red) / delta;
            } else {
                h = 4 + (red - green) / delta;
            }
            h /= 6;
            h < 0 && h++;
            h > 1 && h--;
            hsl = {h: h, s: s, l: l};
        }
        hsl.toString = hsltoString;
        return hsl;
    };
    R._path2string = function () {
        return this.join(",")[rp](p2s, "$1");
    };
    function cacher(f, scope, postprocessor) {
        function newf() {
            var arg = Array[proto].slice.call(arguments, 0),
                args = arg[join]("\u25ba"),
                cache = newf.cache = newf.cache || {},
                count = newf.count = newf.count || [];
            if (cache[has](args)) {
                return postprocessor ? postprocessor(cache[args]) : cache[args];
            }
            count[length] >= 1e3 && delete cache[count.shift()];
            count[push](args);
            cache[args] = f[apply](scope, arg);
            return postprocessor ? postprocessor(cache[args]) : cache[args];
        }
        return newf;
    }
 
    R.getRGB = cacher(function (colour) {
        if (!colour || !!((colour = Str(colour)).indexOf("-") + 1)) {
            return {r: -1, g: -1, b: -1, hex: "none", error: 1};
        }
        if (colour == "none") {
            return {r: -1, g: -1, b: -1, hex: "none"};
        }
        !(hsrg[has](colour.toLowerCase().substring(0, 2)) || colour.charAt() == "#") && (colour = toHex(colour));
        var res,
            red,
            green,
            blue,
            opacity,
            t,
            values,
            rgb = colour.match(colourRegExp);
        if (rgb) {
            if (rgb[2]) {
                blue = toInt(rgb[2].substring(5), 16);
                green = toInt(rgb[2].substring(3, 5), 16);
                red = toInt(rgb[2].substring(1, 3), 16);
            }
            if (rgb[3]) {
                blue = toInt((t = rgb[3].charAt(3)) + t, 16);
                green = toInt((t = rgb[3].charAt(2)) + t, 16);
                red = toInt((t = rgb[3].charAt(1)) + t, 16);
            }
            if (rgb[4]) {
                values = rgb[4][split](commaSpaces);
                red = toFloat(values[0]);
                values[0].slice(-1) == "%" && (red *= 2.55);
                green = toFloat(values[1]);
                values[1].slice(-1) == "%" && (green *= 2.55);
                blue = toFloat(values[2]);
                values[2].slice(-1) == "%" && (blue *= 2.55);
                rgb[1].toLowerCase().slice(0, 4) == "rgba" && (opacity = toFloat(values[3]));
                values[3] && values[3].slice(-1) == "%" && (opacity /= 100);
            }
            if (rgb[5]) {
                values = rgb[5][split](commaSpaces);
                red = toFloat(values[0]);
                values[0].slice(-1) == "%" && (red *= 2.55);
                green = toFloat(values[1]);
                values[1].slice(-1) == "%" && (green *= 2.55);
                blue = toFloat(values[2]);
                values[2].slice(-1) == "%" && (blue *= 2.55);
                (values[0].slice(-3) == "deg" || values[0].slice(-1) == "\xb0") && (red /= 360);
                rgb[1].toLowerCase().slice(0, 4) == "hsba" && (opacity = toFloat(values[3]));
                values[3] && values[3].slice(-1) == "%" && (opacity /= 100);
                return R.hsb2rgb(red, green, blue, opacity);
            }
            if (rgb[6]) {
                values = rgb[6][split](commaSpaces);
                red = toFloat(values[0]);
                values[0].slice(-1) == "%" && (red *= 2.55);
                green = toFloat(values[1]);
                values[1].slice(-1) == "%" && (green *= 2.55);
                blue = toFloat(values[2]);
                values[2].slice(-1) == "%" && (blue *= 2.55);
                (values[0].slice(-3) == "deg" || values[0].slice(-1) == "\xb0") && (red /= 360);
                rgb[1].toLowerCase().slice(0, 4) == "hsla" && (opacity = toFloat(values[3]));
                values[3] && values[3].slice(-1) == "%" && (opacity /= 100);
                return R.hsl2rgb(red, green, blue, opacity);
            }
            rgb = {r: red, g: green, b: blue};
            rgb.hex = "#" + (16777216 | blue | (green << 8) | (red << 16)).toString(16).slice(1);
            R.is(opacity, "finite") && (rgb.opacity = opacity);
            return rgb;
        }
        return {r: -1, g: -1, b: -1, hex: "none", error: 1};
    }, R);
    R.getColor = function (value) {
        var start = this.getColor.start = this.getColor.start || {h: 0, s: 1, b: value || .75},
            rgb = this.hsb2rgb(start.h, start.s, start.b);
        start.h += .075;
        if (start.h > 1) {
            start.h = 0;
            start.s -= .2;
            start.s <= 0 && (this.getColor.start = {h: 0, s: 1, b: start.b});
        }
        return rgb.hex;
    };
    R.getColor.reset = function () {
        delete this.start;
    };
    // path utilities
    R.parsePathString = cacher(function (pathString) {
        if (!pathString) {
            return null;
        }
        var paramCounts = {a: 7, c: 6, h: 1, l: 2, m: 2, q: 4, s: 4, t: 2, v: 1, z: 0},
            data = [];
        if (R.is(pathString, array) && R.is(pathString[0], array)) { // rough assumption
            data = pathClone(pathString);
        }
        if (!data[length]) {
            Str(pathString)[rp](pathCommand, function (a, b, c) {
                var params = [],
                    name = lowerCase.call(b);
                c[rp](pathValues, function (a, b) {
                    b && params[push](+b);
                });
                if (name == "m" && params[length] > 2) {
                    data[push]([b][concat](params.splice(0, 2)));
                    name = "l";
                    b = b == "m" ? "l" : "L";
                }
                while (params[length] >= paramCounts[name]) {
                    data[push]([b][concat](params.splice(0, paramCounts[name])));
                    if (!paramCounts[name]) {
                        break;
                    }
                }
            });
        }
        data[toString] = R._path2string;
        return data;
    });
    R.findDotsAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {
        var t1 = 1 - t,
            x = pow(t1, 3) * p1x + pow(t1, 2) * 3 * t * c1x + t1 * 3 * t * t * c2x + pow(t, 3) * p2x,
            y = pow(t1, 3) * p1y + pow(t1, 2) * 3 * t * c1y + t1 * 3 * t * t * c2y + pow(t, 3) * p2y,
            mx = p1x + 2 * t * (c1x - p1x) + t * t * (c2x - 2 * c1x + p1x),
            my = p1y + 2 * t * (c1y - p1y) + t * t * (c2y - 2 * c1y + p1y),
            nx = c1x + 2 * t * (c2x - c1x) + t * t * (p2x - 2 * c2x + c1x),
            ny = c1y + 2 * t * (c2y - c1y) + t * t * (p2y - 2 * c2y + c1y),
            ax = (1 - t) * p1x + t * c1x,
            ay = (1 - t) * p1y + t * c1y,
            cx = (1 - t) * c2x + t * p2x,
            cy = (1 - t) * c2y + t * p2y,
            alpha = (90 - math.atan((mx - nx) / (my - ny)) * 180 / PI);
        (mx > nx || my < ny) && (alpha += 180);
        return {x: x, y: y, m: {x: mx, y: my}, n: {x: nx, y: ny}, start: {x: ax, y: ay}, end: {x: cx, y: cy}, alpha: alpha};
    };
    var pathDimensions = cacher(function (path) {
        if (!path) {
            return {x: 0, y: 0, width: 0, height: 0};
        }
        path = path2curve(path);
        var x = 0, 
            y = 0,
            X = [],
            Y = [],
            p;
        for (var i = 0, ii = path[length]; i < ii; i++) {
            p = path[i];
            if (p[0] == "M") {
                x = p[1];
                y = p[2];
                X[push](x);
                Y[push](y);
            } else {
                var dim = curveDim(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);
                X = X[concat](dim.min.x, dim.max.x);
                Y = Y[concat](dim.min.y, dim.max.y);
                x = p[5];
                y = p[6];
            }
        }
        var xmin = mmin[apply](0, X),
            ymin = mmin[apply](0, Y);
        return {
            x: xmin,
            y: ymin,
            width: mmax[apply](0, X) - xmin,
            height: mmax[apply](0, Y) - ymin
        };
    }),
        pathClone = function (pathArray) {
            var res = [];
            if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption
                pathArray = R.parsePathString(pathArray);
            }
            for (var i = 0, ii = pathArray[length]; i < ii; i++) {
                res[i] = [];
                for (var j = 0, jj = pathArray[i][length]; j < jj; j++) {
                    res[i][j] = pathArray[i][j];
                }
            }
            res[toString] = R._path2string;
            return res;
        },
        pathToRelative = cacher(function (pathArray) {
            if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption
                pathArray = R.parsePathString(pathArray);
            }
            var res = [],
                x = 0,
                y = 0,
                mx = 0,
                my = 0,
                start = 0;
            if (pathArray[0][0] == "M") {
                x = pathArray[0][1];
                y = pathArray[0][2];
                mx = x;
                my = y;
                start++;
                res[push](["M", x, y]);
            }
            for (var i = start, ii = pathArray[length]; i < ii; i++) {
                var r = res[i] = [],
                    pa = pathArray[i];
                if (pa[0] != lowerCase.call(pa[0])) {
                    r[0] = lowerCase.call(pa[0]);
                    switch (r[0]) {
                        case "a":
                            r[1] = pa[1];
                            r[2] = pa[2];
                            r[3] = pa[3];
                            r[4] = pa[4];
                            r[5] = pa[5];
                            r[6] = +(pa[6] - x).toFixed(3);
                            r[7] = +(pa[7] - y).toFixed(3);
                            break;
                        case "v":
                            r[1] = +(pa[1] - y).toFixed(3);
                            break;
                        case "m":
                            mx = pa[1];
                            my = pa[2];
                        default:
                            for (var j = 1, jj = pa[length]; j < jj; j++) {
                                r[j] = +(pa[j] - ((j % 2) ? x : y)).toFixed(3);
                            }
                    }
                } else {
                    r = res[i] = [];
                    if (pa[0] == "m") {
                        mx = pa[1] + x;
                        my = pa[2] + y;
                    }
                    for (var k = 0, kk = pa[length]; k < kk; k++) {
                        res[i][k] = pa[k];
                    }
                }
                var len = res[i][length];
                switch (res[i][0]) {
                    case "z":
                        x = mx;
                        y = my;
                        break;
                    case "h":
                        x += +res[i][len - 1];
                        break;
                    case "v":
                        y += +res[i][len - 1];
                        break;
                    default:
                        x += +res[i][len - 2];
                        y += +res[i][len - 1];
                }
            }
            res[toString] = R._path2string;
            return res;
        }, 0, pathClone),
        pathToAbsolute = cacher(function (pathArray) {
            if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption
                pathArray = R.parsePathString(pathArray);
            }
            var res = [],
                x = 0,
                y = 0,
                mx = 0,
                my = 0,
                start = 0;
            if (pathArray[0][0] == "M") {
                x = +pathArray[0][1];
                y = +pathArray[0][2];
                mx = x;
                my = y;
                start++;
                res[0] = ["M", x, y];
            }
            for (var i = start, ii = pathArray[length]; i < ii; i++) {
                var r = res[i] = [],
                    pa = pathArray[i];
                if (pa[0] != upperCase.call(pa[0])) {
                    r[0] = upperCase.call(pa[0]);
                    switch (r[0]) {
                        case "A":
                            r[1] = pa[1];
                            r[2] = pa[2];
                            r[3] = pa[3];
                            r[4] = pa[4];
                            r[5] = pa[5];
                            r[6] = +(pa[6] + x);
                            r[7] = +(pa[7] + y);
                            break;
                        case "V":
                            r[1] = +pa[1] + y;
                            break;
                        case "H":
                            r[1] = +pa[1] + x;
                            break;
                        case "M":
                            mx = +pa[1] + x;
                            my = +pa[2] + y;
                        default:
                            for (var j = 1, jj = pa[length]; j < jj; j++) {
                                r[j] = +pa[j] + ((j % 2) ? x : y);
                            }
                    }
                } else {
                    for (var k = 0, kk = pa[length]; k < kk; k++) {
                        res[i][k] = pa[k];
                    }
                }
                switch (r[0]) {
                    case "Z":
                        x = mx;
                        y = my;
                        break;
                    case "H":
                        x = r[1];
                        break;
                    case "V":
                        y = r[1];
                        break;
                    case "M":
                        mx = res[i][res[i][length] - 2];
                        my = res[i][res[i][length] - 1];
                    default:
                        x = res[i][res[i][length] - 2];
                        y = res[i][res[i][length] - 1];
                }
            }
            res[toString] = R._path2string;
            return res;
        }, null, pathClone),
        l2c = function (x1, y1, x2, y2) {
            return [x1, y1, x2, y2, x2, y2];
        },
        q2c = function (x1, y1, ax, ay, x2, y2) {
            var _13 = 1 / 3,
                _23 = 2 / 3;
            return [
                    _13 * x1 + _23 * ax,
                    _13 * y1 + _23 * ay,
                    _13 * x2 + _23 * ax,
                    _13 * y2 + _23 * ay,
                    x2,
                    y2
                ];
        },
        a2c = function (x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) {
            // for more information of where this math came from visit:
            // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
            var _120 = PI * 120 / 180,
                rad = PI / 180 * (+angle || 0),
                res = [],
                xy,
                rotate = cacher(function (x, y, rad) {
                    var X = x * math.cos(rad) - y * math.sin(rad),
                        Y = x * math.sin(rad) + y * math.cos(rad);
                    return {x: X, y: Y};
                });
            if (!recursive) {
                xy = rotate(x1, y1, -rad);
                x1 = xy.x;
                y1 = xy.y;
                xy = rotate(x2, y2, -rad);
                x2 = xy.x;
                y2 = xy.y;
                var cos = math.cos(PI / 180 * angle),
                    sin = math.sin(PI / 180 * angle),
                    x = (x1 - x2) / 2,
                    y = (y1 - y2) / 2;
                var h = (x * x) / (rx * rx) + (y * y) / (ry * ry);
                if (h > 1) {
                    h = math.sqrt(h);
                    rx = h * rx;
                    ry = h * ry;
                }
                var rx2 = rx * rx,
                    ry2 = ry * ry,
                    k = (large_arc_flag == sweep_flag ? -1 : 1) *
                        math.sqrt(abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x))),
                    cx = k * rx * y / ry + (x1 + x2) / 2,
                    cy = k * -ry * x / rx + (y1 + y2) / 2,
                    f1 = math.asin(((y1 - cy) / ry).toFixed(9)),
                    f2 = math.asin(((y2 - cy) / ry).toFixed(9));

                f1 = x1 < cx ? PI - f1 : f1;
                f2 = x2 < cx ? PI - f2 : f2;
                f1 < 0 && (f1 = PI * 2 + f1);
                f2 < 0 && (f2 = PI * 2 + f2);
                if (sweep_flag && f1 > f2) {
                    f1 = f1 - PI * 2;
                }
                if (!sweep_flag && f2 > f1) {
                    f2 = f2 - PI * 2;
                }
            } else {
                f1 = recursive[0];
                f2 = recursive[1];
                cx = recursive[2];
                cy = recursive[3];
            }
            var df = f2 - f1;
            if (abs(df) > _120) {
                var f2old = f2,
                    x2old = x2,
                    y2old = y2;
                f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1);
                x2 = cx + rx * math.cos(f2);
                y2 = cy + ry * math.sin(f2);
                res = a2c(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]);
            }
            df = f2 - f1;
            var c1 = math.cos(f1),
                s1 = math.sin(f1),
                c2 = math.cos(f2),
                s2 = math.sin(f2),
                t = math.tan(df / 4),
                hx = 4 / 3 * rx * t,
                hy = 4 / 3 * ry * t,
                m1 = [x1, y1],
                m2 = [x1 + hx * s1, y1 - hy * c1],
                m3 = [x2 + hx * s2, y2 - hy * c2],
                m4 = [x2, y2];
            m2[0] = 2 * m1[0] - m2[0];
            m2[1] = 2 * m1[1] - m2[1];
            if (recursive) {
                return [m2, m3, m4][concat](res);
            } else {
                res = [m2, m3, m4][concat](res)[join]()[split](",");
                var newres = [];
                for (var i = 0, ii = res[length]; i < ii; i++) {
                    newres[i] = i % 2 ? rotate(res[i - 1], res[i], rad).y : rotate(res[i], res[i + 1], rad).x;
                }
                return newres;
            }
        },
        findDotAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {
            var t1 = 1 - t;
            return {
                x: pow(t1, 3) * p1x + pow(t1, 2) * 3 * t * c1x + t1 * 3 * t * t * c2x + pow(t, 3) * p2x,
                y: pow(t1, 3) * p1y + pow(t1, 2) * 3 * t * c1y + t1 * 3 * t * t * c2y + pow(t, 3) * p2y
            };
        },
        curveDim = cacher(function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {
            var a = (c2x - 2 * c1x + p1x) - (p2x - 2 * c2x + c1x),
                b = 2 * (c1x - p1x) - 2 * (c2x - c1x),
                c = p1x - c1x,
                t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a,
                t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a,
                y = [p1y, p2y],
                x = [p1x, p2x],
                dot;
            abs(t1) > "1e12" && (t1 = .5);
            abs(t2) > "1e12" && (t2 = .5);
            if (t1 > 0 && t1 < 1) {
                dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);
                x[push](dot.x);
                y[push](dot.y);
            }
            if (t2 > 0 && t2 < 1) {
                dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);
                x[push](dot.x);
                y[push](dot.y);
            }
            a = (c2y - 2 * c1y + p1y) - (p2y - 2 * c2y + c1y);
            b = 2 * (c1y - p1y) - 2 * (c2y - c1y);
            c = p1y - c1y;
            t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a;
            t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a;
            abs(t1) > "1e12" && (t1 = .5);
            abs(t2) > "1e12" && (t2 = .5);
            if (t1 > 0 && t1 < 1) {
                dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);
                x[push](dot.x);
                y[push](dot.y);
            }
            if (t2 > 0 && t2 < 1) {
                dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);
                x[push](dot.x);
                y[push](dot.y);
            }
            return {
                min: {x: mmin[apply](0, x), y: mmin[apply](0, y)},
                max: {x: mmax[apply](0, x), y: mmax[apply](0, y)}
            };
        }),
        path2curve = cacher(function (path, path2) {
            var p = pathToAbsolute(path),
                p2 = path2 && pathToAbsolute(path2),
                attrs = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},
                attrs2 = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},
                processPath = function (path, d) {
                    var nx, ny;
                    if (!path) {
                        return ["C", d.x, d.y, d.x, d.y, d.x, d.y];
                    }
                    !(path[0] in {T:1, Q:1}) && (d.qx = d.qy = null);
                    switch (path[0]) {
                        case "M":
                            d.X = path[1];
                            d.Y = path[2];
                            break;
                        case "A":
                            path = ["C"][concat](a2c[apply](0, [d.x, d.y][concat](path.slice(1))));
                            break;
                        case "S":
                            nx = d.x + (d.x - (d.bx || d.x));
                            ny = d.y + (d.y - (d.by || d.y));
                            path = ["C", nx, ny][concat](path.slice(1));
                            break;
                        case "T":
                            d.qx = d.x + (d.x - (d.qx || d.x));
                            d.qy = d.y + (d.y - (d.qy || d.y));
                            path = ["C"][concat](q2c(d.x, d.y, d.qx, d.qy, path[1], path[2]));
                            break;
                        case "Q":
                            d.qx = path[1];
                            d.qy = path[2];
                            path = ["C"][concat](q2c(d.x, d.y, path[1], path[2], path[3], path[4]));
                            break;
                        case "L":
                            path = ["C"][concat](l2c(d.x, d.y, path[1], path[2]));
                            break;
                        case "H":
                            path = ["C"][concat](l2c(d.x, d.y, path[1], d.y));
                            break;
                        case "V":
                            path = ["C"][concat](l2c(d.x, d.y, d.x, path[1]));
                            break;
                        case "Z":
                            path = ["C"][concat](l2c(d.x, d.y, d.X, d.Y));
                            break;
                    }
                    return path;
                },
                fixArc = function (pp, i) {
                    if (pp[i][length] > 7) {
                        pp[i].shift();
                        var pi = pp[i];
                        while (pi[length]) {
                            pp.splice(i++, 0, ["C"][concat](pi.splice(0, 6)));
                        }
                        pp.splice(i, 1);
                        ii = mmax(p[length], p2 && p2[length] || 0);
                    }
                },
                fixM = function (path1, path2, a1, a2, i) {
                    if (path1 && path2 && path1[i][0] == "M" && path2[i][0] != "M") {
                        path2.splice(i, 0, ["M", a2.x, a2.y]);
                        a1.bx = 0;
                        a1.by = 0;
                        a1.x = path1[i][1];
                        a1.y = path1[i][2];
                        ii = mmax(p[length], p2 && p2[length] || 0);
                    }
                };
            for (var i = 0, ii = mmax(p[length], p2 && p2[length] || 0); i < ii; i++) {
                p[i] = processPath(p[i], attrs);
                fixArc(p, i);
                p2 && (p2[i] = processPath(p2[i], attrs2));
                p2 && fixArc(p2, i);
                fixM(p, p2, attrs, attrs2, i);
                fixM(p2, p, attrs2, attrs, i);
                var seg = p[i],
                    seg2 = p2 && p2[i],
                    seglen = seg[length],
                    seg2len = p2 && seg2[length];
                attrs.x = seg[seglen - 2];
                attrs.y = seg[seglen - 1];
                attrs.bx = toFloat(seg[seglen - 4]) || attrs.x;
                attrs.by = toFloat(seg[seglen - 3]) || attrs.y;
                attrs2.bx = p2 && (toFloat(seg2[seg2len - 4]) || attrs2.x);
                attrs2.by = p2 && (toFloat(seg2[seg2len - 3]) || attrs2.y);
                attrs2.x = p2 && seg2[seg2len - 2];
                attrs2.y = p2 && seg2[seg2len - 1];
            }
            return p2 ? [p, p2] : p;
        }, null, pathClone),
        parseDots = cacher(function (gradient) {
            var dots = [];
            for (var i = 0, ii = gradient[length]; i < ii; i++) {
                var dot = {},
                    par = gradient[i].match(/^([^:]*):?([\d\.]*)/);
                dot.color = R.getRGB(par[1]);
                if (dot.color.error) {
                    return null;
                }
                dot.color = dot.color.hex;
                par[2] && (dot.offset = par[2] + "%");
                dots[push](dot);
            }
            for (i = 1, ii = dots[length] - 1; i < ii; i++) {
                if (!dots[i].offset) {
                    var start = toFloat(dots[i - 1].offset || 0),
                        end = 0;
                    for (var j = i + 1; j < ii; j++) {
                        if (dots[j].offset) {
                            end = dots[j].offset;
                            break;
                        }
                    }
                    if (!end) {
                        end = 100;
                        j = ii;
                    }
                    end = toFloat(end);
                    var d = (end - start) / (j - i + 1);
                    for (; i < j; i++) {
                        start += d;
                        dots[i].offset = start + "%";
                    }
                }
            }
            return dots;
        }),
        getContainer = function (x, y, w, h) {
            var container;
            if (R.is(x, string) || R.is(x, "object")) {
                container = R.is(x, string) ? doc.getElementById(x) : x;
                if (container.tagName) {
                    if (y == null) {
                        return {
                            container: container,
                            width: container.style.pixelWidth || container.offsetWidth,
                            height: container.style.pixelHeight || container.offsetHeight
                        };
                    } else {
                        return {container: container, width: y, height: w};
                    }
                }
            } else {
                return {container: 1, x: x, y: y, width: w, height: h};
            }
        },
        plugins = function (con, add) {
            var that = this;
            for (var prop in add) {
                if (add[has](prop) && !(prop in con)) {
                    switch (typeof add[prop]) {
                        case "function":
                            (function (f) {
                                con[prop] = con === that ? f : function () { return f[apply](that, arguments); };
                            })(add[prop]);
                        break;
                        case "object":
                            con[prop] = con[prop] || {};
                            plugins.call(this, con[prop], add[prop]);
                        break;
                        default:
                            con[prop] = add[prop];
                        break;
                    }
                }
            }
        },
        tear = function (el, paper) {
            el == paper.top && (paper.top = el.prev);
            el == paper.bottom && (paper.bottom = el.next);
            el.next && (el.next.prev = el.prev);
            el.prev && (el.prev.next = el.next);
        },
        tofront = function (el, paper) {
            if (paper.top === el) {
                return;
            }
            tear(el, paper);
            el.next = null;
            el.prev = paper.top;
            paper.top.next = el;
            paper.top = el;
        },
        toback = function (el, paper) {
            if (paper.bottom === el) {
                return;
            }
            tear(el, paper);
            el.next = paper.bottom;
            el.prev = null;
            paper.bottom.prev = el;
            paper.bottom = el;
        },
        insertafter = function (el, el2, paper) {
            tear(el, paper);
            el2 == paper.top && (paper.top = el);
            el2.next && (el2.next.prev = el);
            el.next = el2.next;
            el.prev = el2;
            el2.next = el;
        },
        insertbefore = function (el, el2, paper) {
            tear(el, paper);
            el2 == paper.bottom && (paper.bottom = el);
            el2.prev && (el2.prev.next = el);
            el.prev = el2.prev;
            el2.prev = el;
            el.next = el2;
        },
        removed = function (methodname) {
            return function () {
                throw new Error("Rapha\xebl: you are calling to method \u201c" + methodname + "\u201d of removed object");
            };
        };
    R.pathToRelative = pathToRelative;
    // SVG
    if (R.svg) {
        paperproto.svgns = "http://www.w3.org/2000/svg";
        paperproto.xlink = "http://www.w3.org/1999/xlink";
        round = function (num) {
            return +num + (~~num === num) * .5;
        };
        var $ = function (el, attr) {
            if (attr) {
                for (var key in attr) {
                    if (attr[has](key)) {
                        el[setAttribute](key, Str(attr[key]));
                    }
                }
            } else {
                el = doc.createElementNS(paperproto.svgns, el);
                el.style.webkitTapHighlightColor = "rgba(0,0,0,0)";
                return el;
            }
        };
        R[toString] = function () {
            return  "Your browser supports SVG.\nYou are running Rapha\xebl " + this.version;
        };
        var thePath = function (pathString, SVG) {
            var el = $("path");
            SVG.canvas && SVG.canvas[appendChild](el);
            var p = new Element(el, SVG);
            p.type = "path";
            setFillAndStroke(p, {fill: "none", stroke: "#000", path: pathString});
            return p;
        };
        var addGradientFill = function (o, gradient, SVG) {
            var type = "linear",
                fx = .5, fy = .5,
                s = o.style;
            gradient = Str(gradient)[rp](radial_gradient, function (all, _fx, _fy) {
                type = "radial";
                if (_fx && _fy) {
                    fx = toFloat(_fx);
                    fy = toFloat(_fy);
                    var dir = ((fy > .5) * 2 - 1);
                    pow(fx - .5, 2) + pow(fy - .5, 2) > .25 &&
                        (fy = math.sqrt(.25 - pow(fx - .5, 2)) * dir + .5) &&
                        fy != .5 &&
                        (fy = fy.toFixed(5) - 1e-5 * dir);
                }
                return E;
            });
            gradient = gradient[split](/\s*\-\s*/);
            if (type == "linear") {
                var angle = gradient.shift();
                angle = -toFloat(angle);
                if (isNaN(angle)) {
                    return null;
                }
                var vector = [0, 0, math.cos(angle * PI / 180), math.sin(angle * PI / 180)],
                    max = 1 / (mmax(abs(vector[2]), abs(vector[3])) || 1);
                vector[2] *= max;
                vector[3] *= max;
                if (vector[2] < 0) {
                    vector[0] = -vector[2];
                    vector[2] = 0;
                }
                if (vector[3] < 0) {
                    vector[1] = -vector[3];
                    vector[3] = 0;
                }
            }
            var dots = parseDots(gradient);
            if (!dots) {
                return null;
            }
            var id = o.getAttribute(fillString);
            id = id.match(/^url\(#(.*)\)$/);
            id && SVG.defs.removeChild(doc.getElementById(id[1]));

            var el = $(type + "Gradient");
            el.id = createUUID();
            $(el, type == "radial" ? {fx: fx, fy: fy} : {x1: vector[0], y1: vector[1], x2: vector[2], y2: vector[3]});
            SVG.defs[appendChild](el);
            for (var i = 0, ii = dots[length]; i < ii; i++) {
                var stop = $("stop");
                $(stop, {
                    offset: dots[i].offset ? dots[i].offset : !i ? "0%" : "100%",
                    "stop-color": dots[i].color || "#fff"
                });
                el[appendChild](stop);
            }
            $(o, {
                fill: "url(#" + el.id + ")",
                opacity: 1,
                "fill-opacity": 1
            });
            s.fill = E;
            s.opacity = 1;
            s.fillOpacity = 1;
            return 1;
        };
        var updatePosition = function (o) {
            var bbox = o.getBBox();
            $(o.pattern, {patternTransform: R.format("translate({0},{1})", bbox.x, bbox.y)});
        };
        var setFillAndStroke = function (o, params) {
            var dasharray = {
                    "": [0],
                    "none": [0],
                    "-": [3, 1],
                    ".": [1, 1],
                    "-.": [3, 1, 1, 1],
                    "-..": [3, 1, 1, 1, 1, 1],
                    ". ": [1, 3],
                    "- ": [4, 3],
                    "--": [8, 3],
                    "- .": [4, 3, 1, 3],
                    "--.": [8, 3, 1, 3],
                    "--..": [8, 3, 1, 3, 1, 3]
                },
                node = o.node,
                attrs = o.attrs,
                rot = o.rotate(),
                addDashes = function (o, value) {
                    value = dasharray[lowerCase.call(value)];
                    if (value) {
                        var width = o.attrs["stroke-width"] || "1",
                            butt = {round: width, square: width, butt: 0}[o.attrs["stroke-linecap"] || params["stroke-linecap"]] || 0,
                            dashes = [];
                        var i = value[length];
                        while (i--) {
                            dashes[i] = value[i] * width + ((i % 2) ? 1 : -1) * butt;
                        }
                        $(node, {"stroke-dasharray": dashes[join](",")});
                    }
                };
            params[has]("rotation") && (rot = params.rotation);
            var rotxy = Str(rot)[split](separator);
            if (!(rotxy.length - 1)) {
                rotxy = null;
            } else {
                rotxy[1] = +rotxy[1];
                rotxy[2] = +rotxy[2];
            }
            toFloat(rot) && o.rotate(0, true);
            for (var att in params) {
                if (params[has](att)) {
                    if (!availableAttrs[has](att)) {
                        continue;
                    }
                    var value = params[att];
                    attrs[att] = value;
                    switch (att) {
                        case "blur":
                            o.blur(value);
                            break;
                        case "rotation":
                            o.rotate(value, true);
                            break;
                        case "href":
                        case "title":
                        case "target":
                            var pn = node.parentNode;
                            if (lowerCase.call(pn.tagName) != "a") {
                                var hl = $("a");
                                pn.insertBefore(hl, node);
                                hl[appendChild](node);
                                pn = hl;
                            }
                            if (att == "target" && value == "blank") {
                                pn.setAttributeNS(o.paper.xlink, "show", "new");
                            } else {
                                pn.setAttributeNS(o.paper.xlink, att, value);
                            }
                            break;
                        case "cursor":
                            node.style.cursor = value;
                            break;
                        case "clip-rect":
                            var rect = Str(value)[split](separator);
                            if (rect[length] == 4) {
                                o.clip && o.clip.parentNode.parentNode.removeChild(o.clip.parentNode);
                                var el = $("clipPath"),
                                    rc = $("rect");
                                el.id = createUUID();
                                $(rc, {
                                    x: rect[0],
                                    y: rect[1],
                                    width: rect[2],
                                    height: rect[3]
                                });
                                el[appendChild](rc);
                                o.paper.defs[appendChild](el);
                                $(node, {"clip-path": "url(#" + el.id + ")"});
                                o.clip = rc;
                            }
                            if (!value) {
                                var clip = doc.getElementById(node.getAttribute("clip-path")[rp](/(^url\(#|\)$)/g, E));
                                clip && clip.parentNode.removeChild(clip);
                                $(node, {"clip-path": E});
                                delete o.clip;
                            }
                        break;
                        case "path":
                            if (o.type == "path") {
                                $(node, {d: value ? attrs.path = pathToAbsolute(value) : "M0,0"});
                            }
                            break;
                        case "width":
                            node[setAttribute](att, value);
                            if (attrs.fx) {
                                att = "x";
                                value = attrs.x;
                            } else {
                                break;
                            }
                        case "x":
                            if (attrs.fx) {
                                value = -attrs.x - (attrs.width || 0);
                            }
                        case "rx":
                            if (att == "rx" && o.type == "rect") {
                                break;
                            }
                        case "cx":
                            rotxy && (att == "x" || att == "cx") && (rotxy[1] += value - attrs[att]);
                            node[setAttribute](att, value);
                            o.pattern && updatePosition(o);
                            break;
                        case "height":
                            node[setAttribute](att, value);
                            if (attrs.fy) {
                                att = "y";
                                value = attrs.y;
                            } else {
                                break;
                            }
                        case "y":
                            if (attrs.fy) {
                                value = -attrs.y - (attrs.height || 0);
                            }
                        case "ry":
                            if (att == "ry" && o.type == "rect") {
                                break;
                            }
                        case "cy":
                            rotxy && (att == "y" || att == "cy") && (rotxy[2] += value - attrs[att]);
                            node[setAttribute](att, value);
                            o.pattern && updatePosition(o);
                            break;
                        case "r":
                            if (o.type == "rect") {
                                $(node, {rx: value, ry: value});
                            } else {
                                node[setAttribute](att, value);
                            }
                            break;
                        case "src":
                            if (o.type == "image") {
                                node.setAttributeNS(o.paper.xlink, "href", value);
                            }
                            break;
                        case "stroke-width":
                            node.style.strokeWidth = value;
                            // Need following line for Firefox
                            node[setAttribute](att, value);
                            if (attrs["stroke-dasharray"]) {
                                addDashes(o, attrs["stroke-dasharray"]);
                            }
                            break;
                        case "stroke-dasharray":
                            addDashes(o, value);
                            break;
                        case "translation":
                            var xy = Str(value)[split](separator);
                            xy[0] = +xy[0] || 0;
                            xy[1] = +xy[1] || 0;
                            if (rotxy) {
                                rotxy[1] += xy[0];
                                rotxy[2] += xy[1];
                            }
                            translate.call(o, xy[0], xy[1]);
                            break;
                        case "scale":
                            xy = Str(value)[split](separator);
                            o.scale(+xy[0] || 1, +xy[1] || +xy[0] || 1, isNaN(toFloat(xy[2])) ? null : +xy[2], isNaN(toFloat(xy[3])) ? null : +xy[3]);
                            break;
                        case fillString:
                            var isURL = Str(value).match(ISURL);
                            if (isURL) {
                                el = $("pattern");
                                var ig = $("image");
                                el.id = createUUID();
                                $(el, {x: 0, y: 0, patternUnits: "userSpaceOnUse", height: 1, width: 1});
                                $(ig, {x: 0, y: 0});
                                ig.setAttributeNS(o.paper.xlink, "href", isURL[1]);
                                el[appendChild](ig);
 
                                var img = doc.createElement("img");
                                img.style.cssText = "position:absolute;left:-9999em;top-9999em";
                                img.onload = function () {
                                    $(el, {width: this.offsetWidth, height: this.offsetHeight});
                                    $(ig, {width: this.offsetWidth, height: this.offsetHeight});
                                    doc.body.removeChild(this);
                                    o.paper.safari();
                                };
                                doc.body[appendChild](img);
                                img.src = isURL[1];
                                o.paper.defs[appendChild](el);
                                node.style.fill = "url(#" + el.id + ")";
                                $(node, {fill: "url(#" + el.id + ")"});
                                o.pattern = el;
                                o.pattern && updatePosition(o);
                                break;
                            }
                            var clr = R.getRGB(value);
                            if (!clr.error) {
                                delete params.gradient;
                                delete attrs.gradient;
                                !R.is(attrs.opacity, "undefined") &&
                                    R.is(params.opacity, "undefined") &&
                                    $(node, {opacity: attrs.opacity});
                                !R.is(attrs["fill-opacity"], "undefined") &&
                                    R.is(params["fill-opacity"], "undefined") &&
                                    $(node, {"fill-opacity": attrs["fill-opacity"]});
                            } else if ((({circle: 1, ellipse: 1})[has](o.type) || Str(value).charAt() != "r") && addGradientFill(node, value, o.paper)) {
                                attrs.gradient = value;
                                attrs.fill = "none";
                                break;
                            }
                            clr[has]("opacity") && $(node, {"fill-opacity": clr.opacity > 1 ? clr.opacity / 100 : clr.opacity});
                        case "stroke":
                            clr = R.getRGB(value);
                            node[setAttribute](att, clr.hex);
                            att == "stroke" && clr[has]("opacity") && $(node, {"stroke-opacity": clr.opacity > 1 ? clr.opacity / 100 : clr.opacity});
                            break;
                        case "gradient":
                            (({circle: 1, ellipse: 1})[has](o.type) || Str(value).charAt() != "r") && addGradientFill(node, value, o.paper);
                            break;
                        case "opacity":
                            if (attrs.gradient && !attrs[has]("stroke-opacity")) {
                                $(node, {"stroke-opacity": value > 1 ? value / 100 : value});
                            }
                            // fall
                        case "fill-opacity":
                            if (attrs.gradient) {
                                var gradient = doc.getElementById(node.getAttribute(fillString)[rp](/^url\(#|\)$/g, E));
                                if (gradient) {
                                    var stops = gradient.getElementsByTagName("stop");
                                    stops[stops[length] - 1][setAttribute]("stop-opacity", value);
                                }
                                break;
                            }
                        default:
                            att == "font-size" && (value = toInt(value, 10) + "px");
                            var cssrule = att[rp](/(\-.)/g, function (w) {
                                return upperCase.call(w.substring(1));
                            });
                            node.style[cssrule] = value;
                            // Need following line for Firefox
                            node[setAttribute](att, value);
                            break;
                    }
                }
            }
            
            tuneText(o, params);
            if (rotxy) {
                o.rotate(rotxy.join(S));
            } else {
                toFloat(rot) && o.rotate(rot, true);
            }
        };
        var leading = 1.2,
        tuneText = function (el, params) {
            if (el.type != "text" || !(params[has]("text") || params[has]("font") || params[has]("font-size") || params[has]("x") || params[has]("y"))) {
                return;
            }
            var a = el.attrs,
                node = el.node,
                fontSize = node.firstChild ? toInt(doc.defaultView.getComputedStyle(node.firstChild, E).getPropertyValue("font-size"), 10) : 10;
 
            if (params[has]("text")) {
                a.text = params.text;
                while (node.firstChild) {
                    node.removeChild(node.firstChild);
                }
                var texts = Str(params.text)[split]("\n");
                for (var i = 0, ii = texts[length]; i < ii; i++) if (texts[i]) {
                    var tspan = $("tspan");
                    i && $(tspan, {dy: fontSize * leading, x: a.x});
                    tspan[appendChild](doc.createTextNode(texts[i]));
                    node[appendChild](tspan);
                }
            } else {
                texts = node.getElementsByTagName("tspan");
                for (i = 0, ii = texts[length]; i < ii; i++) {
                    i && $(texts[i], {dy: fontSize * leading, x: a.x});
                }
            }
            $(node, {y: a.y});
            var bb = el.getBBox(),
                dif = a.y - (bb.y + bb.height / 2);
            dif && R.is(dif, "finite") && $(node, {y: a.y + dif});
        },
        Element = function (node, svg) {
            var X = 0,
                Y = 0;
            this[0] = node;
            this.id = R._oid++;
            this.node = node;
            node.raphael = this;
            this.paper = svg;
            this.attrs = this.attrs || {};
            this.transformations = []; // rotate, translate, scale
            this._ = {
                tx: 0,
                ty: 0,
                rt: {deg: 0, cx: 0, cy: 0},
                sx: 1,
                sy: 1
            };
            !svg.bottom && (svg.bottom = this);
            this.prev = svg.top;
            svg.top && (svg.top.next = this);
            svg.top = this;
            this.next = null;
        };
        var elproto = Element[proto];
        Element[proto].rotate = function (deg, cx, cy) {
            if (this.removed) {
                return this;
            }
            if (deg == null) {
                if (this._.rt.cx) {
                    return [this._.rt.deg, this._.rt.cx, this._.rt.cy][join](S);
                }
                return this._.rt.deg;
            }
            var bbox = this.getBBox();
            deg = Str(deg)[split](separator);
            if (deg[length] - 1) {
                cx = toFloat(deg[1]);
                cy = toFloat(deg[2]);
            }
            deg = toFloat(deg[0]);
            if (cx != null && cx !== false) {
                this._.rt.deg = deg;
            } else {
                this._.rt.deg += deg;
            }
            (cy == null) && (cx = null);
            this._.rt.cx = cx;
            this._.rt.cy = cy;
            cx = cx == null ? bbox.x + bbox.width / 2 : cx;
            cy = cy == null ? bbox.y + bbox.height / 2 : cy;
            if (this._.rt.deg) {
                this.transformations[0] = R.format("rotate({0} {1} {2})", this._.rt.deg, cx, cy);
                this.clip && $(this.clip, {transform: R.format("rotate({0} {1} {2})", -this._.rt.deg, cx, cy)});
            } else {
                this.transformations[0] = E;
                this.clip && $(this.clip, {transform: E});
            }
            $(this.node, {transform: this.transformations[join](S)});
            return this;
        };
        Element[proto].hide = function () {
            !this.removed && (this.node.style.display = "none");
            return this;
        };
        Element[proto].show = function () {
            !this.removed && (this.node.style.display = "");
            return this;
        };
        Element[proto].remove = function () {
            if (this.removed) {
                return;
            }
            tear(this, this.paper);
            this.node.parentNode.removeChild(this.node);
            for (var i in this) {
                delete this[i];
            }
            this.removed = true;
        };
        Element[proto].getBBox = function () {
            if (this.removed) {
                return this;
            }
            if (this.type == "path") {
                return pathDimensions(this.attrs.path);
            }
            if (this.node.style.display == "none") {
                this.show();
                var hide = true;
            }
            var bbox = {};
            try {
                bbox = this.node.getBBox();
            } catch(e) {
                // Firefox 3.0.x plays badly here
            } finally {
                bbox = bbox || {};
            }
            if (this.type == "text") {
                bbox = {x: bbox.x, y: Infinity, width: 0, height: 0};
                for (var i = 0, ii = this.node.getNumberOfChars(); i < ii; i++) {
                    var bb = this.node.getExtentOfChar(i);
                    (bb.y < bbox.y) && (bbox.y = bb.y);
                    (bb.y + bb.height - bbox.y > bbox.height) && (bbox.height = bb.y + bb.height - bbox.y);
                    (bb.x + bb.width - bbox.x > bbox.width) && (bbox.width = bb.x + bb.width - bbox.x);
                }
            }
            hide && this.hide();
            return bbox;
        };
        Element[proto].attr = function (name, value) {
            if (this.removed) {
                return this;
            }
            if (name == null) {
                var res = {};
                for (var i in this.attrs) if (this.attrs[has](i)) {
                    res[i] = this.attrs[i];
                }
                this._.rt.deg && (res.rotation = this.rotate());
                (this._.sx != 1 || this._.sy != 1) && (res.scale = this.scale());
                res.gradient && res.fill == "none" && (res.fill = res.gradient) && delete res.gradient;
                return res;
            }
            if (value == null && R.is(name, string)) {
                if (name == "translation") {
                    return translate.call(this);
                }
                if (name == "rotation") {
                    return this.rotate();
                }
                if (name == "scale") {
                    return this.scale();
                }
                if (name == fillString && this.attrs.fill == "none" && this.attrs.gradient) {
                    return this.attrs.gradient;
                }
                return this.attrs[name];
            }
            if (value == null && R.is(name, array)) {
                var values = {};
                for (var j = 0, jj = name.length; j < jj; j++) {
                    values[name[j]] = this.attr(name[j]);
                }
                return values;
            }
            if (value != null) {
                var params = {};
                params[name] = value;
            } else if (name != null && R.is(name, "object")) {
                params = name;
            }
            for (var key in this.paper.customAttributes) if (this.paper.customAttributes[has](key) && params[has](key) && R.is(this.paper.customAttributes[key], "function")) {
                var par = this.paper.customAttributes[key].apply(this, [][concat](params[key]));
                this.attrs[key] = params[key];
                for (var subkey in par) if (par[has](subkey)) {
                    params[subkey] = par[subkey];
                }
            }
            setFillAndStroke(this, params);
            return this;
        };
        Element[proto].toFront = function () {
            if (this.removed) {
                return this;
            }
            this.node.parentNode[appendChild](this.node);
            var svg = this.paper;
            svg.top != this && tofront(this, svg);
            return this;
        };
        Element[proto].toBack = function () {
            if (this.removed) {
                return this;
            }
            if (this.node.parentNode.firstChild != this.node) {
                this.node.parentNode.insertBefore(this.node, this.node.parentNode.firstChild);
                toback(this, this.paper);
                var svg = this.paper;
            }
            return this;
        };
        Element[proto].insertAfter = function (element) {
            if (this.removed) {
                return this;
            }
            var node = element.node || element[element.length - 1].node;
            if (node.nextSibling) {
                node.parentNode.insertBefore(this.node, node.nextSibling);
            } else {
                node.parentNode[appendChild](this.node);
            }
            insertafter(this, element, this.paper);
            return this;
        };
        Element[proto].insertBefore = function (element) {
            if (this.removed) {
                return this;
            }
            var node = element.node || element[0].node;
            node.parentNode.insertBefore(this.node, node);
            insertbefore(this, element, this.paper);
            return this;
        };
        Element[proto].blur = function (size) {
            // Experimental. No Safari support. Use it on your own risk.
            var t = this;
            if (+size !== 0) {
                var fltr = $("filter"),
                    blur = $("feGaussianBlur");
                t.attrs.blur = size;
                fltr.id = createUUID();
                $(blur, {stdDeviation: +size || 1.5});
                fltr.appendChild(blur);
                t.paper.defs.appendChild(fltr);
                t._blur = fltr;
                $(t.node, {filter: "url(#" + fltr.id + ")"});
            } else {
                if (t._blur) {
                    t._blur.parentNode.removeChild(t._blur);
                    delete t._blur;
                    delete t.attrs.blur;
                }
                t.node.removeAttribute("filter");
            }
        };
        var theCircle = function (svg, x, y, r) {
            var el = $("circle");
            svg.canvas && svg.canvas[appendChild](el);
            var res = new Element(el, svg);
            res.attrs = {cx: x, cy: y, r: r, fill: "none", stroke: "#000"};
            res.type = "circle";
            $(el, res.attrs);
            return res;
        },
        theRect = function (svg, x, y, w, h, r) {
            var el = $("rect");
            svg.canvas && svg.canvas[appendChild](el);
            var res = new Element(el, svg);
            res.attrs = {x: x, y: y, width: w, height: h, r: r || 0, rx: r || 0, ry: r || 0, fill: "none", stroke: "#000"};
            res.type = "rect";
            $(el, res.attrs);
            return res;
        },
        theEllipse = function (svg, x, y, rx, ry) {
            var el = $("ellipse");
            svg.canvas && svg.canvas[appendChild](el);
            var res = new Element(el, svg);
            res.attrs = {cx: x, cy: y, rx: rx, ry: ry, fill: "none", stroke: "#000"};
            res.type = "ellipse";
            $(el, res.attrs);
            return res;
        },
        theImage = function (svg, src, x, y, w, h) {
            var el = $("image");
            $(el, {x: x, y: y, width: w, height: h, preserveAspectRatio: "none"});
            el.setAttributeNS(svg.xlink, "href", src);
            svg.canvas && svg.canvas[appendChild](el);
            var res = new Element(el, svg);
            res.attrs = {x: x, y: y, width: w, height: h, src: src};
            res.type = "image";
            return res;
        },
        theText = function (svg, x, y, text) {
            var el = $("text");
            $(el, {x: x, y: y, "text-anchor": "middle"});
            svg.canvas && svg.canvas[appendChild](el);
            var res = new Element(el, svg);
            res.attrs = {x: x, y: y, "text-anchor": "middle", text: text, font: availableAttrs.font, stroke: "none", fill: "#000"};
            res.type = "text";
            setFillAndStroke(res, res.attrs);
            return res;
        },
        setSize = function (width, height) {
            this.width = width || this.width;
            this.height = height || this.height;
            this.canvas[setAttribute]("width", this.width);
            this.canvas[setAttribute]("height", this.height);
            return this;
        },
        create = function () {
            var con = getContainer[apply](0, arguments),
                container = con && con.container,
                x = con.x,
                y = con.y,
                width = con.width,
                height = con.height;
            if (!container) {
                throw new Error("SVG container not found.");
            }
            var cnvs = $("svg");
            x = x || 0;
            y = y || 0;
            width = width || 512;
            height = height || 342;
            $(cnvs, {
                xmlns: "http://www.w3.org/2000/svg",
                version: 1.1,
                width: width,
                height: height
            });
            if (container == 1) {
                cnvs.style.cssText = "position:absolute;left:" + x + "px;top:" + y + "px";
                doc.body[appendChild](cnvs);
            } else {
                if (container.firstChild) {
                    container.insertBefore(cnvs, container.firstChild);
                } else {
                    container[appendChild](cnvs);
                }
            }
            container = new Paper;
            container.width = width;
            container.height = height;
            container.canvas = cnvs;
            plugins.call(container, container, R.fn);
            container.clear();
            return container;
        };
        paperproto.clear = function () {
            var c = this.canvas;
            while (c.firstChild) {
                c.removeChild(c.firstChild);
            }
            this.bottom = this.top = null;
            (this.desc = $("desc"))[appendChild](doc.createTextNode("Created with Rapha\xebl"));
            c[appendChild](this.desc);
            c[appendChild](this.defs = $("defs"));
        };
        paperproto.remove = function () {
            this.canvas.parentNode && this.canvas.parentNode.removeChild(this.canvas);
            for (var i in this) {
                this[i] = removed(i);
            }
        };
    }

    // VML
    if (R.vml) {
        var map = {M: "m", L: "l", C: "c", Z: "x", m: "t", l: "r", c: "v", z: "x"},
            bites = /([clmz]),?([^clmz]*)/gi,
            blurregexp = / progid:\S+Blur\([^\)]+\)/g,
            val = /-?[^,\s-]+/g,
            coordsize = 1e3 + S + 1e3,
            zoom = 10,
            pathlike = {path: 1, rect: 1},
            path2vml = function (path) {
                var total =  /[ahqstv]/ig,
                    command = pathToAbsolute;
                Str(path).match(total) && (command = path2curve);
                total = /[clmz]/g;
                if (command == pathToAbsolute && !Str(path).match(total)) {
                    var res = Str(path)[rp](bites, function (all, command, args) {
                        var vals = [],
                            isMove = lowerCase.call(command) == "m",
                            res = map[command];
                        args[rp](val, function (value) {
                            if (isMove && vals[length] == 2) {
                                res += vals + map[command == "m" ? "l" : "L"];
                                vals = [];
                            }
                            vals[push](round(value * zoom));
                        });
                        return res + vals;
                    });
                    return res;
                }
                var pa = command(path), p, r;
                res = [];
                for (var i = 0, ii = pa[length]; i < ii; i++) {
                    p = pa[i];
                    r = lowerCase.call(pa[i][0]);
                    r == "z" && (r = "x");
                    for (var j = 1, jj = p[length]; j < jj; j++) {
                        r += round(p[j] * zoom) + (j != jj - 1 ? "," : E);
                    }
                    res[push](r);
                }
                return res[join](S);
            };
        
        R[toString] = function () {
            return  "Your browser doesn\u2019t support SVG. Falling down to VML.\nYou are running Rapha\xebl " + this.version;
        };
        thePath = function (pathString, vml) {
            var g = createNode("group");
            g.style.cssText = "position:absolute;left:0;top:0;width:" + vml.width + "px;height:" + vml.height + "px";
            g.coordsize = vml.coordsize;
            g.coordorigin = vml.coordorigin;
            var el = createNode("shape"), ol = el.style;
            ol.width = vml.width + "px";
            ol.height = vml.height + "px";
            el.coordsize = coordsize;
            el.coordorigin = vml.coordorigin;
            g[appendChild](el);
            var p = new Element(el, g, vml),
                attr = {fill: "none", stroke: "#000"};
            pathString && (attr.path = pathString);
            p.type = "path";
            p.path = [];
            p.Path = E;
            setFillAndStroke(p, attr);
            vml.canvas[appendChild](g);
            return p;
        };
        setFillAndStroke = function (o, params) {
            o.attrs = o.attrs || {};
            var node = o.node,
                a = o.attrs,
                s = node.style,
                xy,
                newpath = (params.x != a.x || params.y != a.y || params.width != a.width || params.height != a.height || params.r != a.r) && o.type == "rect",
                res = o;

            for (var par in params) if (params[has](par)) {
                a[par] = params[par];
            }
            if (newpath) {
                a.path = rectPath(a.x, a.y, a.width, a.height, a.r);
                o.X = a.x;
                o.Y = a.y;
                o.W = a.width;
                o.H = a.height;
            }
            params.href && (node.href = params.href);
            params.title && (node.title = params.title);
            params.target && (node.target = params.target);
            params.cursor && (s.cursor = params.cursor);
            "blur" in params && o.blur(params.blur);
            if (params.path && o.type == "path" || newpath) {
                node.path = path2vml(a.path);
            }
            if (params.rotation != null) {
                o.rotate(params.rotation, true);
            }
            if (params.translation) {
                xy = Str(params.translation)[split](separator);
                translate.call(o, xy[0], xy[1]);
                if (o._.rt.cx != null) {
                    o._.rt.cx +=+ xy[0];
                    o._.rt.cy +=+ xy[1];
                    o.setBox(o.attrs, xy[0], xy[1]);
                }
            }
            if (params.scale) {
                xy = Str(params.scale)[split](separator);
                o.scale(+xy[0] || 1, +xy[1] || +xy[0] || 1, +xy[2] || null, +xy[3] || null);
            }
            if ("clip-rect" in params) {
                var rect = Str(params["clip-rect"])[split](separator);
                if (rect[length] == 4) {
                    rect[2] = +rect[2] + (+rect[0]);
                    rect[3] = +rect[3] + (+rect[1]);
                    var div = node.clipRect || doc.createElement("div"),
                        dstyle = div.style,
                        group = node.parentNode;
                    dstyle.clip = R.format("rect({1}px {2}px {3}px {0}px)", rect);
                    if (!node.clipRect) {
                        dstyle.position = "absolute";
                        dstyle.top = 0;
                        dstyle.left = 0;
                        dstyle.width = o.paper.width + "px";
                        dstyle.height = o.paper.height + "px";
                        group.parentNode.insertBefore(div, group);
                        div[appendChild](group);
                        node.clipRect = div;
                    }
                }
                if (!params["clip-rect"]) {
                    node.clipRect && (node.clipRect.style.clip = E);
                }
            }
            if (o.type == "image" && params.src) {
                node.src = params.src;
            }
            if (o.type == "image" && params.opacity) {
                node.filterOpacity = ms + ".Alpha(opacity=" + (params.opacity * 100) + ")";
                s.filter = (node.filterMatrix || E) + (node.filterOpacity || E);
            }
            params.font && (s.font = params.font);
            params["font-family"] && (s.fontFamily = '"' + params["font-family"][split](",")[0][rp](/^['"]+|['"]+$/g, E) + '"');
            params["font-size"] && (s.fontSize = params["font-size"]);
            params["font-weight"] && (s.fontWeight = params["font-weight"]);
            params["font-style"] && (s.fontStyle = params["font-style"]);
            if (params.opacity != null || 
                params["stroke-width"] != null ||
                params.fill != null ||
                params.stroke != null ||
                params["stroke-width"] != null ||
                params["stroke-opacity"] != null ||
                params["fill-opacity"] != null ||
                params["stroke-dasharray"] != null ||
                params["stroke-miterlimit"] != null ||
                params["stroke-linejoin"] != null ||
                params["stroke-linecap"] != null) {
                node = o.shape || node;
                var fill = (node.getElementsByTagName(fillString) && node.getElementsByTagName(fillString)[0]),
                    newfill = false;
                !fill && (newfill = fill = createNode(fillString));
                if ("fill-opacity" in params || "opacity" in params) {
                    var opacity = ((+a["fill-opacity"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+R.getRGB(params.fill).o + 1 || 2) - 1);
                    opacity = mmin(mmax(opacity, 0), 1);
                    fill.opacity = opacity;
                }
                params.fill && (fill.on = true);
                if (fill.on == null || params.fill == "none") {
                    fill.on = false;
                }
                if (fill.on && params.fill) {
                    var isURL = params.fill.match(ISURL);
                    if (isURL) {
                        fill.src = isURL[1];
                        fill.type = "tile";
                    } else {
                        fill.color = R.getRGB(params.fill).hex;
                        fill.src = E;
                        fill.type = "solid";
                        if (R.getRGB(params.fill).error && (res.type in {circle: 1, ellipse: 1} || Str(params.fill).charAt() != "r") && addGradientFill(res, params.fill)) {
                            a.fill = "none";
                            a.gradient = params.fill;
                        }
                    }
                }
                newfill && node[appendChild](fill);
                var stroke = (node.getElementsByTagName("stroke") && node.getElementsByTagName("stroke")[0]),
                newstroke = false;
                !stroke && (newstroke = stroke = createNode("stroke"));
                if ((params.stroke && params.stroke != "none") ||
                    params["stroke-width"] ||
                    params["stroke-opacity"] != null ||
                    params["stroke-dasharray"] ||
                    params["stroke-miterlimit"] ||
                    params["stroke-linejoin"] ||
                    params["stroke-linecap"]) {
                    stroke.on = true;
                }
                (params.stroke == "none" || stroke.on == null || params.stroke == 0 || params["stroke-width"] == 0) && (stroke.on = false);
                var strokeColor = R.getRGB(params.stroke);
                stroke.on && params.stroke && (stroke.color = strokeColor.hex);
                opacity = ((+a["stroke-opacity"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+strokeColor.o + 1 || 2) - 1);
                var width = (toFloat(params["stroke-width"]) || 1) * .75;
                opacity = mmin(mmax(opacity, 0), 1);
                params["stroke-width"] == null && (width = a["stroke-width"]);
                params["stroke-width"] && (stroke.weight = width);
                width && width < 1 && (opacity *= width) && (stroke.weight = 1);
                stroke.opacity = opacity;
                
                params["stroke-linejoin"] && (stroke.joinstyle = params["stroke-linejoin"] || "miter");
                stroke.miterlimit = params["stroke-miterlimit"] || 8;
                params["stroke-linecap"] && (stroke.endcap = params["stroke-linecap"] == "butt" ? "flat" : params["stroke-linecap"] == "square" ? "square" : "round");
                if (params["stroke-dasharray"]) {
                    var dasharray = {
                        "-": "shortdash",
                        ".": "shortdot",
                        "-.": "shortdashdot",
                        "-..": "shortdashdotdot",
                        ". ": "dot",
                        "- ": "dash",
                        "--": "longdash",
                        "- .": "dashdot",
                        "--.": "longdashdot",
                        "--..": "longdashdotdot"
                    };
                    stroke.dashstyle = dasharray[has](params["stroke-dasharray"]) ? dasharray[params["stroke-dasharray"]] : E;
                }
                newstroke && node[appendChild](stroke);
            }
            if (res.type == "text") {
                s = res.paper.span.style;
                a.font && (s.font = a.font);
                a["font-family"] && (s.fontFamily = a["font-family"]);
                a["font-size"] && (s.fontSize = a["font-size"]);
                a["font-weight"] && (s.fontWeight = a["font-weight"]);
                a["font-style"] && (s.fontStyle = a["font-style"]);
                res.node.string && (res.paper.span.innerHTML = Str(res.node.string)[rp](/</g, "&#60;")[rp](/&/g, "&#38;")[rp](/\n/g, "<br>"));
                res.W = a.w = res.paper.span.offsetWidth;
                res.H = a.h = res.paper.span.offsetHeight;
                res.X = a.x;
                res.Y = a.y + round(res.H / 2);
 
                // text-anchor emulationm
                switch (a["text-anchor"]) {
                    case "start":
                        res.node.style["v-text-align"] = "left";
                        res.bbx = round(res.W / 2);
                    break;
                    case "end":
                        res.node.style["v-text-align"] = "right";
                        res.bbx = -round(res.W / 2);
                    break;
                    default:
                        res.node.style["v-text-align"] = "center";
                    break;
                }
            }
        };
        addGradientFill = function (o, gradient) {
            o.attrs = o.attrs || {};
            var attrs = o.attrs,
                fill,
                type = "linear",
                fxfy = ".5 .5";
            o.attrs.gradient = gradient;
            gradient = Str(gradient)[rp](radial_gradient, function (all, fx, fy) {
                type = "radial";
                if (fx && fy) {
                    fx = toFloat(fx);
                    fy = toFloat(fy);
                    pow(fx - .5, 2) + pow(fy - .5, 2) > .25 && (fy = math.sqrt(.25 - pow(fx - .5, 2)) * ((fy > .5) * 2 - 1) + .5);
                    fxfy = fx + S + fy;
                }
                return E;
            });
            gradient = gradient[split](/\s*\-\s*/);
            if (type == "linear") {
                var angle = gradient.shift();
                angle = -toFloat(angle);
                if (isNaN(angle)) {
                    return null;
                }
            }
            var dots = parseDots(gradient);
            if (!dots) {
                return null;
            }
            o = o.shape || o.node;
            fill = o.getElementsByTagName(fillString)[0] || createNode(fillString);
            !fill.parentNode && o.appendChild(fill);
            if (dots[length]) {
                fill.on = true;
                fill.method = "none";
                fill.color = dots[0].color;
                fill.color2 = dots[dots[length] - 1].color;
                var clrs = [];
                for (var i = 0, ii = dots[length]; i < ii; i++) {
                    dots[i].offset && clrs[push](dots[i].offset + S + dots[i].color);
                }
                fill.colors && (fill.colors.value = clrs[length] ? clrs[join]() : "0% " + fill.color);
                if (type == "radial") {
                    fill.type = "gradientradial";
                    fill.focus = "100%";
                    fill.focussize = fxfy;
                    fill.focusposition = fxfy;
                } else {
                    fill.type = "gradient";
                    fill.angle = (270 - angle) % 360;
                }
            }
            return 1;
        };
        Element = function (node, group, vml) {
            var Rotation = 0,
                RotX = 0,
                RotY = 0,
                Scale = 1;
            this[0] = node;
            this.id = R._oid++;
            this.node = node;
            node.raphael = this;
            this.X = 0;
            this.Y = 0;
            this.attrs = {};
            this.Group = group;
            this.paper = vml;
            this._ = {
                tx: 0,
                ty: 0,
                rt: {deg:0},
                sx: 1,
                sy: 1
            };
            !vml.bottom && (vml.bottom = this);
            this.prev = vml.top;
            vml.top && (vml.top.next = this);
            vml.top = this;
            this.next = null;
        };
        elproto = Element[proto];
        elproto.rotate = function (deg, cx, cy) {
            if (this.removed) {
                return this;
            }
            if (deg == null) {
                if (this._.rt.cx) {
                    return [this._.rt.deg, this._.rt.cx, this._.rt.cy][join](S);
                }
                return this._.rt.deg;
            }
            deg = Str(deg)[split](separator);
            if (deg[length] - 1) {
                cx = toFloat(deg[1]);
                cy = toFloat(deg[2]);
            }
            deg = toFloat(deg[0]);
            if (cx != null) {
                this._.rt.deg = deg;
            } else {
                this._.rt.deg += deg;
            }
            cy == null && (cx = null);
            this._.rt.cx = cx;
            this._.rt.cy = cy;
            this.setBox(this.attrs, cx, cy);
            this.Group.style.rotation = this._.rt.deg;
            // gradient fix for rotation. TODO
            // var fill = (this.shape || this.node).getElementsByTagName(fillString);
            // fill = fill[0] || {};
            // var b = ((360 - this._.rt.deg) - 270) % 360;
            // !R.is(fill.angle, "undefined") && (fill.angle = b);
            return this;
        };
        elproto.setBox = function (params, cx, cy) {
            if (this.removed) {
                return this;
            }
            var gs = this.Group.style,
                os = (this.shape && this.shape.style) || this.node.style;
            params = params || {};
            for (var i in params) if (params[has](i)) {
                this.attrs[i] = params[i];
            }
            cx = cx || this._.rt.cx;
            cy = cy || this._.rt.cy;
            var attr = this.attrs,
                x,
                y,
                w,
                h;
            switch (this.type) {
                case "circle":
                    x = attr.cx - attr.r;
                    y = attr.cy - attr.r;
                    w = h = attr.r * 2;
                    break;
                case "ellipse":
                    x = attr.cx - attr.rx;
                    y = attr.cy - attr.ry;
                    w = attr.rx * 2;
                    h = attr.ry * 2;
                    break;
                case "image":
                    x = +attr.x;
                    y = +attr.y;
                    w = attr.width || 0;
                    h = attr.height || 0;
                    break;
                case "text":
                    this.textpath.v = ["m", round(attr.x), ", ", round(attr.y - 2), "l", round(attr.x) + 1, ", ", round(attr.y - 2)][join](E);
                    x = attr.x - round(this.W / 2);
                    y = attr.y - this.H / 2;
                    w = this.W;
                    h = this.H;
                    break;
                case "rect":
                case "path":
                    if (!this.attrs.path) {
                        x = 0;
                        y = 0;
                        w = this.paper.width;
                        h = this.paper.height;
                    } else {
                        var dim = pathDimensions(this.attrs.path);
                        x = dim.x;
                        y = dim.y;
                        w = dim.width;
                        h = dim.height;
                    }
                    break;
                default:
                    x = 0;
                    y = 0;
                    w = this.paper.width;
                    h = this.paper.height;
                    break;
            }
            cx = (cx == null) ? x + w / 2 : cx;
            cy = (cy == null) ? y + h / 2 : cy;
            var left = cx - this.paper.width / 2,
                top = cy - this.paper.height / 2, t;
            gs.left != (t = left + "px") && (gs.left = t);
            gs.top != (t = top + "px") && (gs.top = t);
            this.X = pathlike[has](this.type) ? -left : x;
            this.Y = pathlike[has](this.type) ? -top : y;
            this.W = w;
            this.H = h;
            if (pathlike[has](this.type)) {
                os.left != (t = -left * zoom + "px") && (os.left = t);
                os.top != (t = -top * zoom + "px") && (os.top = t);
            } else if (this.type == "text") {
                os.left != (t = -left + "px") && (os.left = t);
                os.top != (t = -top + "px") && (os.top = t);
            } else {
                gs.width != (t = this.paper.width + "px") && (gs.width = t);
                gs.height != (t = this.paper.height + "px") && (gs.height = t);
                os.left != (t = x - left + "px") && (os.left = t);
                os.top != (t = y - top + "px") && (os.top = t);
                os.width != (t = w + "px") && (os.width = t);
                os.height != (t = h + "px") && (os.height = t);
            }
        };
        elproto.hide = function () {
            !this.removed && (this.Group.style.display = "none");
            return this;
        };
        elproto.show = function () {
            !this.removed && (this.Group.style.display = "block");
            return this;
        };
        elproto.getBBox = function () {
            if (this.removed) {
                return this;
            }
            if (pathlike[has](this.type)) {
                return pathDimensions(this.attrs.path);
            }
            return {
                x: this.X + (this.bbx || 0),
                y: this.Y,
                width: this.W,
                height: this.H
            };
        };
        elproto.remove = function () {
            if (this.removed) {
                return;
            }
            tear(this, this.paper);
            this.node.parentNode.removeChild(this.node);
            this.Group.parentNode.removeChild(this.Group);
            this.shape && this.shape.parentNode.removeChild(this.shape);
            for (var i in this) {
                delete this[i];
            }
            this.removed = true;
        };
        elproto.attr = function (name, value) {
            if (this.removed) {
                return this;
            }
            if (name == null) {
                var res = {};
                for (var i in this.attrs) if (this.attrs[has](i)) {
                    res[i] = this.attrs[i];
                }
                this._.rt.deg && (res.rotation = this.rotate());
                (this._.sx != 1 || this._.sy != 1) && (res.scale = this.scale());
                res.gradient && res.fill == "none" && (res.fill = res.gradient) && delete res.gradient;
                return res;
            }
            if (value == null && R.is(name, "string")) {
                if (name == "translation") {
                    return translate.call(this);
                }
                if (name == "rotation") {
                    return this.rotate();
                }
                if (name == "scale") {
                    return this.scale();
                }
                if (name == fillString && this.attrs.fill == "none" && this.attrs.gradient) {
                    return this.attrs.gradient;
                }
                return this.attrs[name];
            }
            if (this.attrs && value == null && R.is(name, array)) {
                var ii, values = {};
                for (i = 0, ii = name[length]; i < ii; i++) {
                    values[name[i]] = this.attr(name[i]);
                }
                return values;
            }
            var params;
            if (value != null) {
                params = {};
                params[name] = value;
            }
            value == null && R.is(name, "object") && (params = name);
            if (params) {
                for (var key in this.paper.customAttributes) if (this.paper.customAttributes[has](key) && params[has](key) && R.is(this.paper.customAttributes[key], "function")) {
                    var par = this.paper.customAttributes[key].apply(this, [][concat](params[key]));
                    this.attrs[key] = params[key];
                    for (var subkey in par) if (par[has](subkey)) {
                        params[subkey] = par[subkey];
                    }
                }
                if (params.text && this.type == "text") {
                    this.node.string = params.text;
                }
                setFillAndStroke(this, params);
                if (params.gradient && (({circle: 1, ellipse: 1})[has](this.type) || Str(params.gradient).charAt() != "r")) {
                    addGradientFill(this, params.gradient);
                }
                (!pathlike[has](this.type) || this._.rt.deg) && this.setBox(this.attrs);
            }
            return this;
        };
        elproto.toFront = function () {
            !this.removed && this.Group.parentNode[appendChild](this.Group);
            this.paper.top != this && tofront(this, this.paper);
            return this;
        };
        elproto.toBack = function () {
            if (this.removed) {
                return this;
            }
            if (this.Group.parentNode.firstChild != this.Group) {
                this.Group.parentNode.insertBefore(this.Group, this.Group.parentNode.firstChild);
                toback(this, this.paper);
            }
            return this;
        };
        elproto.insertAfter = function (element) {
            if (this.removed) {
                return this;
            }
            if (element.constructor == Set) {
                element = element[element.length - 1];
            }
            if (element.Group.nextSibling) {
                element.Group.parentNode.insertBefore(this.Group, element.Group.nextSibling);
            } else {
                element.Group.parentNode[appendChild](this.Group);
            }
            insertafter(this, element, this.paper);
            return this;
        };
        elproto.insertBefore = function (element) {
            if (this.removed) {
                return this;
            }
            if (element.constructor == Set) {
                element = element[0];
            }
            element.Group.parentNode.insertBefore(this.Group, element.Group);
            insertbefore(this, element, this.paper);
            return this;
        };
        elproto.blur = function (size) {
            var s = this.node.runtimeStyle,
                f = s.filter;
            f = f.replace(blurregexp, E);
            if (+size !== 0) {
                this.attrs.blur = size;
                s.filter = f + S + ms + ".Blur(pixelradius=" + (+size || 1.5) + ")";
                s.margin = R.format("-{0}px 0 0 -{0}px", round(+size || 1.5));
            } else {
                s.filter = f;
                s.margin = 0;
                delete this.attrs.blur;
            }
        };
 
        theCircle = function (vml, x, y, r) {
            var g = createNode("group"),
                o = createNode("oval"),
                ol = o.style;
            g.style.cssText = "position:absolute;left:0;top:0;width:" + vml.width + "px;height:" + vml.height + "px";
            g.coordsize = coordsize;
            g.coordorigin = vml.coordorigin;
            g[appendChild](o);
            var res = new Element(o, g, vml);
            res.type = "circle";
            setFillAndStroke(res, {stroke: "#000", fill: "none"});
            res.attrs.cx = x;
            res.attrs.cy = y;
            res.attrs.r = r;
            res.setBox({x: x - r, y: y - r, width: r * 2, height: r * 2});
            vml.canvas[appendChild](g);
            return res;
        };
        function rectPath(x, y, w, h, r) {
            if (r) {
                return R.format("M{0},{1}l{2},0a{3},{3},0,0,1,{3},{3}l0,{5}a{3},{3},0,0,1,{4},{3}l{6},0a{3},{3},0,0,1,{4},{4}l0,{7}a{3},{3},0,0,1,{3},{4}z", x + r, y, w - r * 2, r, -r, h - r * 2, r * 2 - w, r * 2 - h);
            } else {
                return R.format("M{0},{1}l{2},0,0,{3},{4},0z", x, y, w, h, -w);
            }
        }
        theRect = function (vml, x, y, w, h, r) {
            var path = rectPath(x, y, w, h, r),
                res = vml.path(path),
                a = res.attrs;
            res.X = a.x = x;
            res.Y = a.y = y;
            res.W = a.width = w;
            res.H = a.height = h;
            a.r = r;
            a.path = path;
            res.type = "rect";
            return res;
        };
        theEllipse = function (vml, x, y, rx, ry) {
            var g = createNode("group"),
                o = createNode("oval"),
                ol = o.style;
            g.style.cssText = "position:absolute;left:0;top:0;width:" + vml.width + "px;height:" + vml.height + "px";
            g.coordsize = coordsize;
            g.coordorigin = vml.coordorigin;
            g[appendChild](o);
            var res = new Element(o, g, vml);
            res.type = "ellipse";
            setFillAndStroke(res, {stroke: "#000"});
            res.attrs.cx = x;
            res.attrs.cy = y;
            res.attrs.rx = rx;
            res.attrs.ry = ry;
            res.setBox({x: x - rx, y: y - ry, width: rx * 2, height: ry * 2});
            vml.canvas[appendChild](g);
            return res;
        };
        theImage = function (vml, src, x, y, w, h) {
            var g = createNode("group"),
                o = createNode("image");
            g.style.cssText = "position:absolute;left:0;top:0;width:" + vml.width + "px;height:" + vml.height + "px";
            g.coordsize = coordsize;
            g.coordorigin = vml.coordorigin;
            o.src = src;
            g[appendChild](o);
            var res = new Element(o, g, vml);
            res.type = "image";
            res.attrs.src = src;
            res.attrs.x = x;
            res.attrs.y = y;
            res.attrs.w = w;
            res.attrs.h = h;
            res.setBox({x: x, y: y, width: w, height: h});
            vml.canvas[appendChild](g);
            return res;
        };
        theText = function (vml, x, y, text) {
            var g = createNode("group"),
                el = createNode("shape"),
                ol = el.style,
                path = createNode("path"),
                ps = path.style,
                o = createNode("textpath");
            g.style.cssText = "position:absolute;left:0;top:0;width:" + vml.width + "px;height:" + vml.height + "px";
            g.coordsize = coordsize;
            g.coordorigin = vml.coordorigin;
            path.v = R.format("m{0},{1}l{2},{1}", round(x * 10), round(y * 10), round(x * 10) + 1);
            path.textpathok = true;
            ol.width = vml.width;
            ol.height = vml.height;
            o.string = Str(text);
            o.on = true;
            el[appendChild](o);
            el[appendChild](path);
            g[appendChild](el);
            var res = new Element(o, g, vml);
            res.shape = el;
            res.textpath = path;
            res.type = "text";
            res.attrs.text = text;
            res.attrs.x = x;
            res.attrs.y = y;
            res.attrs.w = 1;
            res.attrs.h = 1;
            setFillAndStroke(res, {font: availableAttrs.font, stroke: "none", fill: "#000"});
            res.setBox();
            vml.canvas[appendChild](g);
            return res;
        };
        setSize = function (width, height) {
            var cs = this.canvas.style;
            width == +width && (width += "px");
            height == +height && (height += "px");
            cs.width = width;
            cs.height = height;
            cs.clip = "rect(0 " + width + " " + height + " 0)";
            return this;
        };
        var createNode;
        doc.createStyleSheet().addRule(".rvml", "behavior:url(#default#VML)");
        try {
            !doc.namespaces.rvml && doc.namespaces.add("rvml", "urn:schemas-microsoft-com:vml");
            createNode = function (tagName) {
                return doc.createElement('<rvml:' + tagName + ' class="rvml">');
            };
        } catch (e) {
            createNode = function (tagName) {
                return doc.createElement('<' + tagName + ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">');
            };
        }
        create = function () {
            var con = getContainer[apply](0, arguments),
                container = con.container,
                height = con.height,
                s,
                width = con.width,
                x = con.x,
                y = con.y;
            if (!container) {
                throw new Error("VML container not found.");
            }
            var res = new Paper,
                c = res.canvas = doc.createElement("div"),
                cs = c.style;
            x = x || 0;
            y = y || 0;
            width = width || 512;
            height = height || 342;
            width == +width && (width += "px");
            height == +height && (height += "px");
            res.width = 1e3;
            res.height = 1e3;
            res.coordsize = zoom * 1e3 + S + zoom * 1e3;
            res.coordorigin = "0 0";
            res.span = doc.createElement("span");
            res.span.style.cssText = "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";
            c[appendChild](res.span);
            cs.cssText = R.format("top:0;left:0;width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden", width, height);
            if (container == 1) {
                doc.body[appendChild](c);
                cs.left = x + "px";
                cs.top = y + "px";
                cs.position = "absolute";
            } else {
                if (container.firstChild) {
                    container.insertBefore(c, container.firstChild);
                } else {
                    container[appendChild](c);
                }
            }
            plugins.call(res, res, R.fn);
            return res;
        };
        paperproto.clear = function () {
            this.canvas.innerHTML = E;
            this.span = doc.createElement("span");
            this.span.style.cssText = "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";
            this.canvas[appendChild](this.span);
            this.bottom = this.top = null;
        };
        paperproto.remove = function () {
            this.canvas.parentNode.removeChild(this.canvas);
            for (var i in this) {
                this[i] = removed(i);
            }
            return true;
        };
    }
 
    // rest
    // WebKit rendering bug workaround method
    var version = navigator.userAgent.match(/Version\/(.*?)\s/);
    if ((navigator.vendor == "Apple Computer, Inc.") && (version && version[1] < 4 || navigator.platform.slice(0, 2) == "iP")) {
        paperproto.safari = function () {
            var rect = this.rect(-99, -99, this.width + 99, this.height + 99).attr({stroke: "none"});
            win.setTimeout(function () {rect.remove();});
        };
    } else {
        paperproto.safari = function () {};
    }
 
    // Events
    var preventDefault = function () {
        this.returnValue = false;
    },
    preventTouch = function () {
        return this.originalEvent.preventDefault();
    },
    stopPropagation = function () {
        this.cancelBubble = true;
    },
    stopTouch = function () {
        return this.originalEvent.stopPropagation();
    },
    addEvent = (function () {
        if (doc.addEventListener) {
            return function (obj, type, fn, element) {
                var realName = supportsTouch && touchMap[type] ? touchMap[type] : type;
                var f = function (e) {
                    if (supportsTouch && touchMap[has](type)) {
                        for (var i = 0, ii = e.targetTouches && e.targetTouches.length; i < ii; i++) {
                            if (e.targetTouches[i].target == obj) {
                                var olde = e;
                                e = e.targetTouches[i];
                                e.originalEvent = olde;
                                e.preventDefault = preventTouch;
                                e.stopPropagation = stopTouch;
                                break;
                            }
                        }
                    }
                    return fn.call(element, e);
                };
                obj.addEventListener(realName, f, false);
                return function () {
                    obj.removeEventListener(realName, f, false);
                    return true;
                };
            };
        } else if (doc.attachEvent) {
            return function (obj, type, fn, element) {
                var f = function (e) {
                    e = e || win.event;
                    e.preventDefault = e.preventDefault || preventDefault;
                    e.stopPropagation = e.stopPropagation || stopPropagation;
                    return fn.call(element, e);
                };
                obj.attachEvent("on" + type, f);
                var detacher = function () {
                    obj.detachEvent("on" + type, f);
                    return true;
                };
                return detacher;
            };
        }
    })(),
    drag = [],
    dragMove = function (e) {
        var x = e.clientX,
            y = e.clientY,
            scrollY = doc.documentElement.scrollTop || doc.body.scrollTop,
            scrollX = doc.documentElement.scrollLeft || doc.body.scrollLeft,
            dragi,
            j = drag.length;
        while (j--) {
            dragi = drag[j];
            if (supportsTouch) {
                var i = e.touches.length,
                    touch;
                while (i--) {
                    touch = e.touches[i];
                    if (touch.identifier == dragi.el._drag.id) {
                        x = touch.clientX;
                        y = touch.clientY;
                        (e.originalEvent ? e.originalEvent : e).preventDefault();
                        break;
                    }
                }
            } else {
                e.preventDefault();
            }
            x += scrollX;
            y += scrollY;
            dragi.move && dragi.move.call(dragi.move_scope || dragi.el, x - dragi.el._drag.x, y - dragi.el._drag.y, x, y, e);
        }
    },
    dragUp = function (e) {
        R.unmousemove(dragMove).unmouseup(dragUp);
        var i = drag.length,
            dragi;
        while (i--) {
            dragi = drag[i];
            dragi.el._drag = {};
            dragi.end && dragi.end.call(dragi.end_scope || dragi.start_scope || dragi.move_scope || dragi.el, e);
        }
        drag = [];
    };
    for (var i = events[length]; i--;) {
        (function (eventName) {
            R[eventName] = Element[proto][eventName] = function (fn, scope) {
                if (R.is(fn, "function")) {
                    this.events = this.events || [];
                    this.events.push({name: eventName, f: fn, unbind: addEvent(this.shape || this.node || doc, eventName, fn, scope || this)});
                }
                return this;
            };
            R["un" + eventName] = Element[proto]["un" + eventName] = function (fn) {
                var events = this.events,
                    l = events[length];
                while (l--) if (events[l].name == eventName && events[l].f == fn) {
                    events[l].unbind();
                    events.splice(l, 1);
                    !events.length && delete this.events;
                    return this;
                }
                return this;
            };
        })(events[i]);
    }
    elproto.hover = function (f_in, f_out, scope_in, scope_out) {
        return this.mouseover(f_in, scope_in).mouseout(f_out, scope_out || scope_in);
    };
    elproto.unhover = function (f_in, f_out) {
        return this.unmouseover(f_in).unmouseout(f_out);
    };
    elproto.drag = function (onmove, onstart, onend, move_scope, start_scope, end_scope) {
        this._drag = {};
        this.mousedown(function (e) {
            (e.originalEvent || e).preventDefault();
            var scrollY = doc.documentElement.scrollTop || doc.body.scrollTop,
                scrollX = doc.documentElement.scrollLeft || doc.body.scrollLeft;
            this._drag.x = e.clientX + scrollX;
            this._drag.y = e.clientY + scrollY;
            this._drag.id = e.identifier;
            onstart && onstart.call(start_scope || move_scope || this, e.clientX + scrollX, e.clientY + scrollY, e);
            !drag.length && R.mousemove(dragMove).mouseup(dragUp);
            drag.push({el: this, move: onmove, end: onend, move_scope: move_scope, start_scope: start_scope, end_scope: end_scope});
        });
        return this;
    };
    elproto.undrag = function (onmove, onstart, onend) {
        var i = drag.length;
        while (i--) {
            drag[i].el == this && (drag[i].move == onmove && drag[i].end == onend) && drag.splice(i++, 1);
        }
        !drag.length && R.unmousemove(dragMove).unmouseup(dragUp);
    };
    paperproto.circle = function (x, y, r) {
        return theCircle(this, x || 0, y || 0, r || 0);
    };
    paperproto.rect = function (x, y, w, h, r) {
        return theRect(this, x || 0, y || 0, w || 0, h || 0, r || 0);
    };
    paperproto.ellipse = function (x, y, rx, ry) {
        return theEllipse(this, x || 0, y || 0, rx || 0, ry || 0);
    };
    paperproto.path = function (pathString) {
        pathString && !R.is(pathString, string) && !R.is(pathString[0], array) && (pathString += E);
        return thePath(R.format[apply](R, arguments), this);
    };
    paperproto.image = function (src, x, y, w, h) {
        return theImage(this, src || "about:blank", x || 0, y || 0, w || 0, h || 0);
    };
    paperproto.text = function (x, y, text) {
        return theText(this, x || 0, y || 0, Str(text));
    };
    paperproto.set = function (itemsArray) {
        arguments[length] > 1 && (itemsArray = Array[proto].splice.call(arguments, 0, arguments[length]));
        return new Set(itemsArray);
    };
    paperproto.setSize = setSize;
    paperproto.top = paperproto.bottom = null;
    paperproto.raphael = R;
    function x_y() {
        return this.x + S + this.y;
    }
    elproto.resetScale = function () {
        if (this.removed) {
            return this;
        }
        this._.sx = 1;
        this._.sy = 1;
        this.attrs.scale = "1 1";
    };
    elproto.scale = function (x, y, cx, cy) {
        if (this.removed) {
            return this;
        }
        if (x == null && y == null) {
            return {
                x: this._.sx,
                y: this._.sy,
                toString: x_y
            };
        }
        y = y || x;
        !+y && (y = x);
        var dx,
            dy,
            dcx,
            dcy,
            a = this.attrs;
        if (x != 0) {
            var bb = this.getBBox(),
                rcx = bb.x + bb.width / 2,
                rcy = bb.y + bb.height / 2,
                kx = abs(x / this._.sx),
                ky = abs(y / this._.sy);
            cx = (+cx || cx == 0) ? cx : rcx;
            cy = (+cy || cy == 0) ? cy : rcy;
            var posx = this._.sx > 0,
                posy = this._.sy > 0,
                dirx = ~~(x / abs(x)),
                diry = ~~(y / abs(y)),
                dkx = kx * dirx,
                dky = ky * diry,
                s = this.node.style,
                ncx = cx + abs(rcx - cx) * dkx * (rcx > cx == posx ? 1 : -1),
                ncy = cy + abs(rcy - cy) * dky * (rcy > cy == posy ? 1 : -1),
                fr = (x * dirx > y * diry ? ky : kx);
            switch (this.type) {
                case "rect":
                case "image":
                    var neww = a.width * kx,
                        newh = a.height * ky;
                    this.attr({
                        height: newh,
                        r: a.r * fr,
                        width: neww,
                        x: ncx - neww / 2,
                        y: ncy - newh / 2
                    });
                    break;
                case "circle":
                case "ellipse":
                    this.attr({
                        rx: a.rx * kx,
                        ry: a.ry * ky,
                        r: a.r * fr,
                        cx: ncx,
                        cy: ncy
                    });
                    break;
                case "text":
                    this.attr({
                        x: ncx,
                        y: ncy
                    });
                    break;
                case "path":
                    var path = pathToRelative(a.path),
                        skip = true,
                        fx = posx ? dkx : kx,
                        fy = posy ? dky : ky;
                    for (var i = 0, ii = path[length]; i < ii; i++) {
                        var p = path[i],
                            P0 = upperCase.call(p[0]);
                        if (P0 == "M" && skip) {
                            continue;
                        } else {
                            skip = false;
                        }
                        if (P0 == "A") {
                            p[path[i][length] - 2] *= fx;
                            p[path[i][length] - 1] *= fy;
                            p[1] *= kx;
                            p[2] *= ky;
                            p[5] = +(dirx + diry ? !!+p[5] : !+p[5]);
                        } else if (P0 == "H") {
                            for (var j = 1, jj = p[length]; j < jj; j++) {
                                p[j] *= fx;
                            }
                        } else if (P0 == "V") {
                            for (j = 1, jj = p[length]; j < jj; j++) {
                                p[j] *= fy;
                            }
                         } else {
                            for (j = 1, jj = p[length]; j < jj; j++) {
                                p[j] *= (j % 2) ? fx : fy;
                            }
                        }
                    }
                    var dim2 = pathDimensions(path);
                    dx = ncx - dim2.x - dim2.width / 2;
                    dy = ncy - dim2.y - dim2.height / 2;
                    path[0][1] += dx;
                    path[0][2] += dy;
                    this.attr({path: path});
                break;
            }
            if (this.type in {text: 1, image:1} && (dirx != 1 || diry != 1)) {
                if (this.transformations) {
                    this.transformations[2] = "scale("[concat](dirx, ",", diry, ")");
                    this.node[setAttribute]("transform", this.transformations[join](S));
                    dx = (dirx == -1) ? -a.x - (neww || 0) : a.x;
                    dy = (diry == -1) ? -a.y - (newh || 0) : a.y;
                    this.attr({x: dx, y: dy});
                    a.fx = dirx - 1;
                    a.fy = diry - 1;
                } else {
                    this.node.filterMatrix = ms + ".Matrix(M11="[concat](dirx,
                        ", M12=0, M21=0, M22=", diry,
                        ", Dx=0, Dy=0, sizingmethod='auto expand', filtertype='bilinear')");
                    s.filter = (this.node.filterMatrix || E) + (this.node.filterOpacity || E);
                }
            } else {
                if (this.transformations) {
                    this.transformations[2] = E;
                    this.node[setAttribute]("transform", this.transformations[join](S));
                    a.fx = 0;
                    a.fy = 0;
                } else {
                    this.node.filterMatrix = E;
                    s.filter = (this.node.filterMatrix || E) + (this.node.filterOpacity || E);
                }
            }
            a.scale = [x, y, cx, cy][join](S);
            this._.sx = x;
            this._.sy = y;
        }
        return this;
    };
    elproto.clone = function () {
        if (this.removed) {
            return null;
        }
        var attr = this.attr();
        delete attr.scale;
        delete attr.translation;
        return this.paper[this.type]().attr(attr);
    };
    var curveslengths = {},
    getPointAtSegmentLength = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length) {
        var len = 0,
            precision = 100,
            name = [p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y].join(),
            cache = curveslengths[name],
            old, dot;
        !cache && (curveslengths[name] = cache = {data: []});
        cache.timer && clearTimeout(cache.timer);
        cache.timer = setTimeout(function () {delete curveslengths[name];}, 2000);
        if (length != null) {
            var total = getPointAtSegmentLength(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y);
            precision = ~~total * 10;
        }
        for (var i = 0; i < precision + 1; i++) {
            if (cache.data[length] > i) {
                dot = cache.data[i * precision];
            } else {
                dot = R.findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, i / precision);
                cache.data[i] = dot;
            }
            i && (len += pow(pow(old.x - dot.x, 2) + pow(old.y - dot.y, 2), .5));
            if (length != null && len >= length) {
                return dot;
            }
            old = dot;
        }
        if (length == null) {
            return len;
        }
    },
    getLengthFactory = function (istotal, subpath) {
        return function (path, length, onlystart) {
            path = path2curve(path);
            var x, y, p, l, sp = "", subpaths = {}, point,
                len = 0;
            for (var i = 0, ii = path.length; i < ii; i++) {
                p = path[i];
                if (p[0] == "M") {
                    x = +p[1];
                    y = +p[2];
                } else {
                    l = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);
                    if (len + l > length) {
                        if (subpath && !subpaths.start) {
                            point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len);
                            sp += ["C", point.start.x, point.start.y, point.m.x, point.m.y, point.x, point.y];
                            if (onlystart) {return sp;}
                            subpaths.start = sp;
                            sp = ["M", point.x, point.y + "C", point.n.x, point.n.y, point.end.x, point.end.y, p[5], p[6]][join]();
                            len += l;
                            x = +p[5];
                            y = +p[6];
                            continue;
                        }
                        if (!istotal && !subpath) {
                            point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len);
                            return {x: point.x, y: point.y, alpha: point.alpha};
                        }
                    }
                    len += l;
                    x = +p[5];
                    y = +p[6];
                }
                sp += p;
            }
            subpaths.end = sp;
            point = istotal ? len : subpath ? subpaths : R.findDotsAtSegment(x, y, p[1], p[2], p[3], p[4], p[5], p[6], 1);
            point.alpha && (point = {x: point.x, y: point.y, alpha: point.alpha});
            return point;
        };
    };
    var getTotalLength = getLengthFactory(1),
        getPointAtLength = getLengthFactory(),
        getSubpathsAtLength = getLengthFactory(0, 1);
    elproto.getTotalLength = function () {
        if (this.type != "path") {return;}
        if (this.node.getTotalLength) {
            return this.node.getTotalLength();
        }
        return getTotalLength(this.attrs.path);
    };
    elproto.getPointAtLength = function (length) {
        if (this.type != "path") {return;}
        return getPointAtLength(this.attrs.path, length);
    };
    elproto.getSubpath = function (from, to) {
        if (this.type != "path") {return;}
        if (abs(this.getTotalLength() - to) < "1e-6") {
            return getSubpathsAtLength(this.attrs.path, from).end;
        }
        var a = getSubpathsAtLength(this.attrs.path, to, 1);
        return from ? getSubpathsAtLength(a, from).end : a;
    };

    // animation easing formulas
    R.easing_formulas = {
        linear: function (n) {
            return n;
        },
        "<": function (n) {
            return pow(n, 3);
        },
        ">": function (n) {
            return pow(n - 1, 3) + 1;
        },
        "<>": function (n) {
            n = n * 2;
            if (n < 1) {
                return pow(n, 3) / 2;
            }
            n -= 2;
            return (pow(n, 3) + 2) / 2;
        },
        backIn: function (n) {
            var s = 1.70158;
            return n * n * ((s + 1) * n - s);
        },
        backOut: function (n) {
            n = n - 1;
            var s = 1.70158;
            return n * n * ((s + 1) * n + s) + 1;
        },
        elastic: function (n) {
            if (n == 0 || n == 1) {
                return n;
            }
            var p = .3,
                s = p / 4;
            return pow(2, -10 * n) * math.sin((n - s) * (2 * PI) / p) + 1;
        },
        bounce: function (n) {
            var s = 7.5625,
                p = 2.75,
                l;
            if (n < (1 / p)) {
                l = s * n * n;
            } else {
                if (n < (2 / p)) {
                    n -= (1.5 / p);
                    l = s * n * n + .75;
                } else {
                    if (n < (2.5 / p)) {
                        n -= (2.25 / p);
                        l = s * n * n + .9375;
                    } else {
                        n -= (2.625 / p);
                        l = s * n * n + .984375;
                    }
                }
            }
            return l;
        }
    };

    var animationElements = [],
        animation = function () {
            var Now = +new Date;
            for (var l = 0; l < animationElements[length]; l++) {
                var e = animationElements[l];
                if (e.stop || e.el.removed) {
                    continue;
                }
                var time = Now - e.start,
                    ms = e.ms,
                    easing = e.easing,
                    from = e.from,
                    diff = e.diff,
                    to = e.to,
                    t = e.t,
                    that = e.el,
                    set = {},
                    now;
                if (time < ms) {
                    var pos = easing(time / ms);
                    for (var attr in from) if (from[has](attr)) {
                        switch (availableAnimAttrs[attr]) {
                            case "along":
                                now = pos * ms * diff[attr];
                                to.back && (now = to.len - now);
                                var point = getPointAtLength(to[attr], now);
                                that.translate(diff.sx - diff.x || 0, diff.sy - diff.y || 0);
                                diff.x = point.x;
                                diff.y = point.y;
                                that.translate(point.x - diff.sx, point.y - diff.sy);
                                to.rot && that.rotate(diff.r + point.alpha, point.x, point.y);
                                break;
                            case nu:
                                now = +from[attr] + pos * ms * diff[attr];
                                break;
                            case "colour":
                                now = "rgb(" + [
                                    upto255(round(from[attr].r + pos * ms * diff[attr].r)),
                                    upto255(round(from[attr].g + pos * ms * diff[attr].g)),
                                    upto255(round(from[attr].b + pos * ms * diff[attr].b))
                                ][join](",") + ")";
                                break;
                            case "path":
                                now = [];
                                for (var i = 0, ii = from[attr][length]; i < ii; i++) {
                                    now[i] = [from[attr][i][0]];
                                    for (var j = 1, jj = from[attr][i][length]; j < jj; j++) {
                                        now[i][j] = +from[attr][i][j] + pos * ms * diff[attr][i][j];
                                    }
                                    now[i] = now[i][join](S);
                                }
                                now = now[join](S);
                                break;
                            case "csv":
                                switch (attr) {
                                    case "translation":
                                        var x = pos * ms * diff[attr][0] - t.x,
                                            y = pos * ms * diff[attr][1] - t.y;
                                        t.x += x;
                                        t.y += y;
                                        now = x + S + y;
                                    break;
                                    case "rotation":
                                        now = +from[attr][0] + pos * ms * diff[attr][0];
                                        from[attr][1] && (now += "," + from[attr][1] + "," + from[attr][2]);
                                    break;
                                    case "scale":
                                        now = [+from[attr][0] + pos * ms * diff[attr][0], +from[attr][1] + pos * ms * diff[attr][1], (2 in to[attr] ? to[attr][2] : E), (3 in to[attr] ? to[attr][3] : E)][join](S);
                                    break;
                                    case "clip-rect":
                                        now = [];
                                        i = 4;
                                        while (i--) {
                                            now[i] = +from[attr][i] + pos * ms * diff[attr][i];
                                        }
                                    break;
                                }
                                break;
                            default:
                              var from2 = [].concat(from[attr]);
                                now = [];
                                i = that.paper.customAttributes[attr].length;
                                while (i--) {
                                    now[i] = +from2[i] + pos * ms * diff[attr][i];
                                }
                                break;
                        }
                        set[attr] = now;
                    }
                    that.attr(set);
                    that._run && that._run.call(that);
                } else {
                    if (to.along) {
                        point = getPointAtLength(to.along, to.len * !to.back);
                        that.translate(diff.sx - (diff.x || 0) + point.x - diff.sx, diff.sy - (diff.y || 0) + point.y - diff.sy);
                        to.rot && that.rotate(diff.r + point.alpha, point.x, point.y);
                    }
                    (t.x || t.y) && that.translate(-t.x, -t.y);
                    to.scale && (to.scale += E);
                    that.attr(to);
                    animationElements.splice(l--, 1);
                }
            }
            R.svg && that && that.paper && that.paper.safari();
            animationElements[length] && setTimeout(animation);
        },
        keyframesRun = function (attr, element, time, prev, prevcallback) {
            var dif = time - prev;
            element.timeouts.push(setTimeout(function () {
                R.is(prevcallback, "function") && prevcallback.call(element);
                element.animate(attr, dif, attr.easing);
            }, prev));
        },
        upto255 = function (color) {
            return mmax(mmin(color, 255), 0);
        },
        translate = function (x, y) {
            if (x == null) {
                return {x: this._.tx, y: this._.ty, toString: x_y};
            }
            this._.tx += +x;
            this._.ty += +y;
            switch (this.type) {
                case "circle":
                case "ellipse":
                    this.attr({cx: +x + this.attrs.cx, cy: +y + this.attrs.cy});
                    break;
                case "rect":
                case "image":
                case "text":
                    this.attr({x: +x + this.attrs.x, y: +y + this.attrs.y});
                    break;
                case "path":
                    var path = pathToRelative(this.attrs.path);
                    path[0][1] += +x;
                    path[0][2] += +y;
                    this.attr({path: path});
                break;
            }
            return this;
        };
    elproto.animateWith = function (element, params, ms, easing, callback) {
        for (var i = 0, ii = animationElements.length; i < ii; i++) {
            if (animationElements[i].el.id == element.id) {
                params.start = animationElements[i].start;
            }
        }
        return this.animate(params, ms, easing, callback);
    };
    elproto.animateAlong = along();
    elproto.animateAlongBack = along(1);
    function along(isBack) {
        return function (path, ms, rotate, callback) {
            var params = {back: isBack};
            R.is(rotate, "function") ? (callback = rotate) : (params.rot = rotate);
            path && path.constructor == Element && (path = path.attrs.path);
            path && (params.along = path);
            return this.animate(params, ms, callback);
        };
    }
    function CubicBezierAtTime(t, p1x, p1y, p2x, p2y, duration) {
        var cx = 3 * p1x,
            bx = 3 * (p2x - p1x) - cx,
            ax = 1 - cx - bx,
            cy = 3 * p1y,
            by = 3 * (p2y - p1y) - cy,
            ay = 1 - cy - by;
        function sampleCurveX(t) {
            return ((ax * t + bx) * t + cx) * t;
        }
        function solve(x, epsilon) {
            var t = solveCurveX(x, epsilon);
            return ((ay * t + by) * t + cy) * t;
        }
        function solveCurveX(x, epsilon) {
            var t0, t1, t2, x2, d2, i;
            for(t2 = x, i = 0; i < 8; i++) {
                x2 = sampleCurveX(t2) - x;
                if (abs(x2) < epsilon) {
                    return t2;
                }
                d2 = (3 * ax * t2 + 2 * bx) * t2 + cx;
                if (abs(d2) < 1e-6) {
                    break;
                }
                t2 = t2 - x2 / d2;
            }
            t0 = 0;
            t1 = 1;
            t2 = x;
            if (t2 < t0) {
                return t0;
            }
            if (t2 > t1) {
                return t1;
            }
            while (t0 < t1) {
                x2 = sampleCurveX(t2);
                if (abs(x2 - x) < epsilon) {
                    return t2;
                }
                if (x > x2) {
                    t0 = t2;
                } else {
                    t1 = t2;
                }
                t2 = (t1 - t0) / 2 + t0;
            }
            return t2;
        }
        return solve(t, 1 / (200 * duration));
    }
    elproto.onAnimation = function (f) {
        this._run = f || 0;
        return this;
    };
    elproto.animate = function (params, ms, easing, callback) {
        var element = this;
        element.timeouts = element.timeouts || [];
        if (R.is(easing, "function") || !easing) {
            callback = easing || null;
        }
        if (element.removed) {
            callback && callback.call(element);
            return element;
        }
        var from = {},
            to = {},
            animateable = false,
            diff = {};
        for (var attr in params) if (params[has](attr)) {
            if (availableAnimAttrs[has](attr) || element.paper.customAttributes[has](attr)) {
                animateable = true;
                from[attr] = element.attr(attr);
                (from[attr] == null) && (from[attr] = availableAttrs[attr]);
                to[attr] = params[attr];
                switch (availableAnimAttrs[attr]) {
                    case "along":
                        var len = getTotalLength(params[attr]);
                        var point = getPointAtLength(params[attr], len * !!params.back);
                        var bb = element.getBBox();
                        diff[attr] = len / ms;
                        diff.tx = bb.x;
                        diff.ty = bb.y;
                        diff.sx = point.x;
                        diff.sy = point.y;
                        to.rot = params.rot;
                        to.back = params.back;
                        to.len = len;
                        params.rot && (diff.r = toFloat(element.rotate()) || 0);
                        break;
                    case nu:
                        diff[attr] = (to[attr] - from[attr]) / ms;
                        break;
                    case "colour":
                        from[attr] = R.getRGB(from[attr]);
                        var toColour = R.getRGB(to[attr]);
                        diff[attr] = {
                            r: (toColour.r - from[attr].r) / ms,
                            g: (toColour.g - from[attr].g) / ms,
                            b: (toColour.b - from[attr].b) / ms
                        };
                        break;
                    case "path":
                        var pathes = path2curve(from[attr], to[attr]);
                        from[attr] = pathes[0];
                        var toPath = pathes[1];
                        diff[attr] = [];
                        for (var i = 0, ii = from[attr][length]; i < ii; i++) {
                            diff[attr][i] = [0];
                            for (var j = 1, jj = from[attr][i][length]; j < jj; j++) {
                                diff[attr][i][j] = (toPath[i][j] - from[attr][i][j]) / ms;
                            }
                        }
                        break;
                    case "csv":
                        var values = Str(params[attr])[split](separator),
                            from2 = Str(from[attr])[split](separator);
                        switch (attr) {
                            case "translation":
                                from[attr] = [0, 0];
                                diff[attr] = [values[0] / ms, values[1] / ms];
                            break;
                            case "rotation":
                                from[attr] = (from2[1] == values[1] && from2[2] == values[2]) ? from2 : [0, values[1], values[2]];
                                diff[attr] = [(values[0] - from[attr][0]) / ms, 0, 0];
                            break;
                            case "scale":
                                params[attr] = values;
                                from[attr] = Str(from[attr])[split](separator);
                                diff[attr] = [(values[0] - from[attr][0]) / ms, (values[1] - from[attr][1]) / ms, 0, 0];
                            break;
                            case "clip-rect":
                                from[attr] = Str(from[attr])[split](separator);
                                diff[attr] = [];
                                i = 4;
                                while (i--) {
                                    diff[attr][i] = (values[i] - from[attr][i]) / ms;
                                }
                            break;
                        }
                        to[attr] = values;
                        break;
                    default:
                        values = [].concat(params[attr]);
                        from2 = [].concat(from[attr]);
                        diff[attr] = [];
                        i = element.paper.customAttributes[attr][length];
                        while (i--) {
                            diff[attr][i] = ((values[i] || 0) - (from2[i] || 0)) / ms;
                        }
                        break;
                }
            }
        }
        if (!animateable) {
            var attrs = [],
                lastcall;
            for (var key in params) if (params[has](key) && animKeyFrames.test(key)) {
                attr = {value: params[key]};
                key == "from" && (key = 0);
                key == "to" && (key = 100);
                attr.key = toInt(key, 10);
                attrs.push(attr);
            }
            attrs.sort(sortByKey);
            if (attrs[0].key) {
                attrs.unshift({key: 0, value: element.attrs});
            }
            for (i = 0, ii = attrs[length]; i < ii; i++) {
                keyframesRun(attrs[i].value, element, ms / 100 * attrs[i].key, ms / 100 * (attrs[i - 1] && attrs[i - 1].key || 0), attrs[i - 1] && attrs[i - 1].value.callback);
            }
            lastcall = attrs[attrs[length] - 1].value.callback;
            if (lastcall) {
                element.timeouts.push(setTimeout(function () {lastcall.call(element);}, ms));
            }
        } else {
            var easyeasy = R.easing_formulas[easing];
            if (!easyeasy) {
                easyeasy = Str(easing).match(bezierrg);
                if (easyeasy && easyeasy[length] == 5) {
                    var curve = easyeasy;
                    easyeasy = function (t) {
                        return CubicBezierAtTime(t, +curve[1], +curve[2], +curve[3], +curve[4], ms);
                    };
                } else {
                    easyeasy = function (t) {
                        return t;
                    };
                }
            }
            animationElements.push({
                start: params.start || +new Date,
                ms: ms,
                easing: easyeasy,
                from: from,
                diff: diff,
                to: to,
                el: element,
                t: {x: 0, y: 0}
            });
            R.is(callback, "function") && (element._ac = setTimeout(function () {
                callback.call(element);
            }, ms));
            animationElements[length] == 1 && setTimeout(animation);
        }
        return this;
    };
    elproto.stop = function () {
        for (var i = 0; i < animationElements.length; i++) {
            animationElements[i].el.id == this.id && animationElements.splice(i--, 1);
        }
        for (i = 0, ii = this.timeouts && this.timeouts.length; i < ii; i++) {
            clearTimeout(this.timeouts[i]);
        }
        this.timeouts = [];
        clearTimeout(this._ac);
        delete this._ac;
        return this;
    };
    elproto.translate = function (x, y) {
        return this.attr({translation: x + " " + y});
    };
    elproto[toString] = function () {
        return "Rapha\xebl\u2019s object";
    };
    R.ae = animationElements;
 
    // Set
    var Set = function (items) {
        this.items = [];
        this[length] = 0;
        this.type = "set";
        if (items) {
            for (var i = 0, ii = items[length]; i < ii; i++) {
                if (items[i] && (items[i].constructor == Element || items[i].constructor == Set)) {
                    this[this.items[length]] = this.items[this.items[length]] = items[i];
                    this[length]++;
                }
            }
        }
    };
    Set[proto][push] = function () {
        var item,
            len;
        for (var i = 0, ii = arguments[length]; i < ii; i++) {
            item = arguments[i];
            if (item && (item.constructor == Element || item.constructor == Set)) {
                len = this.items[length];
                this[len] = this.items[len] = item;
                this[length]++;
            }
        }
        return this;
    };
    Set[proto].pop = function () {
        delete this[this[length]--];
        return this.items.pop();
    };
    for (var method in elproto) if (elproto[has](method)) {
        Set[proto][method] = (function (methodname) {
            return function () {
                for (var i = 0, ii = this.items[length]; i < ii; i++) {
                    this.items[i][methodname][apply](this.items[i], arguments);
                }
                return this;
            };
        })(method);
    }
    Set[proto].attr = function (name, value) {
        if (name && R.is(name, array) && R.is(name[0], "object")) {
            for (var j = 0, jj = name[length]; j < jj; j++) {
                this.items[j].attr(name[j]);
            }
        } else {
            for (var i = 0, ii = this.items[length]; i < ii; i++) {
                this.items[i].attr(name, value);
            }
        }
        return this;
    };
    Set[proto].animate = function (params, ms, easing, callback) {
        (R.is(easing, "function") || !easing) && (callback = easing || null);
        var len = this.items[length],
            i = len,
            item,
            set = this,
            collector;
        callback && (collector = function () {
            !--len && callback.call(set);
        });
        easing = R.is(easing, string) ? easing : collector;
        item = this.items[--i].animate(params, ms, easing, collector);
        while (i--) {
            this.items[i] && !this.items[i].removed && this.items[i].animateWith(item, params, ms, easing, collector);
        }
        return this;
    };
    Set[proto].insertAfter = function (el) {
        var i = this.items[length];
        while (i--) {
            this.items[i].insertAfter(el);
        }
        return this;
    };
    Set[proto].getBBox = function () {
        var x = [],
            y = [],
            w = [],
            h = [];
        for (var i = this.items[length]; i--;) {
            var box = this.items[i].getBBox();
            x[push](box.x);
            y[push](box.y);
            w[push](box.x + box.width);
            h[push](box.y + box.height);
        }
        x = mmin[apply](0, x);
        y = mmin[apply](0, y);
        return {
            x: x,
            y: y,
            width: mmax[apply](0, w) - x,
            height: mmax[apply](0, h) - y
        };
    };
    Set[proto].clone = function (s) {
        s = new Set;
        for (var i = 0, ii = this.items[length]; i < ii; i++) {
            s[push](this.items[i].clone());
        }
        return s;
    };

    R.registerFont = function (font) {
        if (!font.face) {
            return font;
        }
        this.fonts = this.fonts || {};
        var fontcopy = {
                w: font.w,
                face: {},
                glyphs: {}
            },
            family = font.face["font-family"];
        for (var prop in font.face) if (font.face[has](prop)) {
            fontcopy.face[prop] = font.face[prop];
        }
        if (this.fonts[family]) {
            this.fonts[family][push](fontcopy);
        } else {
            this.fonts[family] = [fontcopy];
        }
        if (!font.svg) {
            fontcopy.face["units-per-em"] = toInt(font.face["units-per-em"], 10);
            for (var glyph in font.glyphs) if (font.glyphs[has](glyph)) {
                var path = font.glyphs[glyph];
                fontcopy.glyphs[glyph] = {
                    w: path.w,
                    k: {},
                    d: path.d && "M" + path.d[rp](/[mlcxtrv]/g, function (command) {
                            return {l: "L", c: "C", x: "z", t: "m", r: "l", v: "c"}[command] || "M";
                        }) + "z"
                };
                if (path.k) {
                    for (var k in path.k) if (path[has](k)) {
                        fontcopy.glyphs[glyph].k[k] = path.k[k];
                    }
                }
            }
        }
        return font;
    };
    paperproto.getFont = function (family, weight, style, stretch) {
        stretch = stretch || "normal";
        style = style || "normal";
        weight = +weight || {normal: 400, bold: 700, lighter: 300, bolder: 800}[weight] || 400;
        if (!R.fonts) {
            return;
        }
        var font = R.fonts[family];
        if (!font) {
            var name = new RegExp("(^|\\s)" + family[rp](/[^\w\d\s+!~.:_-]/g, E) + "(\\s|$)", "i");
            for (var fontName in R.fonts) if (R.fonts[has](fontName)) {
                if (name.test(fontName)) {
                    font = R.fonts[fontName];
                    break;
                }
            }
        }
        var thefont;
        if (font) {
            for (var i = 0, ii = font[length]; i < ii; i++) {
                thefont = font[i];
                if (thefont.face["font-weight"] == weight && (thefont.face["font-style"] == style || !thefont.face["font-style"]) && thefont.face["font-stretch"] == stretch) {
                    break;
                }
            }
        }
        return thefont;
    };
    paperproto.print = function (x, y, string, font, size, origin, letter_spacing) {
        origin = origin || "middle"; // baseline|middle
        letter_spacing = mmax(mmin(letter_spacing || 0, 1), -1);
        var out = this.set(),
            letters = Str(string)[split](E),
            shift = 0,
            path = E,
            scale;
        R.is(font, string) && (font = this.getFont(font));
        if (font) {
            scale = (size || 16) / font.face["units-per-em"];
            var bb = font.face.bbox.split(separator),
                top = +bb[0],
                height = +bb[1] + (origin == "baseline" ? bb[3] - bb[1] + (+font.face.descent) : (bb[3] - bb[1]) / 2);
            for (var i = 0, ii = letters[length]; i < ii; i++) {
                var prev = i && font.glyphs[letters[i - 1]] || {},
                    curr = font.glyphs[letters[i]];
                shift += i ? (prev.w || font.w) + (prev.k && prev.k[letters[i]] || 0) + (font.w * letter_spacing) : 0;
                curr && curr.d && out[push](this.path(curr.d).attr({fill: "#000", stroke: "none", translation: [shift, 0]}));
            }
            out.scale(scale, scale, top, height).translate(x - top, y - height);
        }
        return out;
    };

    R.format = function (token, params) {
        var args = R.is(params, array) ? [0][concat](params) : arguments;
        token && R.is(token, string) && args[length] - 1 && (token = token[rp](formatrg, function (str, i) {
            return args[++i] == null ? E : args[i];
        }));
        return token || E;
    };
    R.ninja = function () {
        oldRaphael.was ? (win.Raphael = oldRaphael.is) : delete Raphael;
        return R;
    };
    R.el = elproto;
    R.st = Set[proto];

    oldRaphael.was ? (win.Raphael = R) : (Raphael = R);
})();
if(!this.Faye)Faye={};Faye.extend=function(a,b,c){if(!b)return a;for(var d in b){if(!b.hasOwnProperty(d))continue;if(a.hasOwnProperty(d)&&c===false)continue;if(a[d]!==b[d])a[d]=b[d]}return a};Faye.extend(Faye,{VERSION:'0.6.4',BAYEUX_VERSION:'1.0',ID_LENGTH:128,JSONP_CALLBACK:'jsonpcallback',CONNECTION_TYPES:['long-polling','cross-origin-long-polling','callback-polling','websocket','in-process'],MANDATORY_CONNECTION_TYPES:['long-polling','callback-polling','in-process'],ENV:(function(){return this})(),random:function(a){a=a||this.ID_LENGTH;if(a>32){var b=Math.ceil(a/32),c='';while(b--)c+=this.random(32);return c}var d=Math.pow(2,a)-1,f=d.toString(36).length,c=Math.floor(Math.random()*d).toString(36);while(c.length<f)c='0'+c;return c},commonElement:function(a,b){for(var c=0,d=a.length;c<d;c++){if(this.indexOf(b,a[c])!==-1)return a[c]}return null},indexOf:function(a,b){for(var c=0,d=a.length;c<d;c++){if(a[c]===b)return c}return-1},each:function(a,b,c){if(a instanceof Array){for(var d=0,f=a.length;d<f;d++){if(a[d]!==undefined)b.call(c||null,a[d],d)}}else{for(var g in a){if(a.hasOwnProperty(g))b.call(c||null,g,a[g])}}},map:function(a,b,c){if(a.map)return a.map(b,c);var d=[];this.each(a,function(){d.push(b.apply(c||null,arguments))});return d},filter:function(a,b,c){var d=[];this.each(a,function(){if(b.apply(c,arguments))d.push(arguments[0])});return d},size:function(a){var b=0;this.each(a,function(){b+=1});return b},enumEqual:function(c,d){if(d instanceof Array){if(!(c instanceof Array))return false;var f=c.length;if(f!==d.length)return false;while(f--){if(c[f]!==d[f])return false}return true}else{if(!(c instanceof Object))return false;if(this.size(d)!==this.size(c))return false;var g=true;this.each(c,function(a,b){g=g&&(d[a]===b)});return g}},asyncEach:function(a,b,c,d){var f=a.length,g=-1,h=0,i=false;var j=function(){h-=1;g+=1;if(g===f)return c&&c.call(d);b(a[g],m)};var k=function(){if(i)return;i=true;while(h>0)j();i=false};var m=function(){h+=1;k()};m()},toJSON:function(a){if(this.stringify)return this.stringify(a,function(key,value){return(this[key]instanceof Array)?this[key]:value});return JSON.stringify(a)},timestamp:function(){var b=new Date(),c=b.getFullYear(),d=b.getMonth()+1,f=b.getDate(),g=b.getHours(),h=b.getMinutes(),i=b.getSeconds();var j=function(a){return a<10?'0'+a:String(a)};return j(c)+'-'+j(d)+'-'+j(f)+' '+j(g)+':'+j(h)+':'+j(i)}});Faye.Class=function(a,b){if(typeof a!=='function'){b=a;a=Object}var c=function(){if(!this.initialize)return this;return this.initialize.apply(this,arguments)||this};var d=function(){};d.prototype=a.prototype;c.prototype=new d();Faye.extend(c.prototype,b);return c};Faye.Namespace=Faye.Class({initialize:function(){this._c={}},exists:function(a){return this._c.hasOwnProperty(a)},generate:function(){var a=Faye.random();while(this._c.hasOwnProperty(a))a=Faye.random();return this._c[a]=a},release:function(a){delete this._c[a]}});Faye.Error=Faye.Class({initialize:function(a,b,c){this.code=a;this.params=Array.prototype.slice.call(b);this.message=c},toString:function(){return this.code+':'+this.params.join(',')+':'+this.message}});Faye.Error.parse=function(a){a=a||'';if(!Faye.Grammar.ERROR.test(a))return new this(null,[],a);var b=a.split(':'),c=parseInt(b[0]),d=b[1].split(','),a=b[2];return new this(c,d,a)};Faye.Error.versionMismatch=function(){return new this(300,arguments,"Version mismatch").toString()};Faye.Error.conntypeMismatch=function(){return new this(301,arguments,"Connection types not supported").toString()};Faye.Error.extMismatch=function(){return new this(302,arguments,"Extension mismatch").toString()};Faye.Error.badRequest=function(){return new this(400,arguments,"Bad request").toString()};Faye.Error.clientUnknown=function(){return new this(401,arguments,"Unknown client").toString()};Faye.Error.parameterMissing=function(){return new this(402,arguments,"Missing required parameter").toString()};Faye.Error.channelForbidden=function(){return new this(403,arguments,"Forbidden channel").toString()};Faye.Error.channelUnknown=function(){return new this(404,arguments,"Unknown channel").toString()};Faye.Error.channelInvalid=function(){return new this(405,arguments,"Invalid channel").toString()};Faye.Error.extUnknown=function(){return new this(406,arguments,"Unknown extension").toString()};Faye.Error.publishFailed=function(){return new this(407,arguments,"Failed to publish").toString()};Faye.Error.serverError=function(){return new this(500,arguments,"Internal server error").toString()};Faye.Deferrable={callback:function(a,b){if(!a)return;if(this._t==='succeeded')return a.apply(b,this._j);this._k=this._k||[];this._k.push([a,b])},errback:function(a,b){if(!a)return;if(this._t==='failed')return a.apply(b,this._j);this._l=this._l||[];this._l.push([a,b])},setDeferredStatus:function(){var a=Array.prototype.slice.call(arguments),b=a.shift(),c;this._t=b;this._j=a;if(b==='succeeded')c=this._k;else if(b==='failed')c=this._l;if(!c)return;var d;while(d=c.shift())d[0].apply(d[1],this._j)}};Faye.Publisher={countSubscribers:function(a){if(!this._3||!this._3[a])return 0;return this._3[a].length},addSubscriber:function(a,b,c){this._3=this._3||{};var d=this._3[a]=this._3[a]||[];d.push([b,c])},removeSubscriber:function(a,b,c){if(!this._3||!this._3[a])return;if(!b){delete this._3[a];return}var d=this._3[a],f=d.length;while(f--){if(b!==d[f][0])continue;if(c&&d[f][1]!==c)continue;d.splice(f,1)}},removeSubscribers:function(){this._3={}},publishEvent:function(){var b=Array.prototype.slice.call(arguments),c=b.shift();if(!this._3||!this._3[c])return;Faye.each(this._3[c],function(a){a[0].apply(a[1],b)})}};Faye.Timeouts={addTimeout:function(a,b,c,d){this._4=this._4||{};if(this._4.hasOwnProperty(a))return;var f=this;this._4[a]=Faye.ENV.setTimeout(function(){delete f._4[a];c.call(d)},1000*b)},removeTimeout:function(a){this._4=this._4||{};var b=this._4[a];if(!b)return;clearTimeout(b);delete this._4[a]}};Faye.Logging={LOG_LEVELS:{error:3,warn:2,info:1,debug:0},logLevel:'error',log:function(a,b){if(!Faye.logger)return;var c=Faye.Logging.LOG_LEVELS;if(c[Faye.Logging.logLevel]>c[b])return;var a=Array.prototype.slice.apply(a),d=' ['+b.toUpperCase()+'] [Faye',f=this.className,g=a.shift().replace(/\?/g,function(){try{return Faye.toJSON(a.shift())}catch(e){return'[Object]'}});for(var h in Faye){if(f)continue;if(typeof Faye[h]!=='function')continue;if(this instanceof Faye[h])f=h}if(f)d+='.'+f;d+='] ';Faye.logger(Faye.timestamp()+d+g)}};Faye.each(Faye.Logging.LOG_LEVELS,function(a,b){Faye.Logging[a]=function(){this.log(arguments,a)}});Faye.Grammar={LOWALPHA:/^[a-z]$/,UPALPHA:/^[A-Z]$/,ALPHA:/^([a-z]|[A-Z])$/,DIGIT:/^[0-9]$/,ALPHANUM:/^(([a-z]|[A-Z])|[0-9])$/,MARK:/^(\-|\_|\!|\~|\(|\)|\$|\@)$/,STRING:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*$/,TOKEN:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+$/,INTEGER:/^([0-9])+$/,CHANNEL_SEGMENT:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+$/,CHANNEL_SEGMENTS:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*$/,CHANNEL_NAME:/^\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*$/,WILD_CARD:/^\*{1,2}$/,CHANNEL_PATTERN:/^(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*\/\*{1,2}$/,VERSION_ELEMENT:/^(([a-z]|[A-Z])|[0-9])(((([a-z]|[A-Z])|[0-9])|\-|\_))*$/,VERSION:/^([0-9])+(\.(([a-z]|[A-Z])|[0-9])(((([a-z]|[A-Z])|[0-9])|\-|\_))*)*$/,CLIENT_ID:/^((([a-z]|[A-Z])|[0-9]))+$/,ID:/^((([a-z]|[A-Z])|[0-9]))+$/,ERROR_MESSAGE:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*$/,ERROR_ARGS:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*(,(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)*$/,ERROR_CODE:/^[0-9][0-9][0-9]$/,ERROR:/^([0-9][0-9][0-9]:(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*(,(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)*:(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*|[0-9][0-9][0-9]::(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)$/};Faye.Extensible={addExtension:function(a){this._5=this._5||[];this._5.push(a);if(a.added)a.added()},removeExtension:function(a){if(!this._5)return;var b=this._5.length;while(b--){if(this._5[b]!==a)continue;this._5.splice(b,1);if(a.removed)a.removed()}},pipeThroughExtensions:function(c,d,f,g){this.debug('Passing through ? extensions: ?',c,d);if(!this._5)return f.call(g,d);var h=this._5.slice();var i=function(a){if(!a)return f.call(g,a);var b=h.shift();if(!b)return f.call(g,a);if(b[c])b[c](a,i);else i(a)};i(d)}};Faye.extend(Faye.Extensible,Faye.Logging);Faye.Channel=Faye.Class({initialize:function(a){this.id=this.name=a},push:function(a){this.publishEvent('message',a)},isUnused:function(){return this.countSubscribers('message')===0}});Faye.extend(Faye.Channel.prototype,Faye.Publisher);Faye.extend(Faye.Channel,{HANDSHAKE:'/meta/handshake',CONNECT:'/meta/connect',SUBSCRIBE:'/meta/subscribe',UNSUBSCRIBE:'/meta/unsubscribe',DISCONNECT:'/meta/disconnect',META:'meta',SERVICE:'service',expand:function(a){var b=this.parse(a),c=['/**',a];var d=b.slice();d[d.length-1]='*';c.push(this.unparse(d));for(var f=1,g=b.length;f<g;f++){d=b.slice(0,f);d.push('**');c.push(this.unparse(d))}return c},isValid:function(a){return Faye.Grammar.CHANNEL_NAME.test(a)||Faye.Grammar.CHANNEL_PATTERN.test(a)},parse:function(a){if(!this.isValid(a))return null;return a.split('/').slice(1)},unparse:function(a){return'/'+a.join('/')},isMeta:function(a){var b=this.parse(a);return b?(b[0]===this.META):null},isService:function(a){var b=this.parse(a);return b?(b[0]===this.SERVICE):null},isSubscribable:function(a){if(!this.isValid(a))return null;return!this.isMeta(a)&&!this.isService(a)},Set:Faye.Class({initialize:function(){this._2={}},getKeys:function(){var c=[];Faye.each(this._2,function(a,b){c.push(a)});return c},remove:function(a){delete this._2[a]},hasSubscription:function(a){return this._2.hasOwnProperty(a)},subscribe:function(c,d,f){if(!d)return;Faye.each(c,function(a){var b=this._2[a]=this._2[a]||new Faye.Channel(a);b.addSubscriber('message',d,f)},this)},unsubscribe:function(a,b,c){var d=this._2[a];if(!d)return false;d.removeSubscriber('message',b,c);if(d.isUnused()){this.remove(a);return true}else{return false}},distributeMessage:function(c){var d=Faye.Channel.expand(c.channel);Faye.each(d,function(a){var b=this._2[a];if(b)b.publishEvent('message',c.data)},this)}})});Faye.Subscription=Faye.Class({initialize:function(a,b,c,d){this._8=a;this._2=b;this._m=c;this._n=d;this._u=false},cancel:function(){if(this._u)return;this._8.unsubscribe(this._2,this._m,this._n);this._u=true},unsubscribe:function(){this.cancel()}});Faye.extend(Faye.Subscription.prototype,Faye.Deferrable);Faye.Client=Faye.Class({UNCONNECTED:1,CONNECTING:2,CONNECTED:3,DISCONNECTED:4,HANDSHAKE:'handshake',RETRY:'retry',NONE:'none',CONNECTION_TIMEOUT:60.0,DEFAULT_ENDPOINT:'/bayeux',INTERVAL:0.0,initialize:function(b,c){this.info('New client created for ?',b);this.endpoint=b||this.DEFAULT_ENDPOINT;this._v=c||{};Faye.Transport.get(this,Faye.MANDATORY_CONNECTION_TYPES,function(a){this._d=a},this);this._1=this.UNCONNECTED;this._2=new Faye.Channel.Set();this._e=0;this._o={};this._6={reconnect:this.RETRY,interval:1000*(this._v.interval||this.INTERVAL),timeout:1000*(this._v.timeout||this.CONNECTION_TIMEOUT)};if(Faye.Event)Faye.Event.on(Faye.ENV,'beforeunload',this.disconnect,this)},getClientId:function(){return this._0},getState:function(){switch(this._1){case this.UNCONNECTED:return'UNCONNECTED';case this.CONNECTING:return'CONNECTING';case this.CONNECTED:return'CONNECTED';case this.DISCONNECTED:return'DISCONNECTED'}},handshake:function(c,d){if(this._6.reconnect===this.NONE)return;if(this._1!==this.UNCONNECTED)return;this._1=this.CONNECTING;var f=this;this.info('Initiating handshake with ?',this.endpoint);this._9({channel:Faye.Channel.HANDSHAKE,version:Faye.BAYEUX_VERSION,supportedConnectionTypes:[this._d.connectionType]},function(b){if(b.successful){this._1=this.CONNECTED;this._0=b.clientId;Faye.Transport.get(this,b.supportedConnectionTypes,function(a){this._d=a},this);this.info('Handshake successful: ?',this._0);this.subscribe(this._2.getKeys(),true);if(c)c.call(d)}else{this.info('Handshake unsuccessful');Faye.ENV.setTimeout(function(){f.handshake(c,d)},this._6.interval);this._1=this.UNCONNECTED}},this)},connect:function(a,b){if(this._6.reconnect===this.NONE)return;if(this._1===this.DISCONNECTED)return;if(this._1===this.UNCONNECTED)return this.handshake(function(){this.connect(a,b)},this);this.callback(a,b);if(this._1!==this.CONNECTED)return;this.info('Calling deferred actions for ?',this._0);this.setDeferredStatus('succeeded');this.setDeferredStatus('deferred');if(this._p)return;this._p=true;this.info('Initiating connection for ?',this._0);this._9({channel:Faye.Channel.CONNECT,clientId:this._0,connectionType:this._d.connectionType},this._w,this)},disconnect:function(){if(this._1!==this.CONNECTED)return;this._1=this.DISCONNECTED;this.info('Disconnecting ?',this._0);this._9({channel:Faye.Channel.DISCONNECT,clientId:this._0});this.info('Clearing channel listeners for ?',this._0);this._2=new Faye.Channel.Set()},subscribe:function(c,d,f){if(c instanceof Array)return Faye.each(c,function(channel){this.subscribe(channel,d,f)},this);var g=new Faye.Subscription(this,c,d,f);var h=(d===true);if(!h&&this._2.hasSubscription(c)){this._2.subscribe([c],d,f);g.setDeferredStatus('succeeded');return g}this.connect(function(){this.info('Client ? attempting to subscribe to ?',this._0,c);this._9({channel:Faye.Channel.SUBSCRIBE,clientId:this._0,subscription:c},function(a){if(!a.successful)return g.setDeferredStatus('failed',Faye.Error.parse(a.error));var b=[].concat(a.subscription);this.info('Subscription acknowledged for ? to ?',this._0,b);if(!h)this._2.subscribe(b,d,f);g.setDeferredStatus('succeeded')},this)},this);return g},unsubscribe:function(c,d,f){if(c instanceof Array)return Faye.each(c,function(channel){this.unsubscribe(channel,d,f)},this);var g=this._2.unsubscribe(c,d,f);if(!g)return;this.connect(function(){this.info('Client ? attempting to unsubscribe from ?',this._0,c);this._9({channel:Faye.Channel.UNSUBSCRIBE,clientId:this._0,subscription:c},function(a){if(!a.successful)return;var b=[].concat(a.subscription);this.info('Unsubscription acknowledged for ? from ?',this._0,b)},this)},this)},publish:function(a,b){if(!Faye.Grammar.CHANNEL_NAME.test(a))throw new Error("Cannot publish: '"+a+"' is not a valid channel name");this.connect(function(){this.info('Client ? queueing published message to ?: ?',this._0,a,b);this._9({channel:a,data:b,clientId:this._0})},this)},receiveMessage:function(c){this.pipeThroughExtensions('incoming',c,function(a){if(!a)return;if(a.advice)this._z(a.advice);var b=this._o[a.id];if(b){delete this._o[a.id];b[0].call(b[1],a)}this._A(a)},this)},_9:function(b,c,d){b.id=this._B();if(c)this._o[b.id]=[c,d];this.pipeThroughExtensions('outgoing',b,function(a){if(!a)return;this._d.send(a,this._6.timeout/1000)},this)},_B:function(){this._e+=1;if(this._e>=Math.pow(2,32))this._e=0;return this._e.toString(36)},_z:function(a){Faye.extend(this._6,a);if(this._6.reconnect===this.HANDSHAKE&&this._1!==this.DISCONNECTED){this._1=this.UNCONNECTED;this._0=null;this._w()}},_A:function(a){if(!a.channel||!a.data)return;this.info('Client ? calling listeners for ? with ?',this._0,a.channel,a.data);this._2.distributeMessage(a)},_C:function(){if(!this._p)return;this._p=null;this.info('Closed connection for ?',this._0)},_w:function(){this._C();var a=this;Faye.ENV.setTimeout(function(){a.connect()},this._6.interval)}});Faye.extend(Faye.Client.prototype,Faye.Deferrable);Faye.extend(Faye.Client.prototype,Faye.Logging);Faye.extend(Faye.Client.prototype,Faye.Extensible);Faye.Transport=Faye.extend(Faye.Class({MAX_DELAY:0.0,batching:true,initialize:function(a,b){this.debug('Created new ? transport for ?',this.connectionType,b);this._8=a;this._a=b;this._f=[]},send:function(a,b){this.debug('Client ? sending message to ?: ?',this._8._0,this._a,a);if(!this.batching)return this.request([a],b);this._f.push(a);this._7=b;if(a.channel===Faye.Channel.HANDSHAKE)return this.flush();if(a.channel===Faye.Channel.CONNECT)this._q=a;this.addTimeout('publish',this.MAX_DELAY,this.flush,this)},flush:function(){this.removeTimeout('publish');if(this._f.length>1&&this._q)this._q.advice={timeout:0};this.request(this._f,this._7);this._q=null;this._f=[]},receive:function(a){this.debug('Client ? received from ?: ?',this._8._0,this._a,a);Faye.each(a,this._8.receiveMessage,this._8)},retry:function(a,b){var c=this;return function(){Faye.ENV.setTimeout(function(){c.request(a,2*b)},1000*b)}}}),{get:function(g,h,i,j){var k=g.endpoint;if(h===undefined)h=this.supportedConnectionTypes();Faye.asyncEach(this._r,function(b,c){var d=b[0],f=b[1];if(Faye.indexOf(h,d)<0)return c();f.isUsable(k,function(a){if(a)i.call(j,new f(g,k));else c()})},function(){throw new Error('Could not find a usable connection type for '+k);})},register:function(a,b){this._r.push([a,b]);b.prototype.connectionType=a},_r:[],supportedConnectionTypes:function(){return Faye.map(this._r,function(a){return a[0]})}});Faye.extend(Faye.Transport.prototype,Faye.Logging);Faye.extend(Faye.Transport.prototype,Faye.Timeouts);Faye.Event={_g:[],on:function(a,b,c,d){var f=function(){c.call(d)};if(a.addEventListener)a.addEventListener(b,f,false);else a.attachEvent('on'+b,f);this._g.push({_h:a,_s:b,_m:c,_n:d,_x:f})},detach:function(a,b,c,d){var f=this._g.length,g;while(f--){g=this._g[f];if((a&&a!==g._h)||(b&&b!==g._s)||(c&&c!==g._m)||(d&&d!==g._n))continue;if(g._h.removeEventListener)g._h.removeEventListener(g._s,g._x,false);else g._h.detachEvent('on'+g._s,g._x);this._g.splice(f,1);g=null}}};Faye.Event.on(Faye.ENV,'unload',Faye.Event.detach,Faye.Event);Faye.URI=Faye.extend(Faye.Class({queryString:function(){var c=[],d;Faye.each(this.params,function(a,b){c.push(encodeURIComponent(a)+'='+encodeURIComponent(b))});return c.join('&')},isLocal:function(){var a=Faye.URI.parse(Faye.ENV.location.href);var b=(a.hostname!==this.hostname)||(a.port!==this.port)||(a.protocol!==this.protocol);return!b},toURL:function(){var a=this.queryString();return this.protocol+this.hostname+':'+this.port+this.pathname+(a?'?'+a:'')}}),{parse:function(d,f){if(typeof d!=='string')return d;var g=new this();var h=function(b,c){d=d.replace(c,function(a){if(a)g[b]=a;return''})};h('protocol',/^https?\:\/+/);h('hostname',/^[^\/\:]+/);h('port',/^:[0-9]+/);Faye.extend(g,{protocol:'http://',hostname:Faye.ENV.location.hostname,port:Faye.ENV.location.port},false);if(!g.port)g.port=(g.protocol==='https://')?'443':'80';g.port=g.port.replace(/\D/g,'');var i=d.split('?'),j=i.shift(),k=i.join('?'),m=k?k.split('&'):[],o=m.length,l={};while(o--){i=m[o].split('=');l[decodeURIComponent(i[0]||'')]=decodeURIComponent(i[1]||'')}if(typeof f==='object')Faye.extend(l,f);g.pathname=j;g.params=l;return g}});if(!this.JSON){JSON={}}(function(){function k(a){return a<10?'0'+a:a}if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(a){return this.getUTCFullYear()+'-'+k(this.getUTCMonth()+1)+'-'+k(this.getUTCDate())+'T'+k(this.getUTCHours())+':'+k(this.getUTCMinutes())+':'+k(this.getUTCSeconds())+'Z'};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(a){return this.valueOf()}}var m=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,o=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,l,p,s={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},n;function r(c){o.lastIndex=0;return o.test(c)?'"'+c.replace(o,function(a){var b=s[a];return typeof b==='string'?b:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+c+'"'}function q(a,b){var c,d,f,g,h=l,i,j=b[a];if(j&&typeof j==='object'&&typeof j.toJSON==='function'){j=j.toJSON(a)}if(typeof n==='function'){j=n.call(b,a,j)}switch(typeof j){case'string':return r(j);case'number':return isFinite(j)?String(j):'null';case'boolean':case'null':return String(j);case'object':if(!j){return'null'}l+=p;i=[];if(Object.prototype.toString.apply(j)==='[object Array]'){g=j.length;for(c=0;c<g;c+=1){i[c]=q(c,j)||'null'}f=i.length===0?'[]':l?'[\n'+l+i.join(',\n'+l)+'\n'+h+']':'['+i.join(',')+']';l=h;return f}if(n&&typeof n==='object'){g=n.length;for(c=0;c<g;c+=1){d=n[c];if(typeof d==='string'){f=q(d,j);if(f){i.push(r(d)+(l?': ':':')+f)}}}}else{for(d in j){if(Object.hasOwnProperty.call(j,d)){f=q(d,j);if(f){i.push(r(d)+(l?': ':':')+f)}}}}f=i.length===0?'{}':l?'{\n'+l+i.join(',\n'+l)+'\n'+h+'}':'{'+i.join(',')+'}';l=h;return f}}Faye.stringify=function(a,b,c){var d;l='';p='';if(typeof c==='number'){for(d=0;d<c;d+=1){p+=' '}}else if(typeof c==='string'){p=c}n=b;if(b&&typeof b!=='function'&&(typeof b!=='object'||typeof b.length!=='number')){throw new Error('JSON.stringify');}return q('',{'':a})};if(typeof JSON.stringify!=='function'){JSON.stringify=Faye.stringify}if(typeof JSON.parse!=='function'){JSON.parse=function(g,h){var i;function j(a,b){var c,d,f=a[b];if(f&&typeof f==='object'){for(c in f){if(Object.hasOwnProperty.call(f,c)){d=j(f,c);if(d!==undefined){f[c]=d}else{delete f[c]}}}}return h.call(a,b,f)}m.lastIndex=0;if(m.test(g)){g=g.replace(m,function(a){return'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\],:{}\s]*$/.test(g.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,''))){i=eval('('+g+')');return typeof h==='function'?j({'':i},''):i}throw new SyntaxError('JSON.parse');}}}());Faye.Transport.WebSocket=Faye.extend(Faye.Class(Faye.Transport,{UNCONNECTED:1,CONNECTING:2,CONNECTED:3,batching:false,request:function(b,c){this._7=this._7||c;this._i=this._i||{};Faye.each(b,function(a){this._i[a.id]=a},this);this.withSocket(function(a){a.send(Faye.toJSON(b))})},withSocket:function(a,b){this.callback(a,b);this.connect()},connect:function(){this._1=this._1||this.UNCONNECTED;if(this._1!==this.UNCONNECTED)return;this._1=this.CONNECTING;var d=Faye.ENV.WebSocket||Faye.ENV.MozWebSocket;this._b=new d(Faye.Transport.WebSocket.getSocketUrl(this._a));var f=this;this._b.onopen=function(){delete f._7;f._1=f.CONNECTED;f.setDeferredStatus('succeeded',f._b)};this._b.onmessage=function(b){var c=[].concat(JSON.parse(b.data));Faye.each(c,function(a){delete f._i[a.id]});f.receive(c)};this._b.onclose=function(){var a=(f._1===f.CONNECTED);f.setDeferredStatus('deferred');f._1=f.UNCONNECTED;delete f._b;if(a)return f.resend();Faye.ENV.setTimeout(function(){f.connect()},1000*f._7);f._7=f._7*2}},resend:function(){var c=Faye.map(this._i,function(a,b){return b});this.request(c)}}),{WEBSOCKET_TIMEOUT:1000,getSocketUrl:function(a){return Faye.URI.parse(a).toURL().replace(/^http(s?):/ig,'ws$1:')},isUsable:function(a,b,c){var d=Faye.ENV.WebSocket||Faye.ENV.MozWebSocket;if(!d)return b.call(c,false);var f=false,g=false,h=this.getSocketUrl(a),i=new d(h);i.onopen=function(){f=true;i.close();b.call(c,true);g=true;i=null};var j=function(){if(!g&&!f)b.call(c,false);g=true};i.onclose=i.onerror=j;Faye.ENV.setTimeout(j,this.WEBSOCKET_TIMEOUT)}});Faye.extend(Faye.Transport.WebSocket.prototype,Faye.Deferrable);Faye.Transport.register('websocket',Faye.Transport.WebSocket);Faye.Transport.XHR=Faye.extend(Faye.Class(Faye.Transport,{request:function(b,c){var d=this.retry(b,c),f=Faye.URI.parse(this._a).pathname,g=this,h=Faye.ENV.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest();h.open('POST',f,true);h.setRequestHeader('Content-Type','application/json');h.setRequestHeader('X-Requested-With','XMLHttpRequest');h.onreadystatechange=function(){if(h.readyState!==4)return;var a=h.status;try{if((a>=200&&a<300)||a===304||a===1223)g.receive(JSON.parse(h.responseText));else d()}catch(e){d()}finally{Faye.Event.detach(Faye.ENV,'beforeunload',i);h.onreadystatechange=function(){};h=null}};var i=function(){h.abort()};Faye.Event.on(Faye.ENV,'beforeunload',i);h.send(Faye.toJSON(b))}}),{isUsable:function(a,b,c){b.call(c,Faye.URI.parse(a).isLocal())}});Faye.Transport.register('long-polling',Faye.Transport.XHR);Faye.Transport.CORS=Faye.extend(Faye.Class(Faye.Transport,{request:function(a,b){var c=Faye.ENV.XDomainRequest?XDomainRequest:XMLHttpRequest,d=new c(),f=this.retry(a,b),g=this;d.open('POST',this._a,true);d.onload=function(){try{g.receive(JSON.parse(d.responseText))}catch(e){f()}finally{d.onload=d.onerror=null;d=null}};d.onerror=f;d.onprogress=function(){};d.send('message='+encodeURIComponent(Faye.toJSON(a)))}}),{isUsable:function(a,b,c){if(Faye.URI.parse(a).isLocal())return b.call(c,false);if(Faye.ENV.XDomainRequest)return b.call(c,true);if(Faye.ENV.XMLHttpRequest){var d=new Faye.ENV.XMLHttpRequest();return b.call(c,d.withCredentials!==undefined)}return b.call(c,false)}});Faye.Transport.register('cross-origin-long-polling',Faye.Transport.CORS);Faye.Transport.JSONP=Faye.extend(Faye.Class(Faye.Transport,{request:function(b,c){var d={message:Faye.toJSON(b)},f=document.getElementsByTagName('head')[0],g=document.createElement('script'),h=Faye.Transport.JSONP.getCallbackName(),i=Faye.URI.parse(this._a,d),j=this;var k=function(){if(!g.parentNode)return false;g.parentNode.removeChild(g);return true};Faye.ENV[h]=function(a){Faye.ENV[h]=undefined;try{delete Faye.ENV[h]}catch(e){}if(!k())return;j.receive(a)};Faye.ENV.setTimeout(function(){if(!Faye.ENV[h])return;k();j.request(b,2*c)},1000*c);i.params.jsonp=h;g.type='text/javascript';g.src=i.toURL();f.appendChild(g)}}),{_y:0,getCallbackName:function(){this._y+=1;return'__jsonp'+this._y+'__'},isUsable:function(a,b,c){b.call(c,true)}});Faye.Transport.register('callback-polling',Faye.Transport.JSONP);
/* Copyright (c) 2007 Paul Bakaus (paul.bakaus@googlemail.com) and Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * $LastChangedDate: 2007-08-17 13:14:11 -0500 (Fri, 17 Aug 2007) $
 * $Rev: 2759 $
 *
 * Version: 1.1.2
 *
 * Requires: jQuery 1.1.3+
 */


(function($){

// store a copy of the core height and width methods
var height = $.fn.height,
    width  = $.fn.width;

$.fn.extend({
	/**
	 * If used on document, returns the document's height (innerHeight).
	 * If used on window, returns the viewport's (window) height.
	 * See core docs on height() to see what happens when used on an element.
	 *
	 * @example $("#testdiv").height()
	 * @result 200
	 *
	 * @example $(document).height()
	 * @result 800
	 *
	 * @example $(window).height()
	 * @result 400
	 *
	 * @name height
	 * @type Number
	 * @cat Plugins/Dimensions
	 */

  // height: function() {
  //  if ( !this[0] ) error();
  //  if ( this[0] == window )
  //    if ( $.browser.opera || ($.browser.safari && parseInt($.browser.version) > 520) )
  //      return self.innerHeight - (($(document).height() > self.innerHeight) ? getScrollbarWidth() : 0);
  //    else if ( $.browser.safari )
  //      return self.innerHeight;
  //    else
  //                 return $.boxModel && document.documentElement.clientHeight || document.body.clientHeight;
  //  
  //  if ( this[0] == document ) 
  //    return Math.max( ($.boxModel && document.documentElement.scrollHeight || document.body.scrollHeight), document.body.offsetHeight );
  //  
  //  return height.apply(this, arguments);
  // },
	
	/**
	 * If used on document, returns the document's width (innerWidth).
	 * If used on window, returns the viewport's (window) width.
	 * See core docs on width() to see what happens when used on an element.
	 *
	 * @example $("#testdiv").width()
	 * @result 200
	 *
	 * @example $(document).width()
	 * @result 800
	 *
	 * @example $(window).width()
	 * @result 400
	 *
	 * @name width
	 * @type Number
	 * @cat Plugins/Dimensions
	 */

  // width: function() {
  //  if (!this[0]) error();
  //  if ( this[0] == window )
  //    if ( $.browser.opera || ($.browser.safari && parseInt($.browser.version) > 520) )
  //      return self.innerWidth - (($(document).width() > self.innerWidth) ? getScrollbarWidth() : 0);
  //    else if ( $.browser.safari )
  //      return self.innerWidth;
  //    else
  //                 return $.boxModel && document.documentElement.clientWidth || document.body.clientWidth;
  // 
  //  if ( this[0] == document )
  //    if ($.browser.mozilla) {
  //      // mozilla reports scrollWidth and offsetWidth as the same
  //      var scrollLeft = self.pageXOffset;
  //      self.scrollTo(99999999, self.pageYOffset);
  //      var scrollWidth = self.pageXOffset;
  //      self.scrollTo(scrollLeft, self.pageYOffset);
  //      return document.body.offsetWidth + scrollWidth;
  //    }
  //    else 
  //      return Math.max( (($.boxModel && !$.browser.safari) && document.documentElement.scrollWidth || document.body.scrollWidth), document.body.offsetWidth );
  // 
  //  return width.apply(this, arguments);
  // },
	
	/**
	 * Gets the inner height (excludes the border and includes the padding) for the first matched element.
	 * If used on document, returns the document's height (innerHeight).
	 * If used on window, returns the viewport's (window) height.
	 *
	 * @example $("#testdiv").innerHeight()
	 * @result 210
	 *
	 * @name innerHeight
	 * @type Number
	 * @cat Plugins/Dimensions
	 */

  // innerHeight: function() {
  //  if (!this[0]) error();
  //  return this[0] == window || this[0] == document ?
  //    this.height() :
  //    this.is(':visible') ?
  //      this[0].offsetHeight - num(this, 'borderTopWidth') - num(this, 'borderBottomWidth') :
  //      this.height() + num(this, 'paddingTop') + num(this, 'paddingBottom');
  // },
	
	/**
	 * Gets the inner width (excludes the border and includes the padding) for the first matched element.
	 * If used on document, returns the document's width (innerWidth).
	 * If used on window, returns the viewport's (window) width.
	 *
	 * @example $("#testdiv").innerWidth()
	 * @result 210
	 *
	 * @name innerWidth
	 * @type Number
	 * @cat Plugins/Dimensions
	 */

  // innerWidth: function() {
  //  if (!this[0]) error();
  //  return this[0] == window || this[0] == document ?
  //    this.width() :
  //    this.is(':visible') ?
  //      this[0].offsetWidth - num(this, 'borderLeftWidth') - num(this, 'borderRightWidth') :
  //      this.width() + num(this, 'paddingLeft') + num(this, 'paddingRight');
  // },
	
	/**
	 * Gets the outer height (includes the border and padding) for the first matched element.
	 * If used on document, returns the document's height (innerHeight).
	 * If used on window, returns the viewport's (window) height.
	 *
	 * The margin can be included in the calculation by passing an options map with margin
	 * set to true.
	 *
	 * @example $("#testdiv").outerHeight()
	 * @result 220
	 *
	 * @example $("#testdiv").outerHeight({ margin: true })
	 * @result 240
	 *
	 * @name outerHeight
	 * @type Number
	 * @param Map options Optional settings to configure the way the outer height is calculated.
	 * @cat Plugins/Dimensions
	 */

  // outerHeight: function(options) {
  //  if (!this[0]) error();
  //  options = $.extend({ margin: false }, options || {});
  //  return this[0] == window || this[0] == document ?
  //    this.height() :
  //    this.is(':visible') ?
  //      this[0].offsetHeight + (options.margin ? (num(this, 'marginTop') + num(this, 'marginBottom')) : 0) :
  //      this.height() 
  //        + num(this,'borderTopWidth') + num(this, 'borderBottomWidth') 
  //        + num(this, 'paddingTop') + num(this, 'paddingBottom')
  //        + (options.margin ? (num(this, 'marginTop') + num(this, 'marginBottom')) : 0);
  // },
	
	/**
	 * Gets the outer width (including the border and padding) for the first matched element.
	 * If used on document, returns the document's width (innerWidth).
	 * If used on window, returns the viewport's (window) width.
	 *
	 * The margin can be included in the calculation by passing an options map with margin
	 * set to true.
	 *
	 * @example $("#testdiv").outerWidth()
	 * @result 1000
	 *
	 * @example $("#testdiv").outerWidth({ margin: true })
	 * @result 1020
	 * 
	 * @name outerHeight
	 * @type Number
	 * @param Map options Optional settings to configure the way the outer width is calculated.
	 * @cat Plugins/Dimensions
	 */

  // outerWidth: function(options) {
  //  if (!this[0]) error();
  //  options = $.extend({ margin: false }, options || {});
  //  return this[0] == window || this[0] == document ?
  //    this.width() :
  //    this.is(':visible') ?
  //      this[0].offsetWidth + (options.margin ? (num(this, 'marginLeft') + num(this, 'marginRight')) : 0) :
  //      this.width() 
  //        + num(this, 'borderLeftWidth') + num(this, 'borderRightWidth') 
  //        + num(this, 'paddingLeft') + num(this, 'paddingRight')
  //        + (options.margin ? (num(this, 'marginLeft') + num(this, 'marginRight')) : 0);
  // },
	
	/**
	 * Gets how many pixels the user has scrolled to the right (scrollLeft).
	 * Works on containers with overflow: auto and window/document.
	 *
	 * @example $(window).scrollLeft()
	 * @result 100
	 *
	 * @example $(document).scrollLeft()
	 * @result 100
	 * 
	 * @example $("#testdiv").scrollLeft()
	 * @result 100
	 *
	 * @name scrollLeft
	 * @type Number
	 * @cat Plugins/Dimensions
	 */
	/**
	 * Sets the scrollLeft property for each element and continues the chain.
	 * Works on containers with overflow: auto and window/document.
	 *
	 * @example $(window).scrollLeft(100).scrollLeft()
	 * @result 100
	 * 
	 * @example $(document).scrollLeft(100).scrollLeft()
	 * @result 100
	 *
	 * @example $("#testdiv").scrollLeft(100).scrollLeft()
	 * @result 100
	 *
	 * @name scrollLeft
	 * @param Number value A positive number representing the desired scrollLeft.
	 * @type jQuery
	 * @cat Plugins/Dimensions
	 */

  // scrollLeft: function(val) {
  //  if (!this[0]) error();
  //  if ( val != undefined )
  //    // set the scroll left
  //    return this.each(function() {
  //      if (this == window || this == document)
  //        window.scrollTo( val, $(window).scrollTop() );
  //      else
  //        this.scrollLeft = val;
  //    });
  //  
  //  // return the scroll left offest in pixels
  //  if ( this[0] == window || this[0] == document )
  //    return self.pageXOffset ||
  //      $.boxModel && document.documentElement.scrollLeft ||
  //      document.body.scrollLeft;
  //      
  //  return this[0].scrollLeft;
  // },
	
	/**
	 * Gets how many pixels the user has scrolled to the bottom (scrollTop).
	 * Works on containers with overflow: auto and window/document.
	 *
	 * @example $(window).scrollTop()
	 * @result 100
	 *
	 * @example $(document).scrollTop()
	 * @result 100
	 * 
	 * @example $("#testdiv").scrollTop()
	 * @result 100
	 *
	 * @name scrollTop
	 * @type Number
	 * @cat Plugins/Dimensions
	 */
	/**
	 * Sets the scrollTop property for each element and continues the chain.
	 * Works on containers with overflow: auto and window/document.
	 *
	 * @example $(window).scrollTop(100).scrollTop()
	 * @result 100
	 * 
	 * @example $(document).scrollTop(100).scrollTop()
	 * @result 100
	 *
	 * @example $("#testdiv").scrollTop(100).scrollTop()
	 * @result 100
	 *
	 * @name scrollTop
	 * @param Number value A positive number representing the desired scrollTop.
	 * @type jQuery
	 * @cat Plugins/Dimensions
	 */

  // scrollTop: function(val) {
  //  if (!this[0]) error();
  //  if ( val != undefined )
  //    // set the scroll top
  //    return this.each(function() {
  //      if (this == window || this == document)
  //        window.scrollTo( $(window).scrollLeft(), val );
  //      else
  //        this.scrollTop = val;
  //    });
  //  
  //  // return the scroll top offset in pixels
  //  if ( this[0] == window || this[0] == document )
  //    return self.pageYOffset ||
  //      $.boxModel && document.documentElement.scrollTop ||
  //      document.body.scrollTop;
  // 
  //  return this[0].scrollTop;
  // },
	
	/** 
	 * Gets the top and left positioned offset in pixels.
	 * The positioned offset is the offset between a positioned
	 * parent and the element itself.
	 *
	 * For accurate calculations make sure to use pixel values for margins, borders and padding.
	 *
	 * @example $("#testdiv").position()
	 * @result { top: 100, left: 100 }
	 *
	 * @example var position = {};
	 * $("#testdiv").position(position)
	 * @result position = { top: 100, left: 100 }
	 * 
	 * @name position
	 * @param Object returnObject Optional An object to store the return value in, so as not to break the chain. If passed in the
	 *                            chain will not be broken and the result will be assigned to this object.
	 * @type Object
	 * @cat Plugins/Dimensions
	 */
	 
  // position: function(returnObject) {
  //  return this.offset({ margin: false, scroll: false, relativeTo: this.offsetParent() }, returnObject);
  // },
	
	/**
	 * Gets the location of the element in pixels from the top left corner of the viewport.
	 * The offset method takes an optional map of key value pairs to configure the way
	 * the offset is calculated. Here are the different options.
	 *
	 * (Boolean) margin - Should the margin of the element be included in the calculations? True by default.
	 * (Boolean) border - Should the border of the element be included in the calculations? False by default. 
	 * (Boolean) padding - Should the padding of the element be included in the calculations? False by default. 
	 * (Boolean) scroll - Should the scroll offsets of the parent elements be included in the calculations? True by default.
	 *                    When true it adds the total scroll offsets of all parents to the total offset and also adds two
	 *                    properties to the returned object, scrollTop and scrollLeft.
	 * (Boolean) lite - When true it will use the offsetLite method instead of the full-blown, slower offset method. False by default.
	 *                  Only use this when margins, borders and padding calculations don't matter.
	 * (HTML Element) relativeTo - This should be a parent of the element and should have position (like absolute or relative).
	 *                             It will retreive the offset relative to this parent element. By default it is the body element.
	 *
	 * Also an object can be passed as the second paramater to
	 * catch the value of the return and continue the chain.
	 *
	 * For accurate calculations make sure to use pixel values for margins, borders and padding.
	 * 
	 * Known issues:
	 *  - Issue: A div positioned relative or static without any content before it and its parent will report an offsetTop of 0 in Safari
	 *    Workaround: Place content before the relative div ... and set height and width to 0 and overflow to hidden
	 *
	 * @example $("#testdiv").offset()
	 * @result { top: 100, left: 100, scrollTop: 10, scrollLeft: 10 }
	 *
	 * @example $("#testdiv").offset({ scroll: false })
	 * @result { top: 90, left: 90 }
	 *
	 * @example var offset = {}
	 * $("#testdiv").offset({ scroll: false }, offset)
	 * @result offset = { top: 90, left: 90 }
	 *
	 * @name offset
	 * @param Map options Optional settings to configure the way the offset is calculated.
	 * @param Object returnObject An object to store the return value in, so as not to break the chain. If passed in the
	 *                            chain will not be broken and the result will be assigned to this object.
	 * @type Object
	 * @cat Plugins/Dimensions
	 */
	 
  // offset: function(options, returnObject) {
  //  if (!this[0]) error();
  //  var x = 0, y = 0, sl = 0, st = 0,
  //      elem = this[0], parent = this[0], op, parPos, elemPos = $.css(elem, 'position'),
  //      mo = $.browser.mozilla, ie = $.browser.msie, oa = $.browser.opera,
  //      sf = $.browser.safari, sf3 = $.browser.safari && parseInt($.browser.version) > 520,
  //      absparent = false, relparent = false, 
  //      options = $.extend({ margin: true, border: false, padding: false, scroll: true, lite: false, relativeTo: document.body }, options || {});
  //  
  //  // Use offsetLite if lite option is true
  //  if (options.lite) return this.offsetLite(options, returnObject);
  //  // Get the HTMLElement if relativeTo is a jquery collection
  //  if (options.relativeTo.jquery) options.relativeTo = options.relativeTo[0];
  //  
  //  if (elem.tagName == 'BODY') {
  //    // Safari 2 is the only one to get offsetLeft and offsetTop properties of the body "correct"
  //    // Except they all mess up when the body is positioned absolute or relative
  //    x = elem.offsetLeft;
  //    y = elem.offsetTop;
  //    // Mozilla ignores margin and subtracts border from body element
  //    if (mo) {
  //      x += num(elem, 'marginLeft') + (num(elem, 'borderLeftWidth')*2);
  //      y += num(elem, 'marginTop')  + (num(elem, 'borderTopWidth') *2);
  //    } else
  //    // Opera ignores margin
  //    if (oa) {
  //      x += num(elem, 'marginLeft');
  //      y += num(elem, 'marginTop');
  //    } else
  //    // IE does not add the border in Standards Mode
  //    if ((ie && jQuery.boxModel)) {
  //      x += num(elem, 'borderLeftWidth');
  //      y += num(elem, 'borderTopWidth');
  //    } else
  //    // Safari 3 doesn't not include border or margin
  //    if (sf3) {
  //      x += num(elem, 'marginLeft') + num(elem, 'borderLeftWidth');
  //      y += num(elem, 'marginTop')  + num(elem, 'borderTopWidth');
  //    }
  //  } else {
  //    do {
  //      parPos = $.css(parent, 'position');
  //    
  //      x += parent.offsetLeft;
  //      y += parent.offsetTop;
  // 
  //      // Mozilla and IE do not add the border
  //      // Mozilla adds the border for table cells
  //      if ((mo && !parent.tagName.match(/^t[d|h]$/i)) || ie || sf3) {
  //        // add borders to offset
  //        x += num(parent, 'borderLeftWidth');
  //        y += num(parent, 'borderTopWidth');
  // 
  //        // Mozilla does not include the border on body if an element isn't positioned absolute and is without an absolute parent
  //        if (mo && parPos == 'absolute') absparent = true;
  //        // IE does not include the border on the body if an element is position static and without an absolute or relative parent
  //        if (ie && parPos == 'relative') relparent = true;
  //      }
  // 
  //      op = parent.offsetParent || document.body;
  //      if (options.scroll || mo) {
  //        do {
  //          if (options.scroll) {
  //            // get scroll offsets
  //            sl += parent.scrollLeft;
  //            st += parent.scrollTop;
  //          }
  //          
  //          // Opera sometimes incorrectly reports scroll offset for elements with display set to table-row or inline
  //          if (oa && ($.css(parent, 'display') || '').match(/table-row|inline/)) {
  //            sl = sl - ((parent.scrollLeft == parent.offsetLeft) ? parent.scrollLeft : 0);
  //            st = st - ((parent.scrollTop == parent.offsetTop) ? parent.scrollTop : 0);
  //          }
  //      
  //          // Mozilla does not add the border for a parent that has overflow set to anything but visible
  //          if (mo && parent != elem && $.css(parent, 'overflow') != 'visible') {
  //            x += num(parent, 'borderLeftWidth');
  //            y += num(parent, 'borderTopWidth');
  //          }
  //      
  //          parent = parent.parentNode;
  //        } while (parent != op);
  //      }
  //      parent = op;
  //      
  //      // exit the loop if we are at the relativeTo option but not if it is the body or html tag
  //      if (parent == options.relativeTo && !(parent.tagName == 'BODY' || parent.tagName == 'HTML'))  {
  //        // Mozilla does not add the border for a parent that has overflow set to anything but visible
  //        if (mo && parent != elem && $.css(parent, 'overflow') != 'visible') {
  //          x += num(parent, 'borderLeftWidth');
  //          y += num(parent, 'borderTopWidth');
  //        }
  //        // Safari 2 and opera includes border on positioned parents
  //        if ( ((sf && !sf3) || oa) && parPos != 'static' ) {
  //          x -= num(op, 'borderLeftWidth');
  //          y -= num(op, 'borderTopWidth');
  //        }
  //        break;
  //      }
  //      if (parent.tagName == 'BODY' || parent.tagName == 'HTML') {
  //        // Safari 2 and IE Standards Mode doesn't add the body margin for elments positioned with static or relative
  //        if (((sf && !sf3) || (ie && $.boxModel)) && elemPos != 'absolute' && elemPos != 'fixed') {
  //          x += num(parent, 'marginLeft');
  //          y += num(parent, 'marginTop');
  //        }
  //        // Safari 3 does not include the border on body
  //        // Mozilla does not include the border on body if an element isn't positioned absolute and is without an absolute parent
  //        // IE does not include the border on the body if an element is positioned static and without an absolute or relative parent
  //        if ( sf3 || (mo && !absparent && elemPos != 'fixed') || 
  //             (ie && elemPos == 'static' && !relparent) ) {
  //          x += num(parent, 'borderLeftWidth');
  //          y += num(parent, 'borderTopWidth');
  //        }
  //        break; // Exit the loop
  //      }
  //    } while (parent);
  //  }
  // 
  //  var returnValue = handleOffsetReturn(elem, options, x, y, sl, st);
  // 
  //  if (returnObject) { $.extend(returnObject, returnValue); return this; }
  //  else              { return returnValue; }
  // },
	
	/**
	 * Gets the location of the element in pixels from the top left corner of the viewport.
	 * This method is much faster than offset but not as accurate when borders and margins are
	 * on the element and/or its parents. This method can be invoked
	 * by setting the lite option to true in the offset method.
	 * The offsetLite method takes an optional map of key value pairs to configure the way
	 * the offset is calculated. Here are the different options.
	 *
	 * (Boolean) margin - Should the margin of the element be included in the calculations? True by default.
	 * (Boolean) border - Should the border of the element be included in the calculations? False by default. 
	 * (Boolean) padding - Should the padding of the element be included in the calcuations? False by default. 
	 * (Boolean) scroll - Sould the scroll offsets of the parent elements be included int he calculations? True by default.
	 *                    When true it adds the total scroll offsets of all parents to the total offset and also adds two
	 *                    properties to the returned object, scrollTop and scrollLeft.
	 * (HTML Element) relativeTo - This should be a parent of the element and should have position (like absolute or relative).
	 *                             It will retreive the offset relative to this parent element. By default it is the body element.
	 *
	 * @name offsetLite
	 * @param Map options Optional settings to configure the way the offset is calculated.
	 * @param Object returnObject An object to store the return value in, so as not to break the chain. If passed in the
	 *                            chain will not be broken and the result will be assigned to this object.
	 * @type Object
	 * @cat Plugins/Dimensions
	 */
	 
	offsetLite: function(options, returnObject) {
		if (!this[0]) error();
		var x = 0, y = 0, sl = 0, st = 0, parent = this[0], offsetParent, 
		    options = $.extend({ margin: true, border: false, padding: false, scroll: true, relativeTo: document.body }, options || {});
				
		// Get the HTMLElement if relativeTo is a jquery collection
		if (options.relativeTo.jquery) options.relativeTo = options.relativeTo[0];
		
		do {
			x += parent.offsetLeft;
			y += parent.offsetTop;

			offsetParent = parent.offsetParent || document.body;
			if (options.scroll) {
				// get scroll offsets
				do {
					sl += parent.scrollLeft;
					st += parent.scrollTop;
					parent = parent.parentNode;
				} while(parent != offsetParent);
			}
			parent = offsetParent;
		} while (parent && parent.tagName != 'BODY' && parent.tagName != 'HTML' && parent != options.relativeTo);

		var returnValue = handleOffsetReturn(this[0], options, x, y, sl, st);

		if (returnObject) { $.extend(returnObject, returnValue); return this; }
		else              { return returnValue; }
	},
	
	/**
	 * Returns a jQuery collection with the positioned parent of 
	 * the first matched element. This is the first parent of 
	 * the element that has position (as in relative or absolute).
	 *
	 * @name offsetParent
	 * @type jQuery
	 * @cat Plugins/Dimensions
	 */
	 
  // offsetParent: function() {
  //  if (!this[0]) error();
  //  var offsetParent = this[0].offsetParent;
  //  while ( offsetParent && (offsetParent.tagName != 'BODY' && $.css(offsetParent, 'position') == 'static') )
  //    offsetParent = offsetParent.offsetParent;
  //  return $(offsetParent);
  // }
});

/**
 * Throws an error message when no elements are in the jQuery collection
 * @private
 */
var error = function() {
	//throw "Dimensions: jQuery collection is empty";
};

/**
 * Handles converting a CSS Style into an Integer.
 * @private
 */
var num = function(el, prop) {
	return parseInt($.css(el.jquery?el[0]:el,prop))||0;
};

/**
 * Handles the return value of the offset and offsetLite methods.
 * @private
 */
var handleOffsetReturn = function(elem, options, x, y, sl, st) {
	if ( !options.margin ) {
		x -= num(elem, 'marginLeft');
		y -= num(elem, 'marginTop');
	}

	// Safari and Opera do not add the border for the element
	if ( options.border && (($.browser.safari && parseInt($.browser.version) < 520) || $.browser.opera) ) {
		x += num(elem, 'borderLeftWidth');
		y += num(elem, 'borderTopWidth');
	} else if ( !options.border && !(($.browser.safari && parseInt($.browser.version) < 520) || $.browser.opera) ) {
		x -= num(elem, 'borderLeftWidth');
		y -= num(elem, 'borderTopWidth');
	}

	if ( options.padding ) {
		x += num(elem, 'paddingLeft');
		y += num(elem, 'paddingTop');
	}
	
	// do not include scroll offset on the element ... opera sometimes reports scroll offset as actual offset
	if ( options.scroll && (!$.browser.opera || elem.offsetLeft != elem.scrollLeft && elem.offsetTop != elem.scrollLeft) ) {
		sl -= elem.scrollLeft;
		st -= elem.scrollTop;
	}

	return options.scroll ? { top: y - st, left: x - sl, scrollTop:  st, scrollLeft: sl }
	                      : { top: y, left: x };
};

/**
 * Gets the width of the OS scrollbar
 * @private
 */

var scrollbarWidth = 0;
var getScrollbarWidth = function() {
	if (!scrollbarWidth) {
		var testEl = $('<div>')
				.css({
					width: 100,
					height: 100,
					overflow: 'auto',
					position: 'absolute',
					top: -1000,
					left: -1000
				})
				.appendTo('body');
		scrollbarWidth = 100 - testEl
			.append('<div>')
			.find('div')
				.css({
					width: '100%',
					height: 200
				})
				.width();
		testEl.remove();
	}
	return scrollbarWidth;
};

})(jQuery);
/**
 * jGrowl 1.2.6
 *
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * Written by Stan Lemon <stosh1985@gmail.com>
 * Last updated: 2011.03.27
 *
 * jGrowl is a jQuery plugin implementing unobtrusive userland notifications.  These 
 * notifications function similarly to the Growl Framework available for
 * Mac OS X (http://growl.info).
 *
 * To Do:
 * - Move library settings to containers and allow them to be changed per container
 *
 * Changes in 1.2.6
 * - Fixed js error when a notification is opening and closing at the same time
 * 
 * Changes in 1.2.5
 * - Changed wrapper jGrowl's options usage to "o" instead of $.jGrowl.defaults
 * - Added themeState option to control 'highlight' or 'error' for jQuery UI
 * - Ammended some CSS to provide default positioning for nested usage.
 * - Changed some CSS to be prefixed with jGrowl- to prevent namespacing issues
 * - Added two new options - openDuration and closeDuration to allow 
 *   better control of notification open and close speeds, respectively 
 *   Patch contributed by Jesse Vincet.
 * - Added afterOpen callback.  Patch contributed by Russel Branca.
 *
 * Changes in 1.2.4
 * - Fixed IE bug with the close-all button
 * - Fixed IE bug with the filter CSS attribute (special thanks to gotwic)
 * - Update IE opacity CSS
 * - Changed font sizes to use "em", and only set the base style
 *
 * Changes in 1.2.3
 * - The callbacks no longer use the container as context, instead they use the actual notification
 * - The callbacks now receive the container as a parameter after the options parameter
 * - beforeOpen and beforeClose now check the return value, if it's false - the notification does
 *   not continue.  The open callback will also halt execution if it returns false.
 * - Fixed bug where containers would get confused
 * - Expanded the pause functionality to pause an entire container.
 *
 * Changes in 1.2.2
 * - Notification can now be theme rolled for jQuery UI, special thanks to Jeff Chan!
 *
 * Changes in 1.2.1
 * - Fixed instance where the interval would fire the close method multiple times.
 * - Added CSS to hide from print media
 * - Fixed issue with closer button when div { position: relative } is set
 * - Fixed leaking issue with multiple containers.  Special thanks to Matthew Hanlon!
 *
 * Changes in 1.2.0
 * - Added message pooling to limit the number of messages appearing at a given time.
 * - Closing a notification is now bound to the notification object and triggered by the close button.
 *
 * Changes in 1.1.2
 * - Added iPhone styled example
 * - Fixed possible IE7 bug when determining if the ie6 class shoudl be applied.
 * - Added template for the close button, so that it's content could be customized.
 *
 * Changes in 1.1.1
 * - Fixed CSS styling bug for ie6 caused by a mispelling
 * - Changes height restriction on default notifications to min-height
 * - Added skinned examples using a variety of images
 * - Added the ability to customize the content of the [close all] box
 * - Added jTweet, an example of using jGrowl + Twitter
 *
 * Changes in 1.1.0
 * - Multiple container and instances.
 * - Standard $.jGrowl() now wraps $.fn.jGrowl() by first establishing a generic jGrowl container.
 * - Instance methods of a jGrowl container can be called by $.fn.jGrowl(methodName)
 * - Added glue preferenced, which allows notifications to be inserted before or after nodes in the container
 * - Added new log callback which is called before anything is done for the notification
 * - Corner's attribute are now applied on an individual notification basis.
 *
 * Changes in 1.0.4
 * - Various CSS fixes so that jGrowl renders correctly in IE6.
 *
 * Changes in 1.0.3
 * - Fixed bug with options persisting across notifications
 * - Fixed theme application bug
 * - Simplified some selectors and manipulations.
 * - Added beforeOpen and beforeClose callbacks
 * - Reorganized some lines of code to be more readable
 * - Removed unnecessary this.defaults context
 * - If corners plugin is present, it's now customizable.
 * - Customizable open animation.
 * - Customizable close animation.
 * - Customizable animation easing.
 * - Added customizable positioning (top-left, top-right, bottom-left, bottom-right, center)
 *
 * Changes in 1.0.2
 * - All CSS styling is now external.
 * - Added a theme parameter which specifies a secondary class for styling, such
 *   that notifications can be customized in appearance on a per message basis.
 * - Notification life span is now customizable on a per message basis.
 * - Added the ability to disable the global closer, enabled by default.
 * - Added callbacks for when a notification is opened or closed.
 * - Added callback for the global closer.
 * - Customizable animation speed.
 * - jGrowl now set itself up and tears itself down.
 *
 * Changes in 1.0.1:
 * - Removed dependency on metadata plugin in favor of .data()
 * - Namespaced all events
 */

(function($) {

	/** jGrowl Wrapper - Establish a base jGrowl Container for compatibility with older releases. **/
	$.jGrowl = function( m , o ) {
		// To maintain compatibility with older version that only supported one instance we'll create the base container.
		if ( $('#jGrowl').size() == 0 ) 
			$('<div id="jGrowl"></div>').addClass( (o && o.position) ? o.position : $.jGrowl.defaults.position ).appendTo('body');

		// Create a notification on the container.
		$('#jGrowl').jGrowl(m,o);
	};


	/** Raise jGrowl Notification on a jGrowl Container **/
	$.fn.jGrowl = function( m , o ) {
		if ( $.isFunction(this.each) ) {
			var args = arguments;

			return this.each(function() {
				var self = this;

				/** Create a jGrowl Instance on the Container if it does not exist **/
				if ( $(this).data('jGrowl.instance') == undefined ) {
					$(this).data('jGrowl.instance', $.extend( new $.fn.jGrowl(), { notifications: [], element: null, interval: null } ));
					$(this).data('jGrowl.instance').startup( this );
				}

				/** Optionally call jGrowl instance methods, or just raise a normal notification **/
				if ( $.isFunction($(this).data('jGrowl.instance')[m]) ) {
					$(this).data('jGrowl.instance')[m].apply( $(this).data('jGrowl.instance') , $.makeArray(args).slice(1) );
				} else {
					$(this).data('jGrowl.instance').create( m , o );
				}
			});
		};
	};

	$.extend( $.fn.jGrowl.prototype , {

		/** Default JGrowl Settings **/
		defaults: {
			pool: 			0,
			header: 		'',
			group: 			'',
			sticky: 		false,
			position: 		'top-right',
			glue: 			'after',
			theme: 			'default',
			themeState: 	'highlight',
			corners: 		'10px',
			check: 			250,
			life: 			10000,
			closeDuration:  'normal',
			openDuration:   'normal',
			easing: 		'swing',
			closer: 		true,
			closeTemplate: '&times;',
			closerTemplate: '<div>[ close all ]</div>',
			log: 			function(e,m,o) {},
			beforeOpen: 	function(e,m,o) {},
			afterOpen: 		function(e,m,o) {},
			open: 			function(e,m,o) {},
			beforeClose: 	function(e,m,o) {},
			close: 			function(e,m,o) {},
			animateOpen: 	{
				opacity: 	'show'
			},
			animateClose: 	{
				opacity: 	'hide'
			}
		},
		
		notifications: [],
		
		/** jGrowl Container Node **/
		element: 	null,
	
		/** Interval Function **/
		interval:   null,
		
		/** Create a Notification **/
		// Modified: START
		create: 	function( data , o ) {
		// Modified: END
			var o = $.extend({}, this.defaults, o);

			/* To keep backward compatibility with 1.24 and earlier, honor 'speed' if the user has set it */
			if (typeof o.speed !== 'undefined') {
				o.openDuration = o.speed;
				o.closeDuration = o.speed;
			}

      // Modified: START
			this.notifications.push({ message: data , options: o });
			o.log.apply( this.element , [this.element,data.message,o] );
			// Modified: END
		},
		
		// Modified: START
		render:	function( notification ) {
			var self = this;
	    var o = notification.options;
			if(notification.message.sender) {
  			var userName = notification.message.sender.name;
  			var userId = notification.message.sender.id;
  			var message = '';
  			if(notification.message && notification.message.text) {
  			  var name = '<a href="/users/' + userId + '">' + userName + '</a>';
          var message = notification.message.text.replace(/\[sender_name\]/g, name);
          var avatar = '<a href="/users/' + userId + '"><img src="' + notification.message.sender.avatar.thumb.url + '" class="picture"></img></a>';
  			}
      }
      else {
        var message = notification.message.text;
        if(notification.message.event == "message_stack_full") {
          var avatar = '<div class="notification-full-inbox"></div>';
        }
        else {
          var avatar = '<div class="notification-blocked-inbox"></div>';
        }
      }
      // Support for jQuery theme-states, if this is not used it displays a widget header
			o.themeState = (o.themeState == '') ? '' : 'ui-state-' + o.themeState;

			var notification = $(
				'<div class="jGrowl-notification ' + o.themeState + ' ui-corner-all' + 
				((o.group != undefined && o.group != '') ? ' ' + o.group : '') + '">' +
				'<div class="jGrowl-close">' + o.closeTemplate + '</div>' +
				'<div class="jGrowl-avatar">' + avatar + '</div>' +
				'<div class="jGrowl-header">' + o.header + '</div>' +
				'<div class="jGrowl-message">' + message + '</div></div>'
			).data("jGrowl", o).addClass(o.theme).children('div.jGrowl-close').bind("click.jGrowl", function() {
				$(this).parent().trigger('jGrowl.close');
			}).parent();
      // Modified: END

			/** Notification Actions **/
			$(notification).bind("mouseover.jGrowl", function() {
				$('div.jGrowl-notification', self.element).data("jGrowl.pause", true);
			}).bind("mouseout.jGrowl", function() {
				$('div.jGrowl-notification', self.element).data("jGrowl.pause", false);
			}).bind('jGrowl.beforeOpen', function() {
				if ( o.beforeOpen.apply( notification , [notification,message,o,self.element] ) != false ) {
					$(this).trigger('jGrowl.open');
				}
			}).bind('jGrowl.open', function() {
				if ( o.open.apply( notification , [notification,message,o,self.element] ) != false ) {
					if ( o.glue == 'after' ) {
						$('div.jGrowl-notification:last', self.element).after(notification);
					} else {
						$('div.jGrowl-notification:first', self.element).before(notification);
					}
					
					$(this).animate(o.animateOpen, o.openDuration, o.easing, function() {
						// Fixes some anti-aliasing issues with IE filters.
						if ($.browser.msie && (parseInt($(this).css('opacity'), 10) === 1 || parseInt($(this).css('opacity'), 10) === 0))
							this.style.removeAttribute('filter');

						if ( $(this).data("jGrowl") != null ) // Happens when a notification is closing before it's open.
							$(this).data("jGrowl").created = new Date();
						
						$(this).trigger('jGrowl.afterOpen');
					});
				}
			}).bind('jGrowl.afterOpen', function() {
				o.afterOpen.apply( notification , [notification,message,o,self.element] );
			}).bind('jGrowl.beforeClose', function() {
				if ( o.beforeClose.apply( notification , [notification,message,o,self.element] ) != false )
					$(this).trigger('jGrowl.close');
			}).bind('jGrowl.close', function() {
				// Pause the notification, lest during the course of animation another close event gets called.
				$(this).data('jGrowl.pause', true);
				$(this).animate(o.animateClose, o.closeDuration, o.easing, function() {
					if ( $.isFunction(o.close) ) {
						if ( o.close.apply( notification , [notification,message,o,self.element] ) !== false )
							$(this).remove();
					} else {
						$(this).remove();
					}
				});
			}).trigger('jGrowl.beforeOpen');
		
			/** Optional Corners Plugin **/
			if ( o.corners != '' && $.fn.corner != undefined ) $(notification).corner( o.corners );

			/** Add a Global Closer if more than one notification exists **/
			if ( $('div.jGrowl-notification:parent', self.element).size() > 1 && 
				 $('div.jGrowl-closer', self.element).size() == 0 && this.defaults.closer != false ) {
				$(this.defaults.closerTemplate).addClass('jGrowl-closer ' + this.defaults.themeState + ' ui-corner-all').addClass(this.defaults.theme)
					.appendTo(self.element).animate(this.defaults.animateOpen, this.defaults.speed, this.defaults.easing)
					.bind("click.jGrowl", function() {
						$(this).siblings().trigger("jGrowl.beforeClose");

						if ( $.isFunction( self.defaults.closer ) ) {
							self.defaults.closer.apply( $(this).parent()[0] , [$(this).parent()[0]] );
						}
					});
			};
		},

		/** Update the jGrowl Container, removing old jGrowl notifications **/
		update:	 function() {
			$(this.element).find('div.jGrowl-notification:parent').each( function() {
				if ( $(this).data("jGrowl") != undefined && $(this).data("jGrowl").created != undefined && 
					 ($(this).data("jGrowl").created.getTime() + parseInt($(this).data("jGrowl").life))  < (new Date()).getTime() && 
					 $(this).data("jGrowl").sticky != true && 
					 ($(this).data("jGrowl.pause") == undefined || $(this).data("jGrowl.pause") != true) ) {

					// Pause the notification, lest during the course of animation another close event gets called.
					$(this).trigger('jGrowl.beforeClose');
				}
			});

			if ( this.notifications.length > 0 && 
				 (this.defaults.pool == 0 || $(this.element).find('div.jGrowl-notification:parent').size() < this.defaults.pool) )
				this.render( this.notifications.shift() );

			if ( $(this.element).find('div.jGrowl-notification:parent').size() < 2 ) {
				$(this.element).find('div.jGrowl-closer').animate(this.defaults.animateClose, this.defaults.speed, this.defaults.easing, function() {
					$(this).remove();
				});
			}
		},

		/** Setup the jGrowl Notification Container **/
		startup:	function(e) {
			this.element = $(e).addClass('jGrowl').append('<div class="jGrowl-notification"></div>');
			this.interval = setInterval( function() { 
				$(e).data('jGrowl.instance').update(); 
			}, parseInt(this.defaults.check));
			
			if ($.browser.msie && parseInt($.browser.version) < 7 && !window["XMLHttpRequest"]) {
				$(this.element).addClass('ie6');
			}
		},

		/** Shutdown jGrowl, removing it and clearing the interval **/
		shutdown:   function() {
			$(this.element).removeClass('jGrowl').find('div.jGrowl-notification').remove();
			clearInterval( this.interval );
		},
		
		close: 	function() {
			$(this.element).find('div.jGrowl-notification').each(function(){
				$(this).trigger('jGrowl.beforeClose');
			});
		}
	});
	
	/** Reference the Defaults Object for compatibility with older versions of jGrowl **/
	$.jGrowl.defaults = $.fn.jGrowl.prototype.defaults;

})(jQuery);
/*!
 * jQuery Form Plugin
 * version: 2.64 (25-FEB-2011)
 * @requires jQuery v1.3.2 or later
 *
 * Examples and documentation at: http://malsup.com/jquery/form/
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 */

;(function($) {

/*
	Usage Note:
	-----------
	Do not use both ajaxSubmit and ajaxForm on the same form.  These
	functions are intended to be exclusive.  Use ajaxSubmit if you want
	to bind your own submit handler to the form.  For example,

	$(document).ready(function() {
		$('#myForm').bind('submit', function(e) {
			e.preventDefault(); // <-- important
			$(this).ajaxSubmit({
				target: '#output'
			});
		});
	});

	Use ajaxForm when you want the plugin to manage all the event binding
	for you.  For example,

	$(document).ready(function() {
		$('#myForm').ajaxForm({
			target: '#output'
		});
	});

	When using ajaxForm, the ajaxSubmit function will be invoked for you
	at the appropriate time.
*/

/**
 * ajaxSubmit() provides a mechanism for immediately submitting
 * an HTML form using AJAX.
 */
$.fn.ajaxSubmit = function(options) {
	// fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
	if (!this.length) {
		log('ajaxSubmit: skipping submit process - no element selected');
		return this;
	}

	if (typeof options == 'function') {
		options = { success: options };
	}

	var action = this.attr('action');
	var url = (typeof action === 'string') ? $.trim(action) : '';
	if (url) {
		// clean url (don't include hash vaue)
		url = (url.match(/^([^#]+)/)||[])[1];
	}
	url = url || window.location.href || '';

	options = $.extend(true, {
		url:  url,
		type: this[0].getAttribute('method') || 'GET', // IE7 massage (see issue 57)
		iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
	}, options);

	// hook for manipulating the form data before it is extracted;
	// convenient for use with rich editors like tinyMCE or FCKEditor
	var veto = {};
	this.trigger('form-pre-serialize', [this, options, veto]);
	if (veto.veto) {
		log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
		return this;
	}

	// provide opportunity to alter form data before it is serialized
	if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
		log('ajaxSubmit: submit aborted via beforeSerialize callback');
		return this;
	}

	var n,v,a = this.formToArray(options.semantic);
	if (options.data) {
		options.extraData = options.data;
		for (n in options.data) {
			if(options.data[n] instanceof Array) {
				for (var k in options.data[n]) {
					a.push( { name: n, value: options.data[n][k] } );
				}
			}
			else {
				v = options.data[n];
				v = $.isFunction(v) ? v() : v; // if value is fn, invoke it
				a.push( { name: n, value: v } );
			}
		}
	}

	// give pre-submit callback an opportunity to abort the submit
	if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
		log('ajaxSubmit: submit aborted via beforeSubmit callback');
		return this;
	}

	// fire vetoable 'validate' event
	this.trigger('form-submit-validate', [a, this, options, veto]);
	if (veto.veto) {
		log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
		return this;
	}

	var q = $.param(a);

	if (options.type.toUpperCase() == 'GET') {
		options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
		options.data = null;  // data is null for 'get'
	}
	else {
		options.data = q; // data is the query string for 'post'
	}

	var $form = this, callbacks = [];
	if (options.resetForm) {
		callbacks.push(function() { $form.resetForm(); });
	}
	if (options.clearForm) {
		callbacks.push(function() { $form.clearForm(); });
	}

	// perform a load on the target only if dataType is not provided
	if (!options.dataType && options.target) {
		var oldSuccess = options.success || function(){};
		callbacks.push(function(data) {
			var fn = options.replaceTarget ? 'replaceWith' : 'html';
			$(options.target)[fn](data).each(oldSuccess, arguments);
		});
	}
	else if (options.success) {
		callbacks.push(options.success);
	}

	options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg
		var context = options.context || options;   // jQuery 1.4+ supports scope context 
		for (var i=0, max=callbacks.length; i < max; i++) {
			callbacks[i].apply(context, [data, status, xhr || $form, $form]);
		}
	};

	// are there files to upload?
	var fileInputs = $('input:file', this).length > 0;
	var mp = 'multipart/form-data';
	var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);

	// options.iframe allows user to force iframe mode
	// 06-NOV-09: now defaulting to iframe mode if file input is detected
   if (options.iframe !== false && (fileInputs || options.iframe || multipart)) {
	   // hack to fix Safari hang (thanks to Tim Molendijk for this)
	   // see:  http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
	   if (options.closeKeepAlive) {
		   $.get(options.closeKeepAlive, fileUpload);
		}
	   else {
		   fileUpload();
		}
   }
   else {
		$.ajax(options);
   }

	// fire 'notify' event
	this.trigger('form-submit-notify', [this, options]);
	return this;


	// private function for handling file uploads (hat tip to YAHOO!)
	function fileUpload() {
		var form = $form[0];

		if ($(':input[name=submit],:input[id=submit]', form).length) {
			// if there is an input with a name or id of 'submit' then we won't be
			// able to invoke the submit fn on the form (at least not x-browser)
			alert('Error: Form elements must not have name or id of "submit".');
			return;
		}
		
		var s = $.extend(true, {}, $.ajaxSettings, options);
		s.context = s.context || s;
		var id = 'jqFormIO' + (new Date().getTime()), fn = '_'+id;
		var $io = $('<iframe id="' + id + '" name="' + id + '" src="'+ s.iframeSrc +'" />');
		var io = $io[0];

		$io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });

		var xhr = { // mock object
			aborted: 0,
			responseText: null,
			responseXML: null,
			status: 0,
			statusText: 'n/a',
			getAllResponseHeaders: function() {},
			getResponseHeader: function() {},
			setRequestHeader: function() {},
			abort: function() {
				this.aborted = 1;
				$io.attr('src', s.iframeSrc); // abort op in progress
			}
		};

		var g = s.global;
		// trigger ajax global events so that activity/block indicators work like normal
		if (g && ! $.active++) {
			$.event.trigger("ajaxStart");
		}
		if (g) {
			$.event.trigger("ajaxSend", [xhr, s]);
		}

		if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {
			if (s.global) { 
				$.active--;
			}
			return;
		}
		if (xhr.aborted) {
			return;
		}

		var timedOut = 0;

		// add submitting element to data if we know it
		var sub = form.clk;
		if (sub) {
			var n = sub.name;
			if (n && !sub.disabled) {
				s.extraData = s.extraData || {};
				s.extraData[n] = sub.value;
				if (sub.type == "image") {
					s.extraData[n+'.x'] = form.clk_x;
					s.extraData[n+'.y'] = form.clk_y;
				}
			}
		}

		// take a breath so that pending repaints get some cpu time before the upload starts
		function doSubmit() {
			// make sure form attrs are set
			var t = $form.attr('target'), a = $form.attr('action');

			// update form attrs in IE friendly way
			form.setAttribute('target',id);
			if (form.getAttribute('method') != 'POST') {
				form.setAttribute('method', 'POST');
			}
			if (form.getAttribute('action') != s.url) {
				form.setAttribute('action', s.url);
			}

			// ie borks in some cases when setting encoding
			if (! s.skipEncodingOverride) {
				$form.attr({
					encoding: 'multipart/form-data',
					enctype:  'multipart/form-data'
				});
			}

			// support timout
			if (s.timeout) {
				setTimeout(function() { timedOut = true; cb(); }, s.timeout);
			}

			// add "extra" data to form if provided in options
			var extraInputs = [];
			try {
				if (s.extraData) {
					for (var n in s.extraData) {
						extraInputs.push(
							$('<input type="hidden" name="'+n+'" value="'+s.extraData[n]+'" />')
								.appendTo(form)[0]);
					}
				}

				// add iframe to doc and submit the form
				$io.appendTo('body');
                io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false);
				form.submit();
			}
			finally {
				// reset attrs and remove "extra" input elements
				form.setAttribute('action',a);
				if(t) {
					form.setAttribute('target', t);
				} else {
					$form.removeAttr('target');
				}
				$(extraInputs).remove();
			}
		}

		if (s.forceSync) {
			doSubmit();
		}
		else {
			setTimeout(doSubmit, 10); // this lets dom updates render
		}
	
		var data, doc, domCheckCount = 50;

		function cb() {
			doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document;
			if (!doc || doc.location.href == s.iframeSrc) {
				// response not received yet
				return;
			}
            io.detachEvent ? io.detachEvent('onload', cb) : io.removeEventListener('load', cb, false);

			var ok = true;
			try {
				if (timedOut) {
					throw 'timeout';
				}

				var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
				log('isXml='+isXml);
				if (!isXml && window.opera && (doc.body == null || doc.body.innerHTML == '')) {
					if (--domCheckCount) {
						// in some browsers (Opera) the iframe DOM is not always traversable when
						// the onload callback fires, so we loop a bit to accommodate
						log('requeing onLoad callback, DOM not available');
						setTimeout(cb, 250);
						return;
					}
					// let this fall through because server response could be an empty document
					//log('Could not access iframe DOM after mutiple tries.');
					//throw 'DOMException: not available';
				}

				//log('response detected');
				xhr.responseText = doc.body ? doc.body.innerHTML : doc.documentElement ? doc.documentElement.innerHTML : null; 
				xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
				xhr.getResponseHeader = function(header){
					var headers = {'content-type': s.dataType};
					return headers[header];
				};

				var scr = /(json|script)/.test(s.dataType);
				if (scr || s.textarea) {
					// see if user embedded response in textarea
					var ta = doc.getElementsByTagName('textarea')[0];
					if (ta) {
						xhr.responseText = ta.value;
					}
					else if (scr) {
						// account for browsers injecting pre around json response
						var pre = doc.getElementsByTagName('pre')[0];
						var b = doc.getElementsByTagName('body')[0];
						if (pre) {
							xhr.responseText = pre.textContent;
						}
						else if (b) {
							xhr.responseText = b.innerHTML;
						}
					}			  
				}
				else if (s.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) {
					xhr.responseXML = toXml(xhr.responseText);
				}
				
				data = httpData(xhr, s.dataType, s);
			}
			catch(e){
				log('error caught:',e);
				ok = false;
				xhr.error = e;
				s.error && s.error.call(s.context, xhr, 'error', e);
				g && $.event.trigger("ajaxError", [xhr, s, e]);
			}
			
			if (xhr.aborted) {
				log('upload aborted');
				ok = false;
			}

			// ordering of these callbacks/triggers is odd, but that's how $.ajax does it
			if (ok) {
				s.success && s.success.call(s.context, data, 'success', xhr);
				g && $.event.trigger("ajaxSuccess", [xhr, s]);
			}
			
			g && $.event.trigger("ajaxComplete", [xhr, s]);

			if (g && ! --$.active) {
				$.event.trigger("ajaxStop");
			}
			
			s.complete && s.complete.call(s.context, xhr, ok ? 'success' : 'error');

			// clean up
			setTimeout(function() {
				$io.removeData('form-plugin-onload');
				$io.remove();
				xhr.responseXML = null;
			}, 100);
		}

		var toXml = $.parseXML || function(s, doc) { // use parseXML if available (jQuery 1.5+)
			if (window.ActiveXObject) {
				doc = new ActiveXObject('Microsoft.XMLDOM');
				doc.async = 'false';
				doc.loadXML(s);
			}
			else {
				doc = (new DOMParser()).parseFromString(s, 'text/xml');
			}
			return (doc && doc.documentElement && doc.documentElement.nodeName != 'parsererror') ? doc : null;
		};
		var parseJSON = $.parseJSON || function(s) {
			return window['eval']('(' + s + ')');
		};
		
		var httpData = function( xhr, type, s ) { // mostly lifted from jq1.4.4
			var ct = xhr.getResponseHeader('content-type') || '',
				xml = type === 'xml' || !type && ct.indexOf('xml') >= 0,
				data = xml ? xhr.responseXML : xhr.responseText;

			if (xml && data.documentElement.nodeName === 'parsererror') {
				$.error && $.error('parsererror');
			}
			if (s && s.dataFilter) {
				data = s.dataFilter(data, type);
			}
			if (typeof data === 'string') {
				if (type === 'json' || !type && ct.indexOf('json') >= 0) {
					data = parseJSON(data);
				} else if (type === "script" || !type && ct.indexOf("javascript") >= 0) {
					$.globalEval(data);
				}
			}
			return data;
		};
	}
};

/**
 * ajaxForm() provides a mechanism for fully automating form submission.
 *
 * The advantages of using this method instead of ajaxSubmit() are:
 *
 * 1: This method will include coordinates for <input type="image" /> elements (if the element
 *	is used to submit the form).
 * 2. This method will include the submit element's name/value data (for the element that was
 *	used to submit the form).
 * 3. This method binds the submit() method to the form for you.
 *
 * The options argument for ajaxForm works exactly as it does for ajaxSubmit.  ajaxForm merely
 * passes the options argument along after properly binding events for submit elements and
 * the form itself.
 */
$.fn.ajaxForm = function(options) {
	// in jQuery 1.3+ we can fix mistakes with the ready state
	if (this.length === 0) {
		var o = { s: this.selector, c: this.context };
		if (!$.isReady && o.s) {
			log('DOM not ready, queuing ajaxForm');
			$(function() {
				$(o.s,o.c).ajaxForm(options);
			});
			return this;
		}
		// is your DOM ready?  http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
		log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
		return this;
	}
	
	return this.ajaxFormUnbind().bind('submit.form-plugin', function(e) {
		if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
			e.preventDefault();
			$(this).ajaxSubmit(options);
		}
	}).bind('click.form-plugin', function(e) {
		var target = e.target;
		var $el = $(target);
		if (!($el.is(":submit,input:image"))) {
			// is this a child element of the submit el?  (ex: a span within a button)
			var t = $el.closest(':submit');
			if (t.length == 0) {
				return;
			}
			target = t[0];
		}
		var form = this;
		form.clk = target;
		if (target.type == 'image') {
			if (e.offsetX != undefined) {
				form.clk_x = e.offsetX;
				form.clk_y = e.offsetY;
			} else if (typeof $.fn.offset == 'function') { // try to use dimensions plugin
				var offset = $el.offset();
				form.clk_x = e.pageX - offset.left;
				form.clk_y = e.pageY - offset.top;
			} else {
				form.clk_x = e.pageX - target.offsetLeft;
				form.clk_y = e.pageY - target.offsetTop;
			}
		}
		// clear form vars
		setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);
	});
};

// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
$.fn.ajaxFormUnbind = function() {
	return this.unbind('submit.form-plugin click.form-plugin');
};

/**
 * formToArray() gathers form element data into an array of objects that can
 * be passed to any of the following ajax functions: $.get, $.post, or load.
 * Each object in the array has both a 'name' and 'value' property.  An example of
 * an array for a simple login form might be:
 *
 * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
 *
 * It is this array that is passed to pre-submit callback functions provided to the
 * ajaxSubmit() and ajaxForm() methods.
 */
$.fn.formToArray = function(semantic) {
	var a = [];
	if (this.length === 0) {
		return a;
	}

	var form = this[0];
	var els = semantic ? form.getElementsByTagName('*') : form.elements;
	if (!els) {
		return a;
	}
	
	var i,j,n,v,el,max,jmax;
	for(i=0, max=els.length; i < max; i++) {
		el = els[i];
		n = el.name;
		if (!n) {
			continue;
		}

		if (semantic && form.clk && el.type == "image") {
			// handle image inputs on the fly when semantic == true
			if(!el.disabled && form.clk == el) {
				a.push({name: n, value: $(el).val()});
				a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
			}
			continue;
		}

		v = $.fieldValue(el, true);
		if (v && v.constructor == Array) {
			for(j=0, jmax=v.length; j < jmax; j++) {
				a.push({name: n, value: v[j]});
			}
		}
		else if (v !== null && typeof v != 'undefined') {
			a.push({name: n, value: v});
		}
	}

	if (!semantic && form.clk) {
		// input type=='image' are not found in elements array! handle it here
		var $input = $(form.clk), input = $input[0];
		n = input.name;
		if (n && !input.disabled && input.type == 'image') {
			a.push({name: n, value: $input.val()});
			a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
		}
	}
	return a;
};

/**
 * Serializes form data into a 'submittable' string. This method will return a string
 * in the format: name1=value1&amp;name2=value2
 */
$.fn.formSerialize = function(semantic) {
	//hand off to jQuery.param for proper encoding
	return $.param(this.formToArray(semantic));
};

/**
 * Serializes all field elements in the jQuery object into a query string.
 * This method will return a string in the format: name1=value1&amp;name2=value2
 */
$.fn.fieldSerialize = function(successful) {
	var a = [];
	this.each(function() {
		var n = this.name;
		if (!n) {
			return;
		}
		var v = $.fieldValue(this, successful);
		if (v && v.constructor == Array) {
			for (var i=0,max=v.length; i < max; i++) {
				a.push({name: n, value: v[i]});
			}
		}
		else if (v !== null && typeof v != 'undefined') {
			a.push({name: this.name, value: v});
		}
	});
	//hand off to jQuery.param for proper encoding
	return $.param(a);
};

/**
 * Returns the value(s) of the element in the matched set.  For example, consider the following form:
 *
 *  <form><fieldset>
 *	  <input name="A" type="text" />
 *	  <input name="A" type="text" />
 *	  <input name="B" type="checkbox" value="B1" />
 *	  <input name="B" type="checkbox" value="B2"/>
 *	  <input name="C" type="radio" value="C1" />
 *	  <input name="C" type="radio" value="C2" />
 *  </fieldset></form>
 *
 *  var v = $(':text').fieldValue();
 *  // if no values are entered into the text inputs
 *  v == ['','']
 *  // if values entered into the text inputs are 'foo' and 'bar'
 *  v == ['foo','bar']
 *
 *  var v = $(':checkbox').fieldValue();
 *  // if neither checkbox is checked
 *  v === undefined
 *  // if both checkboxes are checked
 *  v == ['B1', 'B2']
 *
 *  var v = $(':radio').fieldValue();
 *  // if neither radio is checked
 *  v === undefined
 *  // if first radio is checked
 *  v == ['C1']
 *
 * The successful argument controls whether or not the field element must be 'successful'
 * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
 * The default value of the successful argument is true.  If this value is false the value(s)
 * for each element is returned.
 *
 * Note: This method *always* returns an array.  If no valid value can be determined the
 *	   array will be empty, otherwise it will contain one or more values.
 */
$.fn.fieldValue = function(successful) {
	for (var val=[], i=0, max=this.length; i < max; i++) {
		var el = this[i];
		var v = $.fieldValue(el, successful);
		if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) {
			continue;
		}
		v.constructor == Array ? $.merge(val, v) : val.push(v);
	}
	return val;
};

/**
 * Returns the value of the field element.
 */
$.fieldValue = function(el, successful) {
	var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
	if (successful === undefined) {
		successful = true;
	}

	if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
		(t == 'checkbox' || t == 'radio') && !el.checked ||
		(t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
		tag == 'select' && el.selectedIndex == -1)) {
			return null;
	}

	if (tag == 'select') {
		var index = el.selectedIndex;
		if (index < 0) {
			return null;
		}
		var a = [], ops = el.options;
		var one = (t == 'select-one');
		var max = (one ? index+1 : ops.length);
		for(var i=(one ? index : 0); i < max; i++) {
			var op = ops[i];
			if (op.selected) {
				var v = op.value;
				if (!v) { // extra pain for IE...
					v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
				}
				if (one) {
					return v;
				}
				a.push(v);
			}
		}
		return a;
	}
	return $(el).val();
};

/**
 * Clears the form data.  Takes the following actions on the form's input fields:
 *  - input text fields will have their 'value' property set to the empty string
 *  - select elements will have their 'selectedIndex' property set to -1
 *  - checkbox and radio inputs will have their 'checked' property set to false
 *  - inputs of type submit, button, reset, and hidden will *not* be effected
 *  - button elements will *not* be effected
 */
$.fn.clearForm = function() {
	return this.each(function() {
		$('input,select,textarea', this).clearFields();
	});
};

/**
 * Clears the selected form elements.
 */
$.fn.clearFields = $.fn.clearInputs = function() {
	return this.each(function() {
		var t = this.type, tag = this.tagName.toLowerCase();
		if (t == 'text' || t == 'password' || tag == 'textarea') {
			this.value = '';
		}
		else if (t == 'checkbox' || t == 'radio') {
			this.checked = false;
		}
		else if (tag == 'select') {
			this.selectedIndex = -1;
		}
	});
};

/**
 * Resets the form data.  Causes all form elements to be reset to their original value.
 */
$.fn.resetForm = function() {
	return this.each(function() {
		// guard against an input with the name of 'reset'
		// note that IE reports the reset function as an 'object'
		if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) {
			this.reset();
		}
	});
};

/**
 * Enables or disables any matching elements.
 */
$.fn.enable = function(b) {
	if (b === undefined) {
		b = true;
	}
	return this.each(function() {
		this.disabled = !b;
	});
};

/**
 * Checks/unchecks any matching checkboxes or radio buttons and
 * selects/deselects and matching option elements.
 */
$.fn.selected = function(select) {
	if (select === undefined) {
		select = true;
	}
	return this.each(function() {
		var t = this.type;
		if (t == 'checkbox' || t == 'radio') {
			this.checked = select;
		}
		else if (this.tagName.toLowerCase() == 'option') {
			var $sel = $(this).parent('select');
			if (select && $sel[0] && $sel[0].type == 'select-one') {
				// deselect all other options
				$sel.find('option').selected(false);
			}
			this.selected = select;
		}
	});
};

// helper fn for console logging
// set $.fn.ajaxSubmit.debug to true to enable debug logging
function log() {
	if ($.fn.ajaxSubmit.debug) {
		var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
		if (window.console && window.console.log) {
			window.console.log(msg);
		}
		else if (window.opera && window.opera.postError) {
			window.opera.postError(msg);
		}
	}
};

})(jQuery);
(function($, undefined) {

/**
 * Unobtrusive scripting adapter for jQuery
 *
 * Requires jQuery 1.6.0 or later.
 * https://github.com/rails/jquery-ujs

 * Uploading file using rails.js
 * =============================
 *
 * By default, browsers do not allow files to be uploaded via AJAX. As a result, if there are any non-blank file fields
 * in the remote form, this adapter aborts the AJAX submission and allows the form to submit through standard means.
 *
 * The `ajax:aborted:file` event allows you to bind your own handler to process the form submission however you wish.
 *
 * Ex:
 *     $('form').live('ajax:aborted:file', function(event, elements){
 *       // Implement own remote file-transfer handler here for non-blank file inputs passed in `elements`.
 *       // Returning false in this handler tells rails.js to disallow standard form submission
 *       return false;
 *     });
 *
 * The `ajax:aborted:file` event is fired when a file-type input is detected with a non-blank value.
 *
 * Third-party tools can use this hook to detect when an AJAX file upload is attempted, and then use
 * techniques like the iframe method to upload the file instead.
 *
 * Required fields in rails.js
 * ===========================
 *
 * If any blank required inputs (required="required") are detected in the remote form, the whole form submission
 * is canceled. Note that this is unlike file inputs, which still allow standard (non-AJAX) form submission.
 *
 * The `ajax:aborted:required` event allows you to bind your own handler to inform the user of blank required inputs.
 *
 * !! Note that Opera does not fire the form's submit event if there are blank required inputs, so this event may never
 *    get fired in Opera. This event is what causes other browsers to exhibit the same submit-aborting behavior.
 *
 * Ex:
 *     $('form').live('ajax:aborted:required', function(event, elements){
 *       // Returning false in this handler tells rails.js to submit the form anyway.
 *       // The blank required inputs are passed to this function in `elements`.
 *       return ! confirm("Would you like to submit the form with missing info?");
 *     });
 */

  // Shorthand to make it a little easier to call public rails functions from within rails.js
  var rails;

  $.rails = rails = {
    // Link elements bound by jquery-ujs
    linkClickSelector: 'a[data-confirm], a[data-method], a[data-remote], a[data-disable-with]',

    // Select elements bound by jquery-ujs
    inputChangeSelector: 'select[data-remote], input[data-remote], textarea[data-remote]',

    // Form elements bound by jquery-ujs
    formSubmitSelector: 'form',

    // Form input elements bound by jquery-ujs
    formInputClickSelector: 'form input[type=submit], form input[type=image], form button[type=submit], form button:not(button[type])',

    // Form input elements disabled during form submission
    disableSelector: 'input[data-disable-with], button[data-disable-with], textarea[data-disable-with]',

    // Form input elements re-enabled after form submission
    enableSelector: 'input[data-disable-with]:disabled, button[data-disable-with]:disabled, textarea[data-disable-with]:disabled',

    // Form required input elements
    requiredInputSelector: 'input[name][required]:not([disabled]),textarea[name][required]:not([disabled])',

    // Form file input elements
    fileInputSelector: 'input:file',

    // Link onClick disable selector with possible reenable after remote submission
    linkDisableSelector: 'a[data-disable-with]',

    // Make sure that every Ajax request sends the CSRF token
    CSRFProtection: function(xhr) {
      var token = $('meta[name="csrf-token"]').attr('content');
      if (token) xhr.setRequestHeader('X-CSRF-Token', token);
    },

    // Triggers an event on an element and returns false if the event result is false
    fire: function(obj, name, data) {
      var event = $.Event(name);
      obj.trigger(event, data);
      return event.result !== false;
    },

    // Default confirm dialog, may be overridden with custom confirm dialog in $.rails.confirm
    confirm: function(message) {
      return confirm(message);
    },

    // Default ajax function, may be overridden with custom function in $.rails.ajax
    ajax: function(options) {
      return $.ajax(options);
    },

    // Submits "remote" forms and links with ajax
    handleRemote: function(element) {
      var method, url, data,
        crossDomain = element.data('cross-domain') || null,
        dataType = element.data('type') || ($.ajaxSettings && $.ajaxSettings.dataType),
        options;

      if (rails.fire(element, 'ajax:before')) {

        if (element.is('form')) {
          method = element.attr('method');
          url = element.attr('action');
          data = element.serializeArray();
          // memoized value from clicked submit button
          var button = element.data('ujs:submit-button');
          if (button) {
            data.push(button);
            element.data('ujs:submit-button', null);
          }
        } else if (element.is(rails.inputChangeSelector)) {
          method = element.data('method');
          url = element.data('url');
          data = element.serialize();
          if (element.data('params')) data = data + "&" + element.data('params');
        } else {
          method = element.data('method');
          url = element.attr('href');
          data = element.data('params') || null;
        }

        options = {
          type: method || 'GET', data: data, dataType: dataType, crossDomain: crossDomain,
          // stopping the "ajax:beforeSend" event will cancel the ajax request
          beforeSend: function(xhr, settings) {
            if (settings.dataType === undefined) {
              xhr.setRequestHeader('accept', '*/*;q=0.5, ' + settings.accepts.script);
            }
            return rails.fire(element, 'ajax:beforeSend', [xhr, settings]);
          },
          success: function(data, status, xhr) {
            element.trigger('ajax:success', [data, status, xhr]);
          },
          complete: function(xhr, status) {
            element.trigger('ajax:complete', [xhr, status]);
          },
          error: function(xhr, status, error) {
            element.trigger('ajax:error', [xhr, status, error]);
          }
        };
        // Only pass url to `ajax` options if not blank
        if (url) { options.url = url; }

        return rails.ajax(options);
      } else {
        return false;
      }
    },

    // Handles "data-method" on links such as:
    // <a href="/users/5" data-method="delete" rel="nofollow" data-confirm="Are you sure?">Delete</a>
    handleMethod: function(link) {
      var href = link.attr('href'),
        method = link.data('method'),
        target = link.attr('target'),
        csrf_token = $('meta[name=csrf-token]').attr('content'),
        csrf_param = $('meta[name=csrf-param]').attr('content'),
        form = $('<form method="post" action="' + href + '"></form>'),
        metadata_input = '<input name="_method" value="' + method + '" type="hidden" />';

      if (csrf_param !== undefined && csrf_token !== undefined) {
        metadata_input += '<input name="' + csrf_param + '" value="' + csrf_token + '" type="hidden" />';
      }

      if (target) { form.attr('target', target); }

      form.hide().append(metadata_input).appendTo('body');
      form.submit();
    },

    /* Disables form elements:
      - Caches element value in 'ujs:enable-with' data store
      - Replaces element text with value of 'data-disable-with' attribute
      - Sets disabled property to true
    */
    disableFormElements: function(form) {
      form.find(rails.disableSelector).each(function() {
        var element = $(this), method = element.is('button') ? 'html' : 'val';
        element.data('ujs:enable-with', element[method]());
        element[method](element.data('disable-with'));
        element.prop('disabled', true);
      });
    },

    /* Re-enables disabled form elements:
      - Replaces element text with cached value from 'ujs:enable-with' data store (created in `disableFormElements`)
      - Sets disabled property to false
    */
    enableFormElements: function(form) {
      form.find(rails.enableSelector).each(function() {
        var element = $(this), method = element.is('button') ? 'html' : 'val';
        if (element.data('ujs:enable-with')) element[method](element.data('ujs:enable-with'));
        element.prop('disabled', false);
      });
    },

   /* For 'data-confirm' attribute:
      - Fires `confirm` event
      - Shows the confirmation dialog
      - Fires the `confirm:complete` event

      Returns `true` if no function stops the chain and user chose yes; `false` otherwise.
      Attaching a handler to the element's `confirm` event that returns a `falsy` value cancels the confirmation dialog.
      Attaching a handler to the element's `confirm:complete` event that returns a `falsy` value makes this function
      return false. The `confirm:complete` event is fired whether or not the user answered true or false to the dialog.
   */
    allowAction: function(element) {
      var message = element.data('confirm'),
          answer = false, callback;
      if (!message) { return true; }

      if (rails.fire(element, 'confirm')) {
        answer = rails.confirm(message);
        callback = rails.fire(element, 'confirm:complete', [answer]);
      }
      return answer && callback;
    },

    // Helper function which checks for blank inputs in a form that match the specified CSS selector
    blankInputs: function(form, specifiedSelector, nonBlank) {
      var inputs = $(), input,
        selector = specifiedSelector || 'input,textarea';
      form.find(selector).each(function() {
        input = $(this);
        // Collect non-blank inputs if nonBlank option is true, otherwise, collect blank inputs
        if (nonBlank ? input.val() : !input.val()) {
          inputs = inputs.add(input);
        }
      });
      return inputs.length ? inputs : false;
    },

    // Helper function which checks for non-blank inputs in a form that match the specified CSS selector
    nonBlankInputs: function(form, specifiedSelector) {
      return rails.blankInputs(form, specifiedSelector, true); // true specifies nonBlank
    },

    // Helper function, needed to provide consistent behavior in IE
    stopEverything: function(e) {
      $(e.target).trigger('ujs:everythingStopped');
      e.stopImmediatePropagation();
      return false;
    },

    // find all the submit events directly bound to the form and
    // manually invoke them. If anyone returns false then stop the loop
    callFormSubmitBindings: function(form, event) {
      var events = form.data('events'), continuePropagation = true;
      if (events !== undefined && events['submit'] !== undefined) {
        $.each(events['submit'], function(i, obj){
          if (typeof obj.handler === 'function') return continuePropagation = obj.handler(event);
        });
      }
      return continuePropagation;
    },

    //  replace element's html with the 'data-disable-with' after storing original html
    //  and prevent clicking on it
    disableElement: function(element) {
      element.data('ujs:enable-with', element.html()); // store enabled state
      element.html(element.data('disable-with')); // set to disabled state
      element.bind('click.railsDisable', function(e) { // prevent further clicking
        return rails.stopEverything(e)
      });
    },

    // restore element to its original state which was disabled by 'disableElement' above
    enableElement: function(element) {
      if (element.data('ujs:enable-with') !== undefined) {
        element.html(element.data('ujs:enable-with')); // set to old enabled state
        // this should be element.removeData('ujs:enable-with')
        // but, there is currently a bug in jquery which makes hyphenated data attributes not get removed
        element.data('ujs:enable-with', false); // clean up cache
      }
      element.unbind('click.railsDisable'); // enable element
    }

  };

  $.ajaxPrefilter(function(options, originalOptions, xhr){ if ( !options.crossDomain ) { rails.CSRFProtection(xhr); }});

  $(document).delegate(rails.linkDisableSelector, 'ajax:complete', function() {
      rails.enableElement($(this));
  });

  $(document).delegate(rails.linkClickSelector, 'click.rails', function(e) {
    var link = $(this), method = link.data('method'), data = link.data('params');
    if (!rails.allowAction(link)) return rails.stopEverything(e);

    if (link.is(rails.linkDisableSelector)) rails.disableElement(link);

    if (link.data('remote') !== undefined) {
      if ( (e.metaKey || e.ctrlKey) && (!method || method === 'GET') && !data ) { return true; }

      if (rails.handleRemote(link) === false) { rails.enableElement(link); }
      return false;

    } else if (link.data('method')) {
      rails.handleMethod(link);
      return false;
    }
  });

  $(document).delegate(rails.inputChangeSelector, 'change.rails', function(e) {
    var link = $(this);
    if (!rails.allowAction(link)) return rails.stopEverything(e);

    rails.handleRemote(link);
    return false;
  });

  $(document).delegate(rails.formSubmitSelector, 'submit.rails', function(e) {
    var form = $(this),
      remote = form.data('remote') !== undefined,
      blankRequiredInputs = rails.blankInputs(form, rails.requiredInputSelector),
      nonBlankFileInputs = rails.nonBlankInputs(form, rails.fileInputSelector);

    if (!rails.allowAction(form)) return rails.stopEverything(e);

    // skip other logic when required values are missing or file upload is present
    if (blankRequiredInputs && form.attr("novalidate") == undefined && rails.fire(form, 'ajax:aborted:required', [blankRequiredInputs])) {
      return rails.stopEverything(e);
    }

    if (remote) {
      if (nonBlankFileInputs) {
        return rails.fire(form, 'ajax:aborted:file', [nonBlankFileInputs]);
      }

      // If browser does not support submit bubbling, then this live-binding will be called before direct
      // bindings. Therefore, we should directly call any direct bindings before remotely submitting form.
      if (!$.support.submitBubbles && $().jquery < '1.7' && rails.callFormSubmitBindings(form, e) === false) return rails.stopEverything(e);

      rails.handleRemote(form);
      return false;

    } else {
      // slight timeout so that the submit button gets properly serialized
      setTimeout(function(){ rails.disableFormElements(form); }, 13);
    }
  });

  $(document).delegate(rails.formInputClickSelector, 'click.rails', function(event) {
    var button = $(this);

    if (!rails.allowAction(button)) return rails.stopEverything(event);

    // register the pressed submit button
    var name = button.attr('name'),
      data = name ? {name:name, value:button.val()} : null;

    button.closest('form').data('ujs:submit-button', data);
  });

  $(document).delegate(rails.formSubmitSelector, 'ajax:beforeSend.rails', function(event) {
    if (this == event.target) rails.disableFormElements($(this));
  });

  $(document).delegate(rails.formSubmitSelector, 'ajax:complete.rails', function(event) {
    if (this == event.target) rails.enableFormElements($(this));
  });

})( jQuery );
/*
 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
 *
 * Uses the built in easing capabilities added In jQuery 1.1
 * to offer multiple easing options
 *
 * TERMS OF USE - jQuery Easing
 * 
 * Open source under the BSD License. 
 * 
 * Copyright © 2008 George McGinley Smith
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification, 
 * are permitted provided that the following conditions are met:
 * 
 * Redistributions of source code must retain the above copyright notice, this list of 
 * conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, this list 
 * of conditions and the following disclaimer in the documentation and/or other materials 
 * provided with the distribution.
 * 
 * Neither the name of the author nor the names of contributors may be used to endorse 
 * or promote products derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
 * OF THE POSSIBILITY OF SUCH DAMAGE. 
 *
*/


// t: current time, b: begInnIng value, c: change In value, d: duration
eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('h.i[\'1a\']=h.i[\'z\'];h.O(h.i,{y:\'D\',z:9(x,t,b,c,d){6 h.i[h.i.y](x,t,b,c,d)},17:9(x,t,b,c,d){6 c*(t/=d)*t+b},D:9(x,t,b,c,d){6-c*(t/=d)*(t-2)+b},13:9(x,t,b,c,d){e((t/=d/2)<1)6 c/2*t*t+b;6-c/2*((--t)*(t-2)-1)+b},X:9(x,t,b,c,d){6 c*(t/=d)*t*t+b},U:9(x,t,b,c,d){6 c*((t=t/d-1)*t*t+1)+b},R:9(x,t,b,c,d){e((t/=d/2)<1)6 c/2*t*t*t+b;6 c/2*((t-=2)*t*t+2)+b},N:9(x,t,b,c,d){6 c*(t/=d)*t*t*t+b},M:9(x,t,b,c,d){6-c*((t=t/d-1)*t*t*t-1)+b},L:9(x,t,b,c,d){e((t/=d/2)<1)6 c/2*t*t*t*t+b;6-c/2*((t-=2)*t*t*t-2)+b},K:9(x,t,b,c,d){6 c*(t/=d)*t*t*t*t+b},J:9(x,t,b,c,d){6 c*((t=t/d-1)*t*t*t*t+1)+b},I:9(x,t,b,c,d){e((t/=d/2)<1)6 c/2*t*t*t*t*t+b;6 c/2*((t-=2)*t*t*t*t+2)+b},G:9(x,t,b,c,d){6-c*8.C(t/d*(8.g/2))+c+b},15:9(x,t,b,c,d){6 c*8.n(t/d*(8.g/2))+b},12:9(x,t,b,c,d){6-c/2*(8.C(8.g*t/d)-1)+b},Z:9(x,t,b,c,d){6(t==0)?b:c*8.j(2,10*(t/d-1))+b},Y:9(x,t,b,c,d){6(t==d)?b+c:c*(-8.j(2,-10*t/d)+1)+b},W:9(x,t,b,c,d){e(t==0)6 b;e(t==d)6 b+c;e((t/=d/2)<1)6 c/2*8.j(2,10*(t-1))+b;6 c/2*(-8.j(2,-10*--t)+2)+b},V:9(x,t,b,c,d){6-c*(8.o(1-(t/=d)*t)-1)+b},S:9(x,t,b,c,d){6 c*8.o(1-(t=t/d-1)*t)+b},Q:9(x,t,b,c,d){e((t/=d/2)<1)6-c/2*(8.o(1-t*t)-1)+b;6 c/2*(8.o(1-(t-=2)*t)+1)+b},P:9(x,t,b,c,d){f s=1.l;f p=0;f a=c;e(t==0)6 b;e((t/=d)==1)6 b+c;e(!p)p=d*.3;e(a<8.w(c)){a=c;f s=p/4}m f s=p/(2*8.g)*8.r(c/a);6-(a*8.j(2,10*(t-=1))*8.n((t*d-s)*(2*8.g)/p))+b},H:9(x,t,b,c,d){f s=1.l;f p=0;f a=c;e(t==0)6 b;e((t/=d)==1)6 b+c;e(!p)p=d*.3;e(a<8.w(c)){a=c;f s=p/4}m f s=p/(2*8.g)*8.r(c/a);6 a*8.j(2,-10*t)*8.n((t*d-s)*(2*8.g)/p)+c+b},T:9(x,t,b,c,d){f s=1.l;f p=0;f a=c;e(t==0)6 b;e((t/=d/2)==2)6 b+c;e(!p)p=d*(.3*1.5);e(a<8.w(c)){a=c;f s=p/4}m f s=p/(2*8.g)*8.r(c/a);e(t<1)6-.5*(a*8.j(2,10*(t-=1))*8.n((t*d-s)*(2*8.g)/p))+b;6 a*8.j(2,-10*(t-=1))*8.n((t*d-s)*(2*8.g)/p)*.5+c+b},F:9(x,t,b,c,d,s){e(s==u)s=1.l;6 c*(t/=d)*t*((s+1)*t-s)+b},E:9(x,t,b,c,d,s){e(s==u)s=1.l;6 c*((t=t/d-1)*t*((s+1)*t+s)+1)+b},16:9(x,t,b,c,d,s){e(s==u)s=1.l;e((t/=d/2)<1)6 c/2*(t*t*(((s*=(1.B))+1)*t-s))+b;6 c/2*((t-=2)*t*(((s*=(1.B))+1)*t+s)+2)+b},A:9(x,t,b,c,d){6 c-h.i.v(x,d-t,0,c,d)+b},v:9(x,t,b,c,d){e((t/=d)<(1/2.k)){6 c*(7.q*t*t)+b}m e(t<(2/2.k)){6 c*(7.q*(t-=(1.5/2.k))*t+.k)+b}m e(t<(2.5/2.k)){6 c*(7.q*(t-=(2.14/2.k))*t+.11)+b}m{6 c*(7.q*(t-=(2.18/2.k))*t+.19)+b}},1b:9(x,t,b,c,d){e(t<d/2)6 h.i.A(x,t*2,0,c,d)*.5+b;6 h.i.v(x,t*2-d,0,c,d)*.5+c*.5+b}});',62,74,'||||||return||Math|function|||||if|var|PI|jQuery|easing|pow|75|70158|else|sin|sqrt||5625|asin|||undefined|easeOutBounce|abs||def|swing|easeInBounce|525|cos|easeOutQuad|easeOutBack|easeInBack|easeInSine|easeOutElastic|easeInOutQuint|easeOutQuint|easeInQuint|easeInOutQuart|easeOutQuart|easeInQuart|extend|easeInElastic|easeInOutCirc|easeInOutCubic|easeOutCirc|easeInOutElastic|easeOutCubic|easeInCirc|easeInOutExpo|easeInCubic|easeOutExpo|easeInExpo||9375|easeInOutSine|easeInOutQuad|25|easeOutSine|easeInOutBack|easeInQuad|625|984375|jswing|easeInOutBounce'.split('|'),0,{}))

/*
 *
 * TERMS OF USE - EASING EQUATIONS
 * 
 * Open source under the BSD License. 
 * 
 * Copyright © 2001 Robert Penner
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification, 
 * are permitted provided that the following conditions are met:
 * 
 * Redistributions of source code must retain the above copyright notice, this list of 
 * conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, this list 
 * of conditions and the following disclaimer in the documentation and/or other materials 
 * provided with the distribution.
 * 
 * Neither the name of the author nor the names of contributors may be used to endorse 
 * or promote products derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
 * OF THE POSSIBILITY OF SUCH DAMAGE. 
 *
 */
/*
 * FancyBox - jQuery Plugin
 * Simple and fancy lightbox alternative
 *
 * Examples and documentation at: http://fancybox.net
 *
 * Copyright (c) 2008 - 2010 Janis Skarnelis
 * That said, it is hardly a one-person project. Many people have submitted bugs, code, and offered their advice freely. Their support is greatly appreciated.
 *
 * Version: 1.3.4 (11/11/2010)
 * Requires: jQuery v1.3+
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 */


;(function($) {
	var tmp, loading, overlay, wrap, outer, content, close, title, nav_left, nav_right,

		selectedIndex = 0, selectedOpts = {}, selectedArray = [], currentIndex = 0, currentOpts = {}, currentArray = [],

		ajaxLoader = null, imgPreloader = new Image(), imgRegExp = /\.(jpg|gif|png|bmp|jpeg)(.*)?$/i, swfRegExp = /[^\.]\.(swf)\s*$/i,

		loadingTimer, loadingFrame = 1,

		titleHeight = 0, titleStr = '', start_pos, final_pos, busy = false, fx = $.extend($('<div/>')[0], { prop: 0 }),

		isIE6 = $.browser.msie && $.browser.version < 7 && !window.XMLHttpRequest,

		/*
		 * Private methods 
		 */

		_abort = function() {
			loading.hide();

			imgPreloader.onerror = imgPreloader.onload = null;

			if (ajaxLoader) {
				ajaxLoader.abort();
			}

			tmp.empty();
		},

		_error = function() {
			if (false === selectedOpts.onError(selectedArray, selectedIndex, selectedOpts)) {
				loading.hide();
				busy = false;
				return;
			}

			selectedOpts.titleShow = false;

			selectedOpts.width = 'auto';
			selectedOpts.height = 'auto';

			tmp.html( '<p id="fancybox-error">The requested content cannot be loaded.<br />Please try again later.</p>' );

			_process_inline();
		},

		_start = function() {
			var obj = selectedArray[ selectedIndex ],
				href, 
				type, 
				title,
				str,
				emb,
				ret;

			_abort();

			selectedOpts = $.extend({}, $.fn.fancybox.defaults, (typeof $(obj).data('fancybox') == 'undefined' ? selectedOpts : $(obj).data('fancybox')));

			ret = selectedOpts.onStart(selectedArray, selectedIndex, selectedOpts);

			if (ret === false) {
				busy = false;
				return;
			} else if (typeof ret == 'object') {
				selectedOpts = $.extend(selectedOpts, ret);
			}

			title = selectedOpts.title || (obj.nodeName ? $(obj).attr('title') : obj.title) || '';

			if (obj.nodeName && !selectedOpts.orig) {
				selectedOpts.orig = $(obj).children("img:first").length ? $(obj).children("img:first") : $(obj);
			}

			if (title === '' && selectedOpts.orig && selectedOpts.titleFromAlt) {
				title = selectedOpts.orig.attr('alt');
			}

			href = selectedOpts.href || (obj.nodeName ? $(obj).attr('href') : obj.href) || null;

			if ((/^(?:javascript)/i).test(href) || href == '#') {
				href = null;
			}

			if (selectedOpts.type) {
				type = selectedOpts.type;

				if (!href) {
					href = selectedOpts.content;
				}

			} else if (selectedOpts.content) {
				type = 'html';

			} else if (href) {
				if (href.match(imgRegExp)) {
					type = 'image';

				} else if (href.match(swfRegExp)) {
					type = 'swf';

				} else if ($(obj).hasClass("iframe")) {
					type = 'iframe';

				} else if (href.indexOf("#") === 0) {
					type = 'inline';

				} else {
					type = 'ajax';
				}
			}

			if (!type) {
				_error();
				return;
			}

			if (type == 'inline') {
				obj	= href.substr(href.indexOf("#"));
				type = $(obj).length > 0 ? 'inline' : 'ajax';
			}

			selectedOpts.type = type;
			selectedOpts.href = href;
			selectedOpts.title = title;

			if (selectedOpts.autoDimensions) {
				if (selectedOpts.type == 'html' || selectedOpts.type == 'inline' || selectedOpts.type == 'ajax') {
					selectedOpts.width = 'auto';
					selectedOpts.height = 'auto';
				} else {
					selectedOpts.autoDimensions = false;	
				}
			}

			if (selectedOpts.modal) {
				selectedOpts.overlayShow = true;
				selectedOpts.hideOnOverlayClick = false;
				selectedOpts.hideOnContentClick = false;
				selectedOpts.enableEscapeButton = false;
				selectedOpts.showCloseButton = false;
			}

			selectedOpts.padding = parseInt(selectedOpts.padding, 10);
			selectedOpts.margin = parseInt(selectedOpts.margin, 10);

			tmp.css('padding', (selectedOpts.padding + selectedOpts.margin));

			$('.fancybox-inline-tmp').unbind('fancybox-cancel').bind('fancybox-change', function() {
				$(this).replaceWith(content.children());				
			});

			switch (type) {
				case 'html' :
					tmp.html( selectedOpts.content );
					_process_inline();
				break;

				case 'inline' :
					if ( $(obj).parent().is('#fancybox-content') === true) {
						busy = false;
						return;
					}

					$('<div class="fancybox-inline-tmp" />')
						.hide()
						.insertBefore( $(obj) )
						.bind('fancybox-cleanup', function() {
							$(this).replaceWith(content.children());
						}).bind('fancybox-cancel', function() {
							$(this).replaceWith(tmp.children());
						});

					$(obj).appendTo(tmp);

					_process_inline();
				break;

				case 'image':
					busy = false;

					$.fancybox.showActivity();

					imgPreloader = new Image();

					imgPreloader.onerror = function() {
						_error();
					};

					imgPreloader.onload = function() {
						busy = true;

						imgPreloader.onerror = imgPreloader.onload = null;

						_process_image();
					};

					imgPreloader.src = href;
				break;

				case 'swf':
					selectedOpts.scrolling = 'no';

					str = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="' + selectedOpts.width + '" height="' + selectedOpts.height + '"><param name="movie" value="' + href + '"></param>';
					emb = '';

					$.each(selectedOpts.swf, function(name, val) {
						str += '<param name="' + name + '" value="' + val + '"></param>';
						emb += ' ' + name + '="' + val + '"';
					});

					str += '<embed src="' + href + '" type="application/x-shockwave-flash" width="' + selectedOpts.width + '" height="' + selectedOpts.height + '"' + emb + '></embed></object>';

					tmp.html(str);

					_process_inline();
				break;

				case 'ajax':
					busy = false;

					$.fancybox.showActivity();

					selectedOpts.ajax.win = selectedOpts.ajax.success;

					ajaxLoader = $.ajax($.extend({}, selectedOpts.ajax, {
						url	: href,
						data : selectedOpts.ajax.data || {},
						error : function(XMLHttpRequest, textStatus, errorThrown) {
							if ( XMLHttpRequest.status > 0 ) {
								_error();
							}
						},
						success : function(data, textStatus, XMLHttpRequest) {
							var o = typeof XMLHttpRequest == 'object' ? XMLHttpRequest : ajaxLoader;
							if (o.status == 200) {
								if ( typeof selectedOpts.ajax.win == 'function' ) {
									ret = selectedOpts.ajax.win(href, data, textStatus, XMLHttpRequest);

									if (ret === false) {
										loading.hide();
										return;
									} else if (typeof ret == 'string' || typeof ret == 'object') {
										data = ret;
									}
								}

								tmp.html( data );
								_process_inline();
							}
						}
					}));

				break;

				case 'iframe':
					_show();
				break;
			}
		},

		_process_inline = function() {
			var
				w = selectedOpts.width,
				h = selectedOpts.height;

			if (w.toString().indexOf('%') > -1) {
				w = parseInt( ($(window).width() - (selectedOpts.margin * 2)) * parseFloat(w) / 100, 10) + 'px';

			} else {
				w = w == 'auto' ? 'auto' : w + 'px';	
			}

			if (h.toString().indexOf('%') > -1) {
				h = parseInt( ($(window).height() - (selectedOpts.margin * 2)) * parseFloat(h) / 100, 10) + 'px';

			} else {
				h = h == 'auto' ? 'auto' : h + 'px';	
			}

			tmp.wrapInner('<div style="width:' + w + ';height:' + h + ';overflow: ' + (selectedOpts.scrolling == 'auto' ? 'auto' : (selectedOpts.scrolling == 'yes' ? 'scroll' : 'hidden')) + ';position:relative;"></div>');

			selectedOpts.width = tmp.width();
			selectedOpts.height = tmp.height();

			_show();
		},

		_process_image = function() {
			selectedOpts.width = imgPreloader.width;
			selectedOpts.height = imgPreloader.height;

			$("<img />").attr({
				'id' : 'fancybox-img',
				'src' : imgPreloader.src,
				'alt' : selectedOpts.title
			}).appendTo( tmp );

			_show();
		},

		_show = function() {
			var pos, equal;

			loading.hide();

			if (wrap.is(":visible") && false === currentOpts.onCleanup(currentArray, currentIndex, currentOpts)) {
				$.event.trigger('fancybox-cancel');

				busy = false;
				return;
			}

			busy = true;

			$(content.add( overlay )).unbind();

			$(window).unbind("resize.fb scroll.fb");
			$(document).unbind('keydown.fb');

			if (wrap.is(":visible") && currentOpts.titlePosition !== 'outside') {
				wrap.css('height', wrap.height());
			}

			currentArray = selectedArray;
			currentIndex = selectedIndex;
			currentOpts = selectedOpts;

			if (currentOpts.overlayShow) {
				overlay.css({
					'background-color' : currentOpts.overlayColor,
					'opacity' : currentOpts.overlayOpacity,
					'cursor' : currentOpts.hideOnOverlayClick ? 'pointer' : 'auto',
					'height' : $(document).height()
				});

				if (!overlay.is(':visible')) {
					if (isIE6) {
						$('select:not(#fancybox-tmp select)').filter(function() {
							return this.style.visibility !== 'hidden';
						}).css({'visibility' : 'hidden'}).one('fancybox-cleanup', function() {
							this.style.visibility = 'inherit';
						});
					}

					overlay.show();
				}
			} else {
				overlay.hide();
			}

			final_pos = _get_zoom_to();

			_process_title();

			if (wrap.is(":visible")) {
				$( close.add( nav_left ).add( nav_right ) ).hide();

				pos = wrap.position(),

				start_pos = {
					top	 : pos.top,
					left : pos.left,
					width : wrap.width(),
					height : wrap.height()
				};

				equal = (start_pos.width == final_pos.width && start_pos.height == final_pos.height);

				content.fadeTo(currentOpts.changeFade, 0.3, function() {
					var finish_resizing = function() {
						content.html( tmp.contents() ).fadeTo(currentOpts.changeFade, 1, _finish);
					};

					$.event.trigger('fancybox-change');

					content
						.empty()
						.removeAttr('filter')
						.css({
							'border-width' : currentOpts.padding,
							'width'	: final_pos.width - currentOpts.padding * 2,
							'height' : selectedOpts.autoDimensions ? 'auto' : final_pos.height - titleHeight - currentOpts.padding * 2
						});

					if (equal) {
						finish_resizing();

					} else {
						fx.prop = 0;

						$(fx).animate({prop: 1}, {
							 duration : currentOpts.changeSpeed,
							 easing : currentOpts.easingChange,
							 step : _draw,
							 complete : finish_resizing
						});
					}
				});

				return;
			}

			wrap.removeAttr("style");

			content.css('border-width', currentOpts.padding);

			if (currentOpts.transitionIn == 'elastic') {
				start_pos = _get_zoom_from();

				content.html( tmp.contents() );

				wrap.show();

				if (currentOpts.opacity) {
					final_pos.opacity = 0;
				}

				fx.prop = 0;

				$(fx).animate({prop: 1}, {
					 duration : currentOpts.speedIn,
					 easing : currentOpts.easingIn,
					 step : _draw,
					 complete : _finish
				});

				return;
			}

			if (currentOpts.titlePosition == 'inside' && titleHeight > 0) {	
				title.show();	
			}

			content
				.css({
					'width' : final_pos.width - currentOpts.padding * 2,
					'height' : selectedOpts.autoDimensions ? 'auto' : final_pos.height - titleHeight - currentOpts.padding * 2
				})
				.html( tmp.contents() );

			wrap
				.css(final_pos)
				.fadeIn( currentOpts.transitionIn == 'none' ? 0 : currentOpts.speedIn, _finish );
		},

		_format_title = function(title) {
			if (title && title.length) {
				if (currentOpts.titlePosition == 'float') {
					return '<table id="fancybox-title-float-wrap" cellpadding="0" cellspacing="0"><tr><td id="fancybox-title-float-left"></td><td id="fancybox-title-float-main">' + title + '</td><td id="fancybox-title-float-right"></td></tr></table>';
				}

				return '<div id="fancybox-title-' + currentOpts.titlePosition + '">' + title + '</div>';
			}

			return false;
		},

		_process_title = function() {
			titleStr = currentOpts.title || '';
			titleHeight = 0;

			title
				.empty()
				.removeAttr('style')
				.removeClass();

			if (currentOpts.titleShow === false) {
				title.hide();
				return;
			}

			titleStr = $.isFunction(currentOpts.titleFormat) ? currentOpts.titleFormat(titleStr, currentArray, currentIndex, currentOpts) : _format_title(titleStr);

			if (!titleStr || titleStr === '') {
				title.hide();
				return;
			}

			title
				.addClass('fancybox-title-' + currentOpts.titlePosition)
				.html( titleStr )
				.appendTo( 'body' )
				.show();

			switch (currentOpts.titlePosition) {
				case 'inside':
					title
						.css({
							'width' : final_pos.width - (currentOpts.padding * 2),
							'marginLeft' : currentOpts.padding,
							'marginRight' : currentOpts.padding
						});

					titleHeight = title.outerHeight(true);

					title.appendTo( outer );

					final_pos.height += titleHeight;
				break;

				case 'over':
					title
						.css({
							'marginLeft' : currentOpts.padding,
							'width'	: final_pos.width - (currentOpts.padding * 2),
							'bottom' : currentOpts.padding
						})
						.appendTo( outer );
				break;

				case 'float':
					title
						.css('left', parseInt((title.width() - final_pos.width - 40)/ 2, 10) * -1)
						.appendTo( wrap );
				break;

				default:
					title
						.css({
							'width' : final_pos.width - (currentOpts.padding * 2),
							'paddingLeft' : currentOpts.padding,
							'paddingRight' : currentOpts.padding
						})
						.appendTo( wrap );
				break;
			}

			title.hide();
		},

		_set_navigation = function() {
			if (currentOpts.enableEscapeButton || currentOpts.enableKeyboardNav) {
				$(document).bind('keydown.fb', function(e) {
					if (e.keyCode == 27 && currentOpts.enableEscapeButton) {
						e.preventDefault();
						$.fancybox.close();

					} else if ((e.keyCode == 37 || e.keyCode == 39) && currentOpts.enableKeyboardNav && e.target.tagName !== 'INPUT' && e.target.tagName !== 'TEXTAREA' && e.target.tagName !== 'SELECT') {
						e.preventDefault();
						$.fancybox[ e.keyCode == 37 ? 'prev' : 'next']();
					}
				});
			}

			if (!currentOpts.showNavArrows) { 
				nav_left.hide();
				nav_right.hide();
				return;
			}

			if ((currentOpts.cyclic && currentArray.length > 1) || currentIndex !== 0) {
				nav_left.show();
			}

			if ((currentOpts.cyclic && currentArray.length > 1) || currentIndex != (currentArray.length -1)) {
				nav_right.show();
			}
		},

		_finish = function () {
			if (!$.support.opacity) {
				content.get(0).style.removeAttribute('filter');
				wrap.get(0).style.removeAttribute('filter');
			}

			if (selectedOpts.autoDimensions) {
				content.css('height', 'auto');
			}

			wrap.css('height', 'auto');

			if (titleStr && titleStr.length) {
				title.show();
			}

			if (currentOpts.showCloseButton) {
				close.show();
			}

			_set_navigation();
	
			if (currentOpts.hideOnContentClick)	{
				content.bind('click', $.fancybox.close);
			}

			if (currentOpts.hideOnOverlayClick)	{
				overlay.bind('click', $.fancybox.close);
			}

			$(window).bind("resize.fb", $.fancybox.resize);

			if (currentOpts.centerOnScroll) {
				$(window).bind("scroll.fb", $.fancybox.center);
			}

			if (currentOpts.type == 'iframe') {
				$('<iframe id="fancybox-frame" name="fancybox-frame' + new Date().getTime() + '" frameborder="0" hspace="0" ' + ($.browser.msie ? 'allowtransparency="true""' : '') + ' scrolling="' + selectedOpts.scrolling + '" src="' + currentOpts.href + '"></iframe>').appendTo(content);
			}

			wrap.show();

			busy = false;

			$.fancybox.center();

			currentOpts.onComplete(currentArray, currentIndex, currentOpts);

			_preload_images();
		},

		_preload_images = function() {
			var href, 
				objNext;

			if ((currentArray.length -1) > currentIndex) {
				href = currentArray[ currentIndex + 1 ].href;

				if (typeof href !== 'undefined' && href.match(imgRegExp)) {
					objNext = new Image();
					objNext.src = href;
				}
			}

			if (currentIndex > 0) {
				href = currentArray[ currentIndex - 1 ].href;

				if (typeof href !== 'undefined' && href.match(imgRegExp)) {
					objNext = new Image();
					objNext.src = href;
				}
			}
		},

		_draw = function(pos) {
			var dim = {
				width : parseInt(start_pos.width + (final_pos.width - start_pos.width) * pos, 10),
				height : parseInt(start_pos.height + (final_pos.height - start_pos.height) * pos, 10),

				top : parseInt(start_pos.top + (final_pos.top - start_pos.top) * pos, 10),
				left : parseInt(start_pos.left + (final_pos.left - start_pos.left) * pos, 10)
			};

			if (typeof final_pos.opacity !== 'undefined') {
				dim.opacity = pos < 0.5 ? 0.5 : pos;
			}

			wrap.css(dim);

			content.css({
				'width' : dim.width - currentOpts.padding * 2,
				'height' : dim.height - (titleHeight * pos) - currentOpts.padding * 2
			});
		},

		_get_viewport = function() {
			return [
				$(window).width() - (currentOpts.margin * 2),
				$(window).height() - (currentOpts.margin * 2),
				$(document).scrollLeft() + currentOpts.margin,
				$(document).scrollTop() + currentOpts.margin
			];
		},

		_get_zoom_to = function () {
			var view = _get_viewport(),
				to = {},
				resize = currentOpts.autoScale,
				double_padding = currentOpts.padding * 2,
				ratio;

			if (currentOpts.width.toString().indexOf('%') > -1) {
				to.width = parseInt((view[0] * parseFloat(currentOpts.width)) / 100, 10);
			} else {
				to.width = currentOpts.width + double_padding;
			}

			if (currentOpts.height.toString().indexOf('%') > -1) {
				to.height = parseInt((view[1] * parseFloat(currentOpts.height)) / 100, 10);
			} else {
				to.height = currentOpts.height + double_padding;
			}

			if (resize && (to.width > view[0] || to.height > view[1])) {
				if (selectedOpts.type == 'image' || selectedOpts.type == 'swf') {
					ratio = (currentOpts.width ) / (currentOpts.height );

					if ((to.width ) > view[0]) {
						to.width = view[0];
						to.height = parseInt(((to.width - double_padding) / ratio) + double_padding, 10);
					}

					if ((to.height) > view[1]) {
						to.height = view[1];
						to.width = parseInt(((to.height - double_padding) * ratio) + double_padding, 10);
					}

				} else {
					to.width = Math.min(to.width, view[0]);
					to.height = Math.min(to.height, view[1]);
				}
			}

			to.top = parseInt(Math.max(view[3] - 20, view[3] + ((view[1] - to.height - 40) * 0.5)), 10);
			to.left = parseInt(Math.max(view[2] - 20, view[2] + ((view[0] - to.width - 40) * 0.5)), 10);

			return to;
		},

		_get_obj_pos = function(obj) {
			var pos = obj.offset();

			pos.top += parseInt( obj.css('paddingTop'), 10 ) || 0;
			pos.left += parseInt( obj.css('paddingLeft'), 10 ) || 0;

			pos.top += parseInt( obj.css('border-top-width'), 10 ) || 0;
			pos.left += parseInt( obj.css('border-left-width'), 10 ) || 0;

			pos.width = obj.width();
			pos.height = obj.height();

			return pos;
		},

		_get_zoom_from = function() {
			var orig = selectedOpts.orig ? $(selectedOpts.orig) : false,
				from = {},
				pos,
				view;

			if (orig && orig.length) {
				pos = _get_obj_pos(orig);

				from = {
					width : pos.width + (currentOpts.padding * 2),
					height : pos.height + (currentOpts.padding * 2),
					top	: pos.top - currentOpts.padding - 20,
					left : pos.left - currentOpts.padding - 20
				};

			} else {
				view = _get_viewport();

				from = {
					width : currentOpts.padding * 2,
					height : currentOpts.padding * 2,
					top	: parseInt(view[3] + view[1] * 0.5, 10),
					left : parseInt(view[2] + view[0] * 0.5, 10)
				};
			}

			return from;
		},

		_animate_loading = function() {
			if (!loading.is(':visible')){
				clearInterval(loadingTimer);
				return;
			}

			$('div', loading).css('top', (loadingFrame * -40) + 'px');

			loadingFrame = (loadingFrame + 1) % 12;
		};

	/*
	 * Public methods 
	 */

	$.fn.fancybox = function(options) {
		if (!$(this).length) {
			return this;
		}

		$(this)
			.data('fancybox', $.extend({}, options, ($.metadata ? $(this).metadata() : {})))
			.unbind('click.fb')
			.bind('click.fb', function(e) {
				e.preventDefault();

				if (busy) {
					return;
				}

				busy = true;

				$(this).blur();

				selectedArray = [];
				selectedIndex = 0;

				var rel = $(this).attr('rel') || '';

				if (!rel || rel == '' || rel === 'nofollow') {
					selectedArray.push(this);

				} else {
					selectedArray = $("a[rel=" + rel + "], area[rel=" + rel + "]");
					selectedIndex = selectedArray.index( this );
				}

				_start();

				return;
			});

		return this;
	};

	$.fancybox = function(obj) {
		var opts;

		if (busy) {
			return;
		}

		busy = true;
		opts = typeof arguments[1] !== 'undefined' ? arguments[1] : {};

		selectedArray = [];
		selectedIndex = parseInt(opts.index, 10) || 0;

		if ($.isArray(obj)) {
			for (var i = 0, j = obj.length; i < j; i++) {
				if (typeof obj[i] == 'object') {
					$(obj[i]).data('fancybox', $.extend({}, opts, obj[i]));
				} else {
					obj[i] = $({}).data('fancybox', $.extend({content : obj[i]}, opts));
				}
			}

			selectedArray = jQuery.merge(selectedArray, obj);

		} else {
			if (typeof obj == 'object') {
				$(obj).data('fancybox', $.extend({}, opts, obj));
			} else {
				obj = $({}).data('fancybox', $.extend({content : obj}, opts));
			}

			selectedArray.push(obj);
		}

		if (selectedIndex > selectedArray.length || selectedIndex < 0) {
			selectedIndex = 0;
		}

		_start();
	};

	$.fancybox.showActivity = function() {
		clearInterval(loadingTimer);

		loading.show();
		loadingTimer = setInterval(_animate_loading, 66);
	};

	$.fancybox.hideActivity = function() {
		loading.hide();
	};

	$.fancybox.next = function() {
		return $.fancybox.pos( currentIndex + 1);
	};

	$.fancybox.prev = function() {
		return $.fancybox.pos( currentIndex - 1);
	};

	$.fancybox.pos = function(pos) {
		if (busy) {
			return;
		}

		pos = parseInt(pos);

		selectedArray = currentArray;

		if (pos > -1 && pos < currentArray.length) {
			selectedIndex = pos;
			_start();

		} else if (currentOpts.cyclic && currentArray.length > 1) {
			selectedIndex = pos >= currentArray.length ? 0 : currentArray.length - 1;
			_start();
		}

		return;
	};

	$.fancybox.cancel = function() {
		if (busy) {
			return;
		}

		busy = true;

		$.event.trigger('fancybox-cancel');

		_abort();

		selectedOpts.onCancel(selectedArray, selectedIndex, selectedOpts);

		busy = false;
	};

	// Note: within an iframe use - parent.$.fancybox.close();
	$.fancybox.close = function() {
		if (busy || wrap.is(':hidden')) {
			return;
		}

		busy = true;

		if (currentOpts && false === currentOpts.onCleanup(currentArray, currentIndex, currentOpts)) {
			busy = false;
			return;
		}

		_abort();

		$(close.add( nav_left ).add( nav_right )).hide();

		$(content.add( overlay )).unbind();

		$(window).unbind("resize.fb scroll.fb");
		$(document).unbind('keydown.fb');

		content.find('iframe').attr('src', isIE6 && /^https/i.test(window.location.href || '') ? 'javascript:void(false)' : 'about:blank');

		if (currentOpts.titlePosition !== 'inside') {
			title.empty();
		}

		wrap.stop();

		function _cleanup() {
			overlay.fadeOut('fast');

			title.empty().hide();
			wrap.hide();

			$.event.trigger('fancybox-cleanup');

			content.empty();

			currentOpts.onClosed(currentArray, currentIndex, currentOpts);

			currentArray = selectedOpts	= [];
			currentIndex = selectedIndex = 0;
			currentOpts = selectedOpts	= {};

			busy = false;
		}

		if (currentOpts.transitionOut == 'elastic') {
			start_pos = _get_zoom_from();

			var pos = wrap.position();

			final_pos = {
				top	 : pos.top ,
				left : pos.left,
				width :	wrap.width(),
				height : wrap.height()
			};

			if (currentOpts.opacity) {
				final_pos.opacity = 1;
			}

			title.empty().hide();

			fx.prop = 1;

			$(fx).animate({ prop: 0 }, {
				 duration : currentOpts.speedOut,
				 easing : currentOpts.easingOut,
				 step : _draw,
				 complete : _cleanup
			});

		} else {
			wrap.fadeOut( currentOpts.transitionOut == 'none' ? 0 : currentOpts.speedOut, _cleanup);
		}
	};

	$.fancybox.resize = function() {
		if (overlay.is(':visible')) {
			overlay.css('height', $(document).height());
		}

		$.fancybox.center(true);
	};

	$.fancybox.center = function() {
		var view, align;

		if (busy) {
			return;	
		}

		align = arguments[0] === true ? 1 : 0;
		view = _get_viewport();

		if (!align && (wrap.width() > view[0] || wrap.height() > view[1])) {
			return;	
		}

		wrap
			.stop()
			.animate({
				'top' : parseInt(Math.max(view[3] - 20, view[3] + ((view[1] - content.height() - 40) * 0.5) - currentOpts.padding)),
				'left' : parseInt(Math.max(view[2] - 20, view[2] + ((view[0] - content.width() - 40) * 0.5) - currentOpts.padding))
			}, typeof arguments[0] == 'number' ? arguments[0] : 200);
	};

	$.fancybox.init = function() {
		if ($("#fancybox-wrap").length) {
			return;
		}

		$('body').append(
			tmp	= $('<div id="fancybox-tmp"></div>'),
			loading	= $('<div id="fancybox-loading"><div></div></div>'),
			overlay	= $('<div id="fancybox-overlay"></div>'),
			wrap = $('<div id="fancybox-wrap"></div>')
		);

		outer = $('<div id="fancybox-outer"></div>')
			.append('<div class="fancybox-bg" id="fancybox-bg-n"></div><div class="fancybox-bg" id="fancybox-bg-ne"></div><div class="fancybox-bg" id="fancybox-bg-e"></div><div class="fancybox-bg" id="fancybox-bg-se"></div><div class="fancybox-bg" id="fancybox-bg-s"></div><div class="fancybox-bg" id="fancybox-bg-sw"></div><div class="fancybox-bg" id="fancybox-bg-w"></div><div class="fancybox-bg" id="fancybox-bg-nw"></div>')
			.appendTo( wrap );

		outer.append(
			content = $('<div id="fancybox-content"></div>'),
			close = $('<a id="fancybox-close" class="tooltip_2" title="Schließen"></a>'),
			title = $('<div id="fancybox-title"></div>'),

			nav_left = $('<a href="javascript:;" id="fancybox-left"><span class="fancy-ico" id="fancybox-left-ico"></span></a>'),
			nav_right = $('<a href="javascript:;" id="fancybox-right"><span class="fancy-ico" id="fancybox-right-ico"></span></a>')
		);

		close.click($.fancybox.close);
		loading.click($.fancybox.cancel);

		nav_left.click(function(e) {
			e.preventDefault();
			$.fancybox.prev();
		});

		nav_right.click(function(e) {
			e.preventDefault();
			$.fancybox.next();
		});

		if ($.fn.mousewheel) {
			wrap.bind('mousewheel.fb', function(e, delta) {
				if (busy) {
					e.preventDefault();

				} else if ($(e.target).get(0).clientHeight == 0 || $(e.target).get(0).scrollHeight === $(e.target).get(0).clientHeight) {
					e.preventDefault();
					$.fancybox[ delta > 0 ? 'prev' : 'next']();
				}
			});
		}

		if (!$.support.opacity) {
			wrap.addClass('fancybox-ie');
		}

		if (isIE6) {
			loading.addClass('fancybox-ie6');
			wrap.addClass('fancybox-ie6');

			$('<iframe id="fancybox-hide-sel-frame" src="' + (/^https/i.test(window.location.href || '') ? 'javascript:void(false)' : 'about:blank' ) + '" scrolling="no" border="0" frameborder="0" tabindex="-1"></iframe>').prependTo(outer);
		}
	};

	$.fn.fancybox.defaults = {
		padding : 10,
		margin : 40,
		opacity : false,
		modal : false,
		cyclic : false,
		scrolling : 'auto',	// 'auto', 'yes' or 'no'

		width : 560,
		height : 340,

		autoScale : true,
		autoDimensions : true,
		centerOnScroll : false,

		ajax : {},
		swf : { wmode: 'transparent' },

		hideOnOverlayClick : true,
		hideOnContentClick : false,

		overlayShow : true,
		overlayOpacity : 0.7,
		overlayColor : '#777',

		titleShow : true,
		titlePosition : 'float', // 'float', 'outside', 'inside' or 'over'
		titleFormat : null,
		titleFromAlt : false,

		transitionIn : 'fade', // 'elastic', 'fade' or 'none'
		transitionOut : 'fade', // 'elastic', 'fade' or 'none'

		speedIn : 300,
		speedOut : 300,

		changeSpeed : 300,
		changeFade : 'fast',

		easingIn : 'swing',
		easingOut : 'swing',

		showCloseButton	 : true,
		showNavArrows : true,
		enableEscapeButton : true,
		enableKeyboardNav : true,

		onStart : function(){},
		onCancel : function(){},
		onComplete : function(){},
		onCleanup : function(){},
		onClosed : function(){},
		onError : function(){}
	};

	$(document).ready(function() {
		$.fancybox.init();
	});

})(jQuery);
/*
 * jQuery Iframe Transport Plugin 1.2.5
 * https://github.com/blueimp/jQuery-File-Upload
 *
 * Copyright 2011, Sebastian Tschan
 * https://blueimp.net
 *
 * Licensed under the MIT license:
 * http://www.opensource.org/licenses/MIT
 */


/*jslint unparam: true, nomen: true */
/*global jQuery, document */

(function ($) {
    'use strict';

    // Helper variable to create unique names for the transport iframes:
    var counter = 0;

    // The iframe transport accepts three additional options:
    // options.fileInput: a jQuery collection of file input fields
    // options.paramName: the parameter name for the file form data,
    //  overrides the name property of the file input field(s)
    // options.formData: an array of objects with name and value properties,
    //  equivalent to the return data of .serializeArray(), e.g.:
    //  [{name: 'a', value: 1}, {name: 'b', value: 2}]
    $.ajaxTransport('iframe', function (options) {
        if (options.async && (options.type === 'POST' || options.type === 'GET')) {
            var form,
                iframe;
            return {
                send: function (_, completeCallback) {
                    form = $('<form style="display:none;"></form>');
                    // javascript:false as initial iframe src
                    // prevents warning popups on HTTPS in IE6.
                    // IE versions below IE8 cannot set the name property of
                    // elements that have already been added to the DOM,
                    // so we set the name along with the iframe HTML markup:
                    iframe = $(
                        '<iframe src="javascript:false;" name="iframe-transport-' +
                            (counter += 1) + '"></iframe>'
                    ).bind('load', function () {
                        var fileInputClones;
                        iframe
                            .unbind('load')
                            .bind('load', function () {
                                var response;
                                // Wrap in a try/catch block to catch exceptions thrown
                                // when trying to access cross-domain iframe contents:
                                try {
                                    response = iframe.contents();
                                    // Google Chrome and Firefox do not throw an
                                    // exception when calling iframe.contents() on
                                    // cross-domain requests, so we unify the response:
                                    if (!response.length || !response[0].firstChild) {
                                        throw new Error();
                                    }
                                } catch (e) {
                                    response = undefined;
                                }
                                // The complete callback returns the
                                // iframe content document as response object:
                                completeCallback(
                                    200,
                                    'success',
                                    {'iframe': response}
                                );
                                // Fix for IE endless progress bar activity bug
                                // (happens on form submits to iframe targets):
                                $('<iframe src="javascript:false;"></iframe>')
                                    .appendTo(form);
                                form.remove();
                            });
                        form
                            .prop('target', iframe.prop('name'))
                            .prop('action', options.url)
                            .prop('method', options.type);
                        if (options.formData) {
                            $.each(options.formData, function (index, field) {
                                $('<input type="hidden"/>')
                                    .prop('name', field.name)
                                    .val(field.value)
                                    .appendTo(form);
                            });
                        }
                        if (options.fileInput && options.fileInput.length &&
                                options.type === 'POST') {
                            fileInputClones = options.fileInput.clone();
                            // Insert a clone for each file input field:
                            options.fileInput.after(function (index) {
                                return fileInputClones[index];
                            });
                            if (options.paramName) {
                                options.fileInput.each(function () {
                                    $(this).prop('name', options.paramName);
                                });
                            }
                            // Appending the file input fields to the hidden form
                            // removes them from their original location:
                            form
                                .append(options.fileInput)
                                .prop('enctype', 'multipart/form-data')
                                // enctype must be set as encoding for IE:
                                .prop('encoding', 'multipart/form-data');
                        }
                        form.submit();
                        // Insert the file input fields at their original location
                        // by replacing the clones with the originals:
                        if (fileInputClones && fileInputClones.length) {
                            options.fileInput.each(function (index, input) {
                                var clone = $(fileInputClones[index]);
                                $(input).prop('name', clone.prop('name'));
                                clone.replaceWith(input);
                            });
                        }
                    });
                    form.append(iframe).appendTo(document.body);
                },
                abort: function () {
                    if (iframe) {
                        // javascript:false as iframe src aborts the request
                        // and prevents warning popups on HTTPS in IE6.
                        // concat is used to avoid the "Script URL" JSLint error:
                        iframe
                            .unbind('load')
                            .prop('src', 'javascript'.concat(':false;'));
                    }
                    if (form) {
                        form.remove();
                    }
                }
            };
        }
    });

    // The iframe transport returns the iframe content document as response.
    // The following adds converters from iframe to text, json, html, and script:
    $.ajaxSetup({
        converters: {
            'iframe text': function (iframe) {
                return $(iframe[0].body).text();
            },
            'iframe json': function (iframe) {
                return $.parseJSON($(iframe[0].body).text());
            },
            'iframe html': function (iframe) {
                return $(iframe[0].body).html();
            },
            'iframe script': function (iframe) {
                return $.globalEval($(iframe[0].body).text());
            }
        }
    });

}(jQuery));
/*
 * jQuery File Upload Plugin 5.5.3
 * https://github.com/blueimp/jQuery-File-Upload
 *
 * Copyright 2010, Sebastian Tschan
 * https://blueimp.net
 *
 * Licensed under the MIT license:
 * http://www.opensource.org/licenses/MIT
 */


/*jslint nomen: true, unparam: true, regexp: true */
/*global document, XMLHttpRequestUpload, Blob, File, FormData, location, jQuery */

(function ($) {
    'use strict';

    // The fileupload widget listens for change events on file input fields defined
    // via fileInput setting and paste or drop events of the given dropZone.
    // In addition to the default jQuery Widget methods, the fileupload widget
    // exposes the "add" and "send" methods, to add or directly send files using
    // the fileupload API.
    // By default, files added via file input selection, paste, drag & drop or
    // "add" method are uploaded immediately, but it is possible to override
    // the "add" callback option to queue file uploads.
    $.widget('blueimp.fileupload', {

        options: {
            // The namespace used for event handler binding on the dropZone and
            // fileInput collections.
            // If not set, the name of the widget ("fileupload") is used.
            namespace: undefined,
            // The drop target collection, by the default the complete document.
            // Set to null or an empty collection to disable drag & drop support:
            dropZone: $(document),
            // The file input field collection, that is listened for change events.
            // If undefined, it is set to the file input fields inside
            // of the widget element on plugin initialization.
            // Set to null or an empty collection to disable the change listener.
            fileInput: undefined,
            // By default, the file input field is replaced with a clone after
            // each input field change event. This is required for iframe transport
            // queues and allows change events to be fired for the same file
            // selection, but can be disabled by setting the following option to false:
            replaceFileInput: true,
            // The parameter name for the file form data (the request argument name).
            // If undefined or empty, the name property of the file input field is
            // used, or "files[]" if the file input name property is also empty:
            paramName: undefined,
            // By default, each file of a selection is uploaded using an individual
            // request for XHR type uploads. Set to false to upload file
            // selections in one request each:
            singleFileUploads: true,
            // To limit the number of files uploaded with one XHR request,
            // set the following option to an integer greater than 0:
            limitMultiFileUploads: undefined,
            // Set the following option to true to issue all file upload requests
            // in a sequential order:
            sequentialUploads: false,
            // To limit the number of concurrent uploads,
            // set the following option to an integer greater than 0:
            limitConcurrentUploads: undefined,
            // Set the following option to true to force iframe transport uploads:
            forceIframeTransport: false,
            // Set the following option to the location of a postMessage window,
            // to enable postMessage transport uploads:
            postMessage: undefined,
            // By default, XHR file uploads are sent as multipart/form-data.
            // The iframe transport is always using multipart/form-data.
            // Set to false to enable non-multipart XHR uploads:
            multipart: true,
            // To upload large files in smaller chunks, set the following option
            // to a preferred maximum chunk size. If set to 0, null or undefined,
            // or the browser does not support the required Blob API, files will
            // be uploaded as a whole.
            maxChunkSize: undefined,
            // When a non-multipart upload or a chunked multipart upload has been
            // aborted, this option can be used to resume the upload by setting
            // it to the size of the already uploaded bytes. This option is most
            // useful when modifying the options object inside of the "add" or
            // "send" callbacks, as the options are cloned for each file upload.
            uploadedBytes: undefined,
            // By default, failed (abort or error) file uploads are removed from the
            // global progress calculation. Set the following option to false to
            // prevent recalculating the global progress data:
            recalculateProgress: true,

            // Additional form data to be sent along with the file uploads can be set
            // using this option, which accepts an array of objects with name and
            // value properties, a function returning such an array, a FormData
            // object (for XHR file uploads), or a simple object.
            // The form of the first fileInput is given as parameter to the function:
            formData: function (form) {
                return form.serializeArray();
            },

            // The add callback is invoked as soon as files are added to the fileupload
            // widget (via file input selection, drag & drop, paste or add API call).
            // If the singleFileUploads option is enabled, this callback will be
            // called once for each file in the selection for XHR file uplaods, else
            // once for each file selection.
            // The upload starts when the submit method is invoked on the data parameter.
            // The data object contains a files property holding the added files
            // and allows to override plugin options as well as define ajax settings.
            // Listeners for this callback can also be bound the following way:
            // .bind('fileuploadadd', func);
            // data.submit() returns a Promise object and allows to attach additional
            // handlers using jQuery's Deferred callbacks:
            // data.submit().done(func).fail(func).always(func);
            add: function (e, data) {
                data.submit();
            },

            // Other callbacks:
            // Callback for the submit event of each file upload:
            // submit: function (e, data) {}, // .bind('fileuploadsubmit', func);
            // Callback for the start of each file upload request:
            // send: function (e, data) {}, // .bind('fileuploadsend', func);
            // Callback for successful uploads:
            // done: function (e, data) {}, // .bind('fileuploaddone', func);
            // Callback for failed (abort or error) uploads:
            // fail: function (e, data) {}, // .bind('fileuploadfail', func);
            // Callback for completed (success, abort or error) requests:
            // always: function (e, data) {}, // .bind('fileuploadalways', func);
            // Callback for upload progress events:
            // progress: function (e, data) {}, // .bind('fileuploadprogress', func);
            // Callback for global upload progress events:
            // progressall: function (e, data) {}, // .bind('fileuploadprogressall', func);
            // Callback for uploads start, equivalent to the global ajaxStart event:
            // start: function (e) {}, // .bind('fileuploadstart', func);
            // Callback for uploads stop, equivalent to the global ajaxStop event:
            // stop: function (e) {}, // .bind('fileuploadstop', func);
            // Callback for change events of the fileInput collection:
            // change: function (e, data) {}, // .bind('fileuploadchange', func);
            // Callback for paste events to the dropZone collection:
            // paste: function (e, data) {}, // .bind('fileuploadpaste', func);
            // Callback for drop events of the dropZone collection:
            // drop: function (e, data) {}, // .bind('fileuploaddrop', func);
            // Callback for dragover events of the dropZone collection:
            // dragover: function (e) {}, // .bind('fileuploaddragover', func);

            // The plugin options are used as settings object for the ajax calls.
            // The following are jQuery ajax settings required for the file uploads:
            processData: false,
            contentType: false,
            cache: false
        },

        // A list of options that require a refresh after assigning a new value:
        _refreshOptionsList: ['namespace', 'dropZone', 'fileInput'],

        _isXHRUpload: function (options) {
            var undef = 'undefined';
            return !options.forceIframeTransport &&
                typeof XMLHttpRequestUpload !== undef && typeof File !== undef &&
                (!options.multipart || typeof FormData !== undef);
        },

        _getFormData: function (options) {
            var formData;
            if (typeof options.formData === 'function') {
                return options.formData(options.form);
            } else if ($.isArray(options.formData)) {
                return options.formData;
            } else if (options.formData) {
                formData = [];
                $.each(options.formData, function (name, value) {
                    formData.push({name: name, value: value});
                });
                return formData;
            }
            return [];
        },

        _getTotal: function (files) {
            var total = 0;
            $.each(files, function (index, file) {
                total += file.size || 1;
            });
            return total;
        },

        _onProgress: function (e, data) {
            if (e.lengthComputable) {
                var total = data.total || this._getTotal(data.files),
                    loaded = parseInt(
                        e.loaded / e.total * (data.chunkSize || total),
                        10
                    ) + (data.uploadedBytes || 0);
                this._loaded += loaded - (data.loaded || data.uploadedBytes || 0);
                data.lengthComputable = true;
                data.loaded = loaded;
                data.total = total;
                // Trigger a custom progress event with a total data property set
                // to the file size(s) of the current upload and a loaded data
                // property calculated accordingly:
                this._trigger('progress', e, data);
                // Trigger a global progress event for all current file uploads,
                // including ajax calls queued for sequential file uploads:
                this._trigger('progressall', e, {
                    lengthComputable: true,
                    loaded: this._loaded,
                    total: this._total
                });
            }
        },

        _initProgressListener: function (options) {
            var that = this,
                xhr = options.xhr ? options.xhr() : $.ajaxSettings.xhr();
            // Accesss to the native XHR object is required to add event listeners
            // for the upload progress event:
            if (xhr.upload && xhr.upload.addEventListener) {
                xhr.upload.addEventListener('progress', function (e) {
                    that._onProgress(e, options);
                }, false);
                options.xhr = function () {
                    return xhr;
                };
            }
        },

        _initXHRData: function (options) {
            var formData,
                file = options.files[0];
            if (!options.multipart || options.blob) {
                // For non-multipart uploads and chunked uploads,
                // file meta data is not part of the request body,
                // so we transmit this data as part of the HTTP headers.
                // For cross domain requests, these headers must be allowed
                // via Access-Control-Allow-Headers or removed using
                // the beforeSend callback:
                options.headers = $.extend(options.headers, {
                    'X-File-Name': file.name,
                    'X-File-Type': file.type,
                    'X-File-Size': file.size
                });
                if (!options.blob) {
                    // Non-chunked non-multipart upload:
                    options.contentType = file.type;
                    options.data = file;
                } else if (!options.multipart) {
                    // Chunked non-multipart upload:
                    options.contentType = 'application/octet-stream';
                    options.data = options.blob;
                }
            }
            if (options.multipart && typeof FormData !== 'undefined') {
                if (options.postMessage) {
                    // window.postMessage does not allow sending FormData
                    // objects, so we just add the File/Blob objects to
                    // the formData array and let the postMessage window
                    // create the FormData object out of this array:
                    formData = this._getFormData(options);
                    if (options.blob) {
                        formData.push({
                            name: options.paramName,
                            value: options.blob
                        });
                    } else {
                        $.each(options.files, function (index, file) {
                            formData.push({
                                name: options.paramName,
                                value: file
                            });
                        });
                    }
                } else {
                    if (options.formData instanceof FormData) {
                        formData = options.formData;
                    } else {
                        formData = new FormData();
                        $.each(this._getFormData(options), function (index, field) {
                            formData.append(field.name, field.value);
                        });
                    }
                    if (options.blob) {
                        formData.append(options.paramName, options.blob);
                    } else {
                        $.each(options.files, function (index, file) {
                            // File objects are also Blob instances.
                            // This check allows the tests to run with
                            // dummy objects:
                            if (file instanceof Blob) {
                                formData.append(options.paramName, file);
                            }
                        });
                    }
                }
                options.data = formData;
            }
            // Blob reference is not needed anymore, free memory:
            options.blob = null;
        },

        _initIframeSettings: function (options) {
            // Setting the dataType to iframe enables the iframe transport:
            options.dataType = 'iframe ' + (options.dataType || '');
            // The iframe transport accepts a serialized array as form data:
            options.formData = this._getFormData(options);
        },

        _initDataSettings: function (options) {
            if (this._isXHRUpload(options)) {
                if (!this._chunkedUpload(options, true)) {
                    if (!options.data) {
                        this._initXHRData(options);
                    }
                    this._initProgressListener(options);
                }
                if (options.postMessage) {
                    // Setting the dataType to postmessage enables the
                    // postMessage transport:
                    options.dataType = 'postmessage ' + (options.dataType || '');
                }
            } else {
                this._initIframeSettings(options, 'iframe');
            }
        },

        _initFormSettings: function (options) {
            // Retrieve missing options from the input field and the
            // associated form, if available:
            if (!options.form || !options.form.length) {
                options.form = $(options.fileInput.prop('form'));
            }
            if (!options.paramName) {
                options.paramName = options.fileInput.prop('name') ||
                    'files[]';
            }
            if (!options.url) {
                options.url = options.form.prop('action') || location.href;
            }
            // The HTTP request method must be "POST" or "PUT":
            options.type = (options.type || options.form.prop('method') || '')
                .toUpperCase();
            if (options.type !== 'POST' && options.type !== 'PUT') {
                options.type = 'POST';
            }
        },

        _getAJAXSettings: function (data) {
            var options = $.extend({}, this.options, data);
            this._initFormSettings(options);
            this._initDataSettings(options);
            return options;
        },

        // Maps jqXHR callbacks to the equivalent
        // methods of the given Promise object:
        _enhancePromise: function (promise) {
            promise.success = promise.done;
            promise.error = promise.fail;
            promise.complete = promise.always;
            return promise;
        },

        // Creates and returns a Promise object enhanced with
        // the jqXHR methods abort, success, error and complete:
        _getXHRPromise: function (resolveOrReject, context, args) {
            var dfd = $.Deferred(),
                promise = dfd.promise();
            context = context || this.options.context || promise;
            if (resolveOrReject === true) {
                dfd.resolveWith(context, args);
            } else if (resolveOrReject === false) {
                dfd.rejectWith(context, args);
            }
            promise.abort = dfd.promise;
            return this._enhancePromise(promise);
        },

        // Uploads a file in multiple, sequential requests
        // by splitting the file up in multiple blob chunks.
        // If the second parameter is true, only tests if the file
        // should be uploaded in chunks, but does not invoke any
        // upload requests:
        _chunkedUpload: function (options, testOnly) {
            var that = this,
                file = options.files[0],
                fs = file.size,
                ub = options.uploadedBytes = options.uploadedBytes || 0,
                mcs = options.maxChunkSize || fs,
                // Use the Blob methods with the slice implementation
                // according to the W3C Blob API specification:
                slice = file.webkitSlice || file.mozSlice || file.slice,
                upload,
                n,
                jqXHR,
                pipe;
            if (!(this._isXHRUpload(options) && slice && (ub || mcs < fs)) ||
                    options.data) {
                return false;
            }
            if (testOnly) {
                return true;
            }
            if (ub >= fs) {
                file.error = 'uploadedBytes';
                return this._getXHRPromise(
                    false,
                    options.context,
                    [null, 'error', file.error]
                );
            }
            // n is the number of blobs to upload,
            // calculated via filesize, uploaded bytes and max chunk size:
            n = Math.ceil((fs - ub) / mcs);
            // The chunk upload method accepting the chunk number as parameter:
            upload = function (i) {
                if (!i) {
                    return that._getXHRPromise(true, options.context);
                }
                // Upload the blobs in sequential order:
                return upload(i -= 1).pipe(function () {
                    // Clone the options object for each chunk upload:
                    var o = $.extend({}, options);
                    o.blob = slice.call(
                        file,
                        ub + i * mcs,
                        ub + (i + 1) * mcs
                    );
                    // Store the current chunk size, as the blob itself
                    // will be dereferenced after data processing:
                    o.chunkSize = o.blob.size;
                    // Process the upload data (the blob and potential form data):
                    that._initXHRData(o);
                    // Add progress listeners for this chunk upload:
                    that._initProgressListener(o);
                    jqXHR = ($.ajax(o) || that._getXHRPromise(false, o.context))
                        .done(function () {
                            // Create a progress event if upload is done and
                            // no progress event has been invoked for this chunk:
                            if (!o.loaded) {
                                that._onProgress($.Event('progress', {
                                    lengthComputable: true,
                                    loaded: o.chunkSize,
                                    total: o.chunkSize
                                }), o);
                            }
                            options.uploadedBytes = o.uploadedBytes +=
                                o.chunkSize;
                        });
                    return jqXHR;
                });
            };
            // Return the piped Promise object, enhanced with an abort method,
            // which is delegated to the jqXHR object of the current upload,
            // and jqXHR callbacks mapped to the equivalent Promise methods:
            pipe = upload(n);
            pipe.abort = function () {
                return jqXHR.abort();
            };
            return this._enhancePromise(pipe);
        },

        _beforeSend: function (e, data) {
            if (this._active === 0) {
                // the start callback is triggered when an upload starts
                // and no other uploads are currently running,
                // equivalent to the global ajaxStart event:
                this._trigger('start');
            }
            this._active += 1;
            // Initialize the global progress values:
            this._loaded += data.uploadedBytes || 0;
            this._total += this._getTotal(data.files);
        },

        _onDone: function (result, textStatus, jqXHR, options) {
            if (!this._isXHRUpload(options)) {
                // Create a progress event for each iframe load:
                this._onProgress($.Event('progress', {
                    lengthComputable: true,
                    loaded: 1,
                    total: 1
                }), options);
            }
            options.result = result;
            options.textStatus = textStatus;
            options.jqXHR = jqXHR;
            this._trigger('done', null, options);
        },

        _onFail: function (jqXHR, textStatus, errorThrown, options) {
            options.jqXHR = jqXHR;
            options.textStatus = textStatus;
            options.errorThrown = errorThrown;
            this._trigger('fail', null, options);
            if (options.recalculateProgress) {
                // Remove the failed (error or abort) file upload from
                // the global progress calculation:
                this._loaded -= options.loaded || options.uploadedBytes || 0;
                this._total -= options.total || this._getTotal(options.files);
            }
        },

        _onAlways: function (jqXHRorResult, textStatus, jqXHRorError, options) {
            this._active -= 1;
            options.textStatus = textStatus;
            if (jqXHRorError && jqXHRorError.always) {
                options.jqXHR = jqXHRorError;
                options.result = jqXHRorResult;
            } else {
                options.jqXHR = jqXHRorResult;
                options.errorThrown = jqXHRorError;
            }
            this._trigger('always', null, options);
            if (this._active === 0) {
                // The stop callback is triggered when all uploads have
                // been completed, equivalent to the global ajaxStop event:
                this._trigger('stop');
                // Reset the global progress values:
                this._loaded = this._total = 0;
            }
        },

        _onSend: function (e, data) {
            var that = this,
                jqXHR,
                slot,
                pipe,
                options = that._getAJAXSettings(data),
                send = function (resolve, args) {
                    that._sending += 1;
                    jqXHR = jqXHR || (
                        (resolve !== false &&
                        that._trigger('send', e, options) !== false &&
                        (that._chunkedUpload(options) || $.ajax(options))) ||
                        that._getXHRPromise(false, options.context, args)
                    ).done(function (result, textStatus, jqXHR) {
                        that._onDone(result, textStatus, jqXHR, options);
                    }).fail(function (jqXHR, textStatus, errorThrown) {
                        that._onFail(jqXHR, textStatus, errorThrown, options);
                    }).always(function (jqXHRorResult, textStatus, jqXHRorError) {
                        that._sending -= 1;
                        that._onAlways(
                            jqXHRorResult,
                            textStatus,
                            jqXHRorError,
                            options
                        );
                        if (options.limitConcurrentUploads &&
                                options.limitConcurrentUploads > that._sending) {
                            // Start the next queued upload,
                            // that has not been aborted:
                            var nextSlot = that._slots.shift();
                            while (nextSlot) {
                                if (!nextSlot.isRejected()) {
                                    nextSlot.resolve();
                                    break;
                                }
                                nextSlot = that._slots.shift();
                            }
                        }
                    });
                    return jqXHR;
                };
            this._beforeSend(e, options);
            if (this.options.sequentialUploads ||
                    (this.options.limitConcurrentUploads &&
                    this.options.limitConcurrentUploads <= this._sending)) {
                if (this.options.limitConcurrentUploads > 1) {
                    slot = $.Deferred();
                    this._slots.push(slot);
                    pipe = slot.pipe(send);
                } else {
                    pipe = (this._sequence = this._sequence.pipe(send, send));
                }
                // Return the piped Promise object, enhanced with an abort method,
                // which is delegated to the jqXHR object of the current upload,
                // and jqXHR callbacks mapped to the equivalent Promise methods:
                pipe.abort = function () {
                    var args = [undefined, 'abort', 'abort'];
                    if (!jqXHR) {
                        if (slot) {
                            slot.rejectWith(args);
                        }
                        return send(false, args);
                    }
                    return jqXHR.abort();
                };
                return this._enhancePromise(pipe);
            }
            return send();
        },

        _onAdd: function (e, data) {
            var that = this,
                result = true,
                options = $.extend({}, this.options, data),
                limit = options.limitMultiFileUploads,
                fileSet,
                i;
            if (!(options.singleFileUploads || limit) ||
                    !this._isXHRUpload(options)) {
                fileSet = [data.files];
            } else if (!options.singleFileUploads && limit) {
                fileSet = [];
                for (i = 0; i < data.files.length; i += limit) {
                    fileSet.push(data.files.slice(i, i + limit));
                }
            }
            data.originalFiles = data.files;
            $.each(fileSet || data.files, function (index, element) {
                var files = fileSet ? element : [element],
                    newData = $.extend({}, data, {files: files});
                newData.submit = function () {
                    newData.jqXHR = this.jqXHR =
                        (that._trigger('submit', e, this) !== false) &&
                        that._onSend(e, this);
                    return this.jqXHR;
                };
                return (result = that._trigger('add', e, newData));
            });
            return result;
        },

        // File Normalization for Gecko 1.9.1 (Firefox 3.5) support:
        _normalizeFile: function (index, file) {
            if (file.name === undefined && file.size === undefined) {
                file.name = file.fileName;
                file.size = file.fileSize;
            }
        },

        _replaceFileInput: function (input) {
            var inputClone = input.clone(true);
            $('<form></form>').append(inputClone)[0].reset();
            // Detaching allows to insert the fileInput on another form
            // without loosing the file input value:
            input.after(inputClone).detach();
            // Avoid memory leaks with the detached file input:
            $.cleanData(input.unbind('remove'));
            // Replace the original file input element in the fileInput
            // collection with the clone, which has been copied including
            // event handlers:
            this.options.fileInput = this.options.fileInput.map(function (i, el) {
                if (el === input[0]) {
                    return inputClone[0];
                }
                return el;
            });
            // If the widget has been initialized on the file input itself,
            // override this.element with the file input clone:
            if (input[0] === this.element[0]) {
                this.element = inputClone;
            }
        },

        _onChange: function (e) {
            var that = e.data.fileupload,
                data = {
                    files: $.each($.makeArray(e.target.files), that._normalizeFile),
                    fileInput: $(e.target),
                    form: $(e.target.form)
                };
            if (!data.files.length) {
                // If the files property is not available, the browser does not
                // support the File API and we add a pseudo File object with
                // the input value as name with path information removed:
                data.files = [{name: e.target.value.replace(/^.*\\/, '')}];
            }
            if (that.options.replaceFileInput) {
                that._replaceFileInput(data.fileInput);
            }
            if (that._trigger('change', e, data) === false ||
                    that._onAdd(e, data) === false) {
                return false;
            }
        },

        _onPaste: function (e) {
            var that = e.data.fileupload,
                cbd = e.originalEvent.clipboardData,
                items = (cbd && cbd.items) || [],
                data = {files: []};
            $.each(items, function (index, item) {
                var file = item.getAsFile && item.getAsFile();
                if (file) {
                    data.files.push(file);
                }
            });
            if (that._trigger('paste', e, data) === false ||
                    that._onAdd(e, data) === false) {
                return false;
            }
        },

        _onDrop: function (e) {
            var that = e.data.fileupload,
                dataTransfer = e.dataTransfer = e.originalEvent.dataTransfer,
                data = {
                    files: $.each(
                        $.makeArray(dataTransfer && dataTransfer.files),
                        that._normalizeFile
                    )
                };
            if (that._trigger('drop', e, data) === false ||
                    that._onAdd(e, data) === false) {
                return false;
            }
            e.preventDefault();
        },

        _onDragOver: function (e) {
            var that = e.data.fileupload,
                dataTransfer = e.dataTransfer = e.originalEvent.dataTransfer;
            if (that._trigger('dragover', e) === false) {
                return false;
            }
            if (dataTransfer) {
                dataTransfer.dropEffect = dataTransfer.effectAllowed = 'copy';
            }
            e.preventDefault();
        },

        _initEventHandlers: function () {
            var ns = this.options.namespace;
            this.options.dropZone
                .bind('dragover.' + ns, {fileupload: this}, this._onDragOver)
                .bind('drop.' + ns, {fileupload: this}, this._onDrop)
                .bind('paste.' + ns, {fileupload: this}, this._onPaste);
            this.options.fileInput
                .bind('change.' + ns, {fileupload: this}, this._onChange);
        },

        _destroyEventHandlers: function () {
            var ns = this.options.namespace;
            this.options.dropZone
                .unbind('dragover.' + ns, this._onDragOver)
                .unbind('drop.' + ns, this._onDrop)
                .unbind('paste.' + ns, this._onPaste);
            this.options.fileInput
                .unbind('change.' + ns, this._onChange);
        },

        _beforeSetOption: function (key, value) {
            this._destroyEventHandlers();
        },

        _afterSetOption: function (key, value) {
            var options = this.options;
            if (!options.fileInput) {
                options.fileInput = $();
            }
            if (!options.dropZone) {
                options.dropZone = $();
            }
            this._initEventHandlers();
        },

        _setOption: function (key, value) {
            var refresh = $.inArray(key, this._refreshOptionsList) !== -1;
            if (refresh) {
                this._beforeSetOption(key, value);
            }
            $.Widget.prototype._setOption.call(this, key, value);
            if (refresh) {
                this._afterSetOption(key, value);
            }
        },

        _create: function () {
            var options = this.options;
            options.namespace = options.namespace || this.widgetName;
            if (options.fileInput === undefined) {
                options.fileInput = this.element.is('input:file') ?
                        this.element : this.element.find('input:file');
            } else if (!options.fileInput) {
                options.fileInput = $();
            }
            if (!options.dropZone) {
                options.dropZone = $();
            }
            this._slots = [];
            this._sequence = this._getXHRPromise(true);
            this._sending = this._active = this._loaded = this._total = 0;
            this._initEventHandlers();
        },

        destroy: function () {
            this._destroyEventHandlers();
            $.Widget.prototype.destroy.call(this);
        },

        enable: function () {
            $.Widget.prototype.enable.call(this);
            this._initEventHandlers();
        },

        disable: function () {
            this._destroyEventHandlers();
            $.Widget.prototype.disable.call(this);
        },

        // This method is exposed to the widget API and allows adding files
        // using the fileupload API. The data parameter accepts an object which
        // must have a files property and can contain additional options:
        // .fileupload('add', {files: filesList});
        add: function (data) {
            if (!data || this.options.disabled) {
                return;
            }
            data.files = $.each($.makeArray(data.files), this._normalizeFile);
            this._onAdd(null, data);
        },

        // This method is exposed to the widget API and allows sending files
        // using the fileupload API. The data parameter accepts an object which
        // must have a files property and can contain additional options:
        // .fileupload('send', {files: filesList});
        // The method returns a Promise object for the file upload call.
        send: function (data) {
            if (data && !this.options.disabled) {
                data.files = $.each($.makeArray(data.files), this._normalizeFile);
                if (data.files.length) {
                    return this._onSend(null, data);
                }
            }
            return this._getXHRPromise(false, data && data.context);
        }

    });

}(jQuery));
/*!
 * jQuery Tools v1.2.5 - The missing UI library for the Web
 * 
 * tooltip/tooltip.js
 * tooltip/tooltip.dynamic.js
 * tooltip/tooltip.slide.js
 * 
 * NO COPYRIGHTS OR LICENSES. DO WHAT YOU LIKE.
 * 
 * http://flowplayer.org/tools/
 * 
 */

(function(a){a.tools=a.tools||{version:"v1.2.5"},a.tools.tooltip={conf:{effect:"toggle",fadeOutSpeed:"fast",predelay:0,delay:30,opacity:1,tip:0,position:["top","center"],offset:[0,0],relative:!1,cancelDefault:!0,events:{def:"mouseenter,mouseleave",input:"focus,blur",widget:"focus mouseenter,blur mouseleave",tooltip:"mouseenter,mouseleave"},layout:"<div/>",tipClass:"tooltip"},addEffect:function(a,c,d){b[a]=[c,d]}};var b={toggle:[function(a){var b=this.getConf(),c=this.getTip(),d=b.opacity;d<1&&c.css({opacity:d}),c.show(),a.call()},function(a){this.getTip().hide(),a.call()}],fade:[function(a){var b=this.getConf();this.getTip().fadeTo(b.fadeInSpeed,b.opacity,a)},function(a){this.getTip().fadeOut(this.getConf().fadeOutSpeed,a)}]};function c(b,c,d){var e=d.relative?b.position().top:b.offset().top,f=d.relative?b.position().left:b.offset().left,g=d.position[0];e-=c.outerHeight()-d.offset[0],f+=b.outerWidth()+d.offset[1],/iPad/i.test(navigator.userAgent)&&(e-=a(window).scrollTop());var h=c.outerHeight()+b.outerHeight();g=="center"&&(e+=h/2),g=="bottom"&&(e+=h),g=d.position[1];var i=c.outerWidth()+b.outerWidth();g=="center"&&(f-=i/2),g=="left"&&(f-=i);return{top:e,left:f}}function d(d,e){var f=this,g=d.add(f),h,i=0,j=0,k=d.attr("title"),l=d.attr("data-tooltip"),m=b[e.effect],n,o=d.is(":input"),p=o&&d.is(":checkbox, :radio, select, :button, :submit"),q=d.attr("type"),r=e.events[q]||e.events[o?p?"widget":"input":"def"];if(!m)throw"Nonexistent effect \""+e.effect+"\"";r=r.split(/,\s*/);if(r.length!=2)throw"Tooltip: bad events configuration for "+q;d.bind(r[0],function(a){clearTimeout(i),e.predelay?j=setTimeout(function(){f.show(a)},e.predelay):f.show(a)}).bind(r[1],function(a){clearTimeout(j),e.delay?i=setTimeout(function(){f.hide(a)},e.delay):f.hide(a)}),k&&e.cancelDefault&&(d.removeAttr("title"),d.data("title",k)),a.extend(f,{show:function(b){if(!h){l?h=a(l):e.tip?h=a(e.tip).eq(0):k?h=a(e.layout).addClass(e.tipClass).appendTo(document.body).hide().append(k):(h=d.next(),h.length||(h=d.parent().next()));if(!h.length)throw"Cannot find tooltip for "+d}if(f.isShown())return f;h.stop(!0,!0);var o=c(d,h,e);e.tip&&h.html(d.data("title")),b=b||a.Event(),b.type="onBeforeShow",g.trigger(b,[o]);if(b.isDefaultPrevented())return f;o=c(d,h,e),h.css({position:"absolute",top:o.top,left:o.left}),n=!0,m[0].call(f,function(){b.type="onShow",n="full",g.trigger(b)});var p=e.events.tooltip.split(/,\s*/);h.data("__set")||(h.bind(p[0],function(){clearTimeout(i),clearTimeout(j)}),p[1]&&!d.is("input:not(:checkbox, :radio), textarea")&&h.bind(p[1],function(a){a.relatedTarget!=d[0]&&d.trigger(r[1].split(" ")[0])}),h.data("__set",!0));return f},hide:function(c){if(!h||!f.isShown())return f;c=c||a.Event(),c.type="onBeforeHide",g.trigger(c);if(!c.isDefaultPrevented()){n=!1,b[e.effect][1].call(f,function(){c.type="onHide",g.trigger(c)});return f}},isShown:function(a){return a?n=="full":n},getConf:function(){return e},getTip:function(){return h},getTrigger:function(){return d}}),a.each("onHide,onBeforeShow,onShow,onBeforeHide".split(","),function(b,c){a.isFunction(e[c])&&a(f).bind(c,e[c]),f[c]=function(b){b&&a(f).bind(c,b);return f}})}a.fn.tooltip=function(b){var c=this.data("tooltip");if(c)return c;b=a.extend(!0,{},a.tools.tooltip.conf,b),typeof b.position=="string"&&(b.position=b.position.split(/,?\s/)),this.each(function(){c=new d(a(this),b),a(this).data("tooltip",c)});return b.api?c:this}})(jQuery);
(function(a){var b=a.tools.tooltip;b.dynamic={conf:{classNames:"top right bottom left"}};function c(b){var c=a(window),d=c.width()+c.scrollLeft(),e=c.height()+c.scrollTop();return[b.offset().top<=c.scrollTop(),d<=b.offset().left+b.width(),e<=b.offset().top+b.height(),c.scrollLeft()>=b.offset().left]}function d(a){var b=a.length;while(b--)if(a[b])return!1;return!0}a.fn.dynamic=function(e){typeof e=="number"&&(e={speed:e}),e=a.extend({},b.dynamic.conf,e);var f=e.classNames.split(/\s/),g;this.each(function(){var b=a(this).tooltip().onBeforeShow(function(b,h){var i=this.getTip(),j=this.getConf();g||(g=[j.position[0],j.position[1],j.offset[0],j.offset[1],a.extend({},j)]),a.extend(j,g[4]),j.position=[g[0],g[1]],j.offset=[g[2],g[3]],i.css({visibility:"hidden",position:"absolute",top:h.top,left:h.left}).show();var k=c(i);if(!d(k)){k[2]&&(a.extend(j,e.top),j.position[0]="top",i.addClass(f[0])),k[3]&&(a.extend(j,e.right),j.position[1]="right",i.addClass(f[1])),k[0]&&(a.extend(j,e.bottom),j.position[0]="bottom",i.addClass(f[2])),k[1]&&(a.extend(j,e.left),j.position[1]="left",i.addClass(f[3]));if(k[0]||k[2])j.offset[0]*=-1;if(k[1]||k[3])j.offset[1]*=-1}i.css({visibility:"visible"}).hide()});b.onBeforeShow(function(){var a=this.getConf(),b=this.getTip();setTimeout(function(){a.position=[g[0],g[1]],a.offset=[g[2],g[3]]},0)}),b.onHide(function(){var a=this.getTip();a.removeClass(e.classNames)}),ret=b});return e.api?ret:this}})(jQuery);
(function(a){var b=a.tools.tooltip;a.extend(b.conf,{direction:"up",bounce:!1,slideOffset:10,slideInSpeed:200,slideOutSpeed:200,slideFade:!a.browser.msie});var c={up:["-","top"],down:["+","top"],left:["-","left"],right:["+","left"]};b.addEffect("slide",function(a){var b=this.getConf(),d=this.getTip(),e=b.slideFade?{opacity:b.opacity}:{},f=c[b.direction]||c.up;e[f[1]]=f[0]+"="+b.slideOffset,b.slideFade&&d.css({opacity:0}),d.show().animate(e,b.slideInSpeed,a)},function(b){var d=this.getConf(),e=d.slideOffset,f=d.slideFade?{opacity:0}:{},g=c[d.direction]||c.up,h=""+g[0];d.bounce&&(h=h=="+"?"-":"+"),f[g[1]]=h+"="+e,this.getTip().animate(f,d.slideOutSpeed,function(){a(this).hide(),b.call()})})})(jQuery);
/**
 * jQuery Cookie plugin
 *
 * Copyright (c) 2010 Klaus Hartl (stilbuero.de)
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 */

jQuery.cookie = function (key, value, options) {

    // key and at least value given, set cookie...
    if (arguments.length > 1 && String(value) !== "[object Object]") {
        options = jQuery.extend({}, options);

        if (value === null || value === undefined) {
            var oExpDate = new Date();  
            oExpDate.setDate(oExpDate.getDate() - 1);
            options.expires = oExpDate;
        }

        if (typeof options.expires === 'number') {
            var days = options.expires, t = options.expires = new Date();
            t.setDate(t.getDate() + days);
        }

        value = String(value);

        return (document.cookie = [
            encodeURIComponent(key), '=',
            options.raw ? value : encodeURIComponent(value),
            options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
            options.path ? '; path=' + options.path : '',
            options.domain ? '; domain=' + options.domain : '',
            options.secure ? '; secure' : ''
        ].join(''));
    }

    // key and possibly options given, get cookie...
    options = value || {};
    var result, decode = options.raw ? function (s) { return s; } : decodeURIComponent;
    return (result = new RegExp('(?:^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? decode(result[1]) : null;
};
(function() {
  /*
  Chosen, a Select Box Enhancer for jQuery and Protoype
  by Patrick Filler for Harvest, http://getharvest.com
  
  Available for use under the MIT License, http://en.wikipedia.org/wiki/MIT_License
  
  Copyright (c) 2011 by Harvest
  */  var $, Chosen, SelectParser, get_side_border_padding, root;
  var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
  root = typeof exports !== "undefined" && exports !== null ? exports : this;
  $ = jQuery;
  $.fn.extend({
    chosen: function(data, options) {
      return $(this).each(function(input_field) {
        if (!($(this)).hasClass("chzn-done")) {
          return new Chosen(this, data, options);
        }
      });
    }
  });
  Chosen = (function() {
    function Chosen(elmn) {
      this.set_default_values();
      this.form_field = elmn;
      this.form_field_jq = $(this.form_field);
      this.is_multiple = this.form_field.multiple;
      this.default_text_default = this.form_field.multiple ? "Select Some Options" : "Select an Option";
      this.set_up_html();
      this.register_observers();
      this.form_field_jq.addClass("chzn-done");
    }
    Chosen.prototype.set_default_values = function() {
      this.click_test_action = __bind(function(evt) {
        return this.test_active_click(evt);
      }, this);
      this.active_field = false;
      this.mouse_on_container = false;
      this.results_showing = false;
      this.result_highlighted = null;
      this.result_single_selected = null;
      return this.choices = 0;
    };
    Chosen.prototype.set_up_html = function() {
      var container_div, dd_top, dd_width, sf_width;
      this.container_id = this.form_field.id.length ? this.form_field.id.replace('.', '_') : this.generate_field_id();
      this.container_id += "_chzn";
      this.f_width = this.form_field_jq.width();
      this.default_text = this.form_field_jq.attr('title') ? this.form_field_jq.attr('title') : this.default_text_default;
      container_div = $("<div />", {
        id: this.container_id,
        "class": 'chzn-container',
        style: 'width: ' + this.f_width + 'px;'
      });
      if (this.is_multiple) {
        container_div.html('<ul class="chzn-choices"><li class="search-field"><input type="text" value="' + this.default_text + '" class="default" style="width:25px;" /></li></ul><div class="chzn-drop" style="left:-9000px;"><ul class="chzn-results"></ul></div>');
      } else {
        container_div.html('<a href="javascript:void(0)" class="chzn-single"><span>' + this.default_text + '</span><div><b></b></div></a><div class="chzn-drop" style="left:-9000px;"><div class="chzn-search"><input type="text" /></div><ul class="chzn-results"></ul></div>');
      }
      this.form_field_jq.hide().after(container_div);
      this.container = $('#' + this.container_id);
      this.container.addClass("chzn-container-" + (this.is_multiple ? "multi" : "single"));
      this.dropdown = this.container.find('div.chzn-drop').first();
      dd_top = this.container.height();
      dd_width = this.f_width - get_side_border_padding(this.dropdown);
      this.dropdown.css({
        "width": dd_width + "px",
        "top": dd_top + "px"
      });
      this.search_field = this.container.find('input').first();
      this.search_results = this.container.find('ul.chzn-results').first();
      this.search_field_scale();
      this.search_no_results = this.container.find('li.no-results').first();
      if (this.is_multiple) {
        this.search_choices = this.container.find('ul.chzn-choices').first();
        this.search_container = this.container.find('li.search-field').first();
      } else {
        this.search_container = this.container.find('div.chzn-search').first();
        this.selected_item = this.container.find('.chzn-single').first();
        sf_width = dd_width - get_side_border_padding(this.search_container) - get_side_border_padding(this.search_field);
        this.search_field.css({
          "width": sf_width + "px"
        });
      }
      this.results_build();
      return this.set_tab_index();
    };
    Chosen.prototype.register_observers = function() {
      this.container.click(__bind(function(evt) {
        return this.container_click(evt);
      }, this));
      this.container.mouseenter(__bind(function(evt) {
        return this.mouse_enter(evt);
      }, this));
      this.container.mouseleave(__bind(function(evt) {
        return this.mouse_leave(evt);
      }, this));
      this.search_results.click(__bind(function(evt) {
        return this.search_results_click(evt);
      }, this));
      this.search_results.mouseover(__bind(function(evt) {
        return this.search_results_mouseover(evt);
      }, this));
      this.search_results.mouseout(__bind(function(evt) {
        return this.search_results_mouseout(evt);
      }, this));
      this.form_field_jq.bind("liszt:updated", __bind(function(evt) {
        return this.results_update_field(evt);
      }, this));
      this.search_field.blur(__bind(function(evt) {
        return this.input_blur(evt);
      }, this));
      this.search_field.keyup(__bind(function(evt) {
        return this.keyup_checker(evt);
      }, this));
      this.search_field.keydown(__bind(function(evt) {
        return this.keydown_checker(evt);
      }, this));
      if (this.is_multiple) {
        this.search_choices.click(__bind(function(evt) {
          return this.choices_click(evt);
        }, this));
        return this.search_field.focus(__bind(function(evt) {
          return this.input_focus(evt);
        }, this));
      } else {
        return this.selected_item.focus(__bind(function(evt) {
          return this.activate_field(evt);
        }, this));
      }
    };
    Chosen.prototype.container_click = function(evt) {
      if (evt && evt.type === "click") {
        evt.stopPropagation();
      }
      if (!this.pending_destroy_click) {
        if (!this.active_field) {
          if (this.is_multiple) {
            this.search_field.val("");
          }
          $(document).click(this.click_test_action);
          this.results_show();
        } else if (!this.is_multiple && evt && ($(evt.target) === this.selected_item || $(evt.target).parents("a.chzn-single").length)) {
          evt.preventDefault();
          this.results_toggle();
        }
        return this.activate_field();
      } else {
        return this.pending_destroy_click = false;
      }
    };
    Chosen.prototype.mouse_enter = function() {
      return this.mouse_on_container = true;
    };
    Chosen.prototype.mouse_leave = function() {
      return this.mouse_on_container = false;
    };
    Chosen.prototype.input_focus = function(evt) {
      if (!this.active_field) {
        return setTimeout((__bind(function() {
          return this.container_click();
        }, this)), 50);
      }
    };
    Chosen.prototype.input_blur = function(evt) {
      if (!this.mouse_on_container) {
        this.active_field = false;
        return setTimeout((__bind(function() {
          return this.blur_test();
        }, this)), 100);
      }
    };
    Chosen.prototype.blur_test = function(evt) {
      if (!this.active_field && this.container.hasClass("chzn-container-active")) {
        return this.close_field();
      }
    };
    Chosen.prototype.close_field = function() {
      $(document).unbind("click", this.click_test_action);
      if (!this.is_multiple) {
        this.selected_item.attr("tabindex", this.search_field.attr("tabindex"));
        this.search_field.attr("tabindex", -1);
      }
      this.active_field = false;
      this.results_hide();
      this.container.removeClass("chzn-container-active");
      this.winnow_results_clear();
      this.clear_backstroke();
      this.show_search_field_default();
      return this.search_field_scale();
    };
    Chosen.prototype.activate_field = function() {
      if (!this.is_multiple && !this.active_field) {
        this.search_field.attr("tabindex", this.selected_item.attr("tabindex"));
        this.selected_item.attr("tabindex", -1);
      }
      this.container.addClass("chzn-container-active");
      this.active_field = true;
      this.search_field.val(this.search_field.val());
      return this.search_field.focus();
    };
    Chosen.prototype.test_active_click = function(evt) {
      if ($(evt.target).parents('#' + this.container_id).length) {
        return this.active_field = true;
      } else {
        return this.close_field();
      }
    };
    Chosen.prototype.results_build = function() {
      var content, data, startTime, _i, _len, _ref;
      startTime = new Date();
      this.parsing = true;
      this.results_data = SelectParser.select_to_array(this.form_field);
      if (this.is_multiple && this.choices > 0) {
        this.search_choices.find("li.search-choice").remove();
        this.choices = 0;
      } else if (!this.is_multiple) {
        this.selected_item.find("span").text(this.default_text);
      }
      content = '';
      _ref = this.results_data;
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        data = _ref[_i];
        if (data.group) {
          content += this.result_add_group(data);
        } else if (!data.empty) {
          content += this.result_add_option(data);
          if (data.selected && this.is_multiple) {
            this.choice_build(data);
          } else if (data.selected && !this.is_multiple) {
            this.selected_item.find("span").text(data.text);
          }
        }
      }
      this.show_search_field_default();
      this.search_field_scale();
      this.search_results.html(content);
      return this.parsing = false;
    };
    Chosen.prototype.result_add_group = function(group) {
      if (!group.disabled) {
        group.dom_id = this.container_id + "_g_" + group.array_index;
        return '<li id="' + group.dom_id + '" class="group-result">' + $("<div />").text(group.label).html() + '</li>';
      } else {
        return "";
      }
    };
    Chosen.prototype.result_add_option = function(option) {
      var classes;
      if (!option.disabled) {
        option.dom_id = this.container_id + "_o_" + option.array_index;
        classes = option.selected && this.is_multiple ? [] : ["active-result"];
        if (option.selected) {
          classes.push("result-selected");
        }
        if (option.group_array_index != null) {
          classes.push("group-option");
        }
        return '<li id="' + option.dom_id + '" class="' + classes.join(' ') + '">' + $("<div />").text(option.text).html() + '</li>';
      } else {
        return "";
      }
    };
    Chosen.prototype.results_update_field = function() {
      this.result_clear_highlight();
      this.result_single_selected = null;
      return this.results_build();
    };
    Chosen.prototype.result_do_highlight = function(el) {
      var high_bottom, high_top, maxHeight, visible_bottom, visible_top;
      if (el.length) {
        this.result_clear_highlight();
        this.result_highlight = el;
        this.result_highlight.addClass("highlighted");
        maxHeight = parseInt(this.search_results.css("maxHeight"), 10);
        visible_top = this.search_results.scrollTop();
        visible_bottom = maxHeight + visible_top;
        high_top = this.result_highlight.position().top + this.search_results.scrollTop();
        high_bottom = high_top + this.result_highlight.outerHeight();
        if (high_bottom >= visible_bottom) {
          return this.search_results.scrollTop((high_bottom - maxHeight) > 0 ? high_bottom - maxHeight : 0);
        } else if (high_top < visible_top) {
          return this.search_results.scrollTop(high_top);
        }
      }
    };
    Chosen.prototype.result_clear_highlight = function() {
      if (this.result_highlight) {
        this.result_highlight.removeClass("highlighted");
      }
      return this.result_highlight = null;
    };
    Chosen.prototype.results_toggle = function() {
      if (this.results_showing) {
        return this.results_hide();
      } else {
        return this.results_show();
      }
    };
    Chosen.prototype.results_show = function() {
      var dd_top;
      if (!this.is_multiple) {
        this.selected_item.addClass("chzn-single-with-drop");
        if (this.result_single_selected) {
          this.result_do_highlight(this.result_single_selected);
        }
      }
      dd_top = this.is_multiple ? this.container.height() : this.container.height() - 1;
      this.dropdown.css({
        "top": dd_top + "px",
        "left": 0
      });
      this.results_showing = true;
      this.search_field.focus();
      this.search_field.val(this.search_field.val());
      return this.winnow_results();
    };
    Chosen.prototype.results_hide = function() {
      if (!this.is_multiple) {
        this.selected_item.removeClass("chzn-single-with-drop");
      }
      this.result_clear_highlight();
      this.dropdown.css({
        "left": "-9000px"
      });
      return this.results_showing = false;
    };
    Chosen.prototype.set_tab_index = function(el) {
      var ti;
      if (this.form_field_jq.attr("tabindex")) {
        ti = this.form_field_jq.attr("tabindex");
        this.form_field_jq.attr("tabindex", -1);
        if (this.is_multiple) {
          return this.search_field.attr("tabindex", ti);
        } else {
          this.selected_item.attr("tabindex", ti);
          return this.search_field.attr("tabindex", -1);
        }
      }
    };
    Chosen.prototype.show_search_field_default = function() {
      if (this.is_multiple && this.choices < 1 && !this.active_field) {
        this.search_field.val(this.default_text);
        return this.search_field.addClass("default");
      } else {
        this.search_field.val("");
        return this.search_field.removeClass("default");
      }
    };
    Chosen.prototype.search_results_click = function(evt) {
      var target;
      target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first();
      if (target.length) {
        this.result_highlight = target;
        return this.result_select();
      }
    };
    Chosen.prototype.search_results_mouseover = function(evt) {
      var target;
      target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first();
      if (target) {
        return this.result_do_highlight(target);
      }
    };
    Chosen.prototype.search_results_mouseout = function(evt) {
      if ($(evt.target).hasClass("active-result" || $(evt.target).parents('.active-result').first())) {
        return this.result_clear_highlight();
      }
    };
    Chosen.prototype.choices_click = function(evt) {
      evt.preventDefault();
      if (this.active_field && !($(evt.target).hasClass("search-choice" || $(evt.target).parents('.search-choice').first)) && !this.results_showing) {
        return this.results_show();
      }
    };
    Chosen.prototype.choice_build = function(item) {
      var choice_id, link;
      choice_id = this.container_id + "_c_" + item.array_index;
      this.choices += 1;
      this.search_container.before('<li class="search-choice" id="' + choice_id + '"><span>' + item.text + '</span><a href="javascript:void(0)" class="search-choice-close" rel="' + item.array_index + '"></a></li>');
      link = $('#' + choice_id).find("a").first();
      return link.click(__bind(function(evt) {
        return this.choice_destroy_link_click(evt);
      }, this));
    };
    Chosen.prototype.choice_destroy_link_click = function(evt) {
      evt.preventDefault();
      this.pending_destroy_click = true;
      return this.choice_destroy($(evt.target));
    };
    Chosen.prototype.choice_destroy = function(link) {
      this.choices -= 1;
      this.show_search_field_default();
      if (this.is_multiple && this.choices > 0 && this.search_field.val().length < 1) {
        this.results_hide();
      }
      this.result_deselect(link.attr("rel"));
      return link.parents('li').first().remove();
    };
    Chosen.prototype.result_select = function() {
      var high, high_id, item, position;
      if (this.result_highlight) {
        high = this.result_highlight;
        high_id = high.attr("id");
        this.result_clear_highlight();
        high.addClass("result-selected");
        if (this.is_multiple) {
          this.result_deactivate(high);
        } else {
          this.result_single_selected = high;
        }
        position = high_id.substr(high_id.lastIndexOf("_") + 1);
        item = this.results_data[position];
        item.selected = true;
        this.form_field.options[item.options_index].selected = true;
        if (this.is_multiple) {
          this.choice_build(item);
        } else {
          this.selected_item.find("span").first().text(item.text);
        }
        this.results_hide();
        this.search_field.val("");
        this.form_field_jq.trigger("change");
        return this.search_field_scale();
      }
    };
    Chosen.prototype.result_activate = function(el) {
      return el.addClass("active-result").show();
    };
    Chosen.prototype.result_deactivate = function(el) {
      return el.removeClass("active-result").hide();
    };
    Chosen.prototype.result_deselect = function(pos) {
      var result, result_data;
      result_data = this.results_data[pos];
      result_data.selected = false;
      this.form_field.options[result_data.options_index].selected = false;
      result = $("#" + this.container_id + "_o_" + pos);
      result.removeClass("result-selected").addClass("active-result").show();
      this.result_clear_highlight();
      this.winnow_results();
      this.form_field_jq.trigger("change");
      return this.search_field_scale();
    };
    Chosen.prototype.results_search = function(evt) {
      if (this.results_showing) {
        return this.winnow_results();
      } else {
        return this.results_show();
      }
    };
    Chosen.prototype.winnow_results = function() {
      var found, option, part, parts, regex, result_id, results, searchText, startTime, startpos, text, zregex, _i, _j, _len, _len2, _ref;
      startTime = new Date();
      this.no_results_clear();
      results = 0;
      searchText = this.search_field.val() === this.default_text ? "" : $.trim(this.search_field.val());
      regex = new RegExp('^' + searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i');
      zregex = new RegExp(searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i');
      _ref = this.results_data;
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        option = _ref[_i];
        if (!option.disabled && !option.empty) {
          if (option.group) {
            $('#' + option.dom_id).hide();
          } else if (!(this.is_multiple && option.selected)) {
            found = false;
            result_id = option.dom_id;
            if (regex.test(option.text)) {
              found = true;
              results += 1;
            } else if (option.text.indexOf(" ") >= 0 || option.text.indexOf("[") === 0) {
              parts = option.text.replace(/\[|\]/g, "").split(" ");
              if (parts.length) {
                for (_j = 0, _len2 = parts.length; _j < _len2; _j++) {
                  part = parts[_j];
                  if (regex.test(part)) {
                    found = true;
                    results += 1;
                  }
                }
              }
            }
            if (found) {
              if (searchText.length) {
                startpos = option.text.search(zregex);
                text = option.text.substr(0, startpos + searchText.length) + '</em>' + option.text.substr(startpos + searchText.length);
                text = text.substr(0, startpos) + '<em>' + text.substr(startpos);
              } else {
                text = option.text;
              }
              if ($("#" + result_id).html !== text) {
                $("#" + result_id).html(text);
              }
              this.result_activate($("#" + result_id));
              if (option.group_array_index != null) {
                $("#" + this.results_data[option.group_array_index].dom_id).show();
              }
            } else {
              if (this.result_highlight && result_id === this.result_highlight.attr('id')) {
                this.result_clear_highlight();
              }
              this.result_deactivate($("#" + result_id));
            }
          }
        }
      }
      if (results < 1 && searchText.length) {
        return this.no_results(searchText);
      } else {
        return this.winnow_results_set_highlight();
      }
    };
    Chosen.prototype.winnow_results_clear = function() {
      var li, lis, _i, _len, _results;
      this.search_field.val("");
      lis = this.search_results.find("li");
      _results = [];
      for (_i = 0, _len = lis.length; _i < _len; _i++) {
        li = lis[_i];
        li = $(li);
        _results.push(li.hasClass("group-result") ? li.show() : !this.is_multiple || !li.hasClass("result-selected") ? this.result_activate(li) : void 0);
      }
      return _results;
    };
    Chosen.prototype.winnow_results_set_highlight = function() {
      var do_high;
      if (!this.result_highlight) {
        do_high = this.search_results.find(".active-result").first();
        if (do_high) {
          return this.result_do_highlight(do_high);
        }
      }
    };
    Chosen.prototype.no_results = function(terms) {
      var no_results_html;
      no_results_html = $('<li class="no-results">No results match "<span></span>"</li>');
      no_results_html.find("span").first().text(terms);
      return this.search_results.append(no_results_html);
    };
    Chosen.prototype.no_results_clear = function() {
      return this.search_results.find(".no-results").remove();
    };
    Chosen.prototype.keydown_arrow = function() {
      var first_active, next_sib;
      if (!this.result_highlight) {
        first_active = this.search_results.find("li.active-result").first();
        if (first_active) {
          this.result_do_highlight($(first_active));
        }
      } else if (this.results_showing) {
        next_sib = this.result_highlight.nextAll("li.active-result").first();
        if (next_sib) {
          this.result_do_highlight(next_sib);
        }
      }
      if (!this.results_showing) {
        return this.results_show();
      }
    };
    Chosen.prototype.keyup_arrow = function() {
      var prev_sibs;
      if (!this.results_showing && !this.is_multiple) {
        return this.results_show();
      } else if (this.result_highlight) {
        prev_sibs = this.result_highlight.prevAll("li.active-result");
        if (prev_sibs.length) {
          return this.result_do_highlight(prev_sibs.first());
        } else {
          if (this.choices > 0) {
            this.results_hide();
          }
          return this.result_clear_highlight();
        }
      }
    };
    Chosen.prototype.keydown_backstroke = function() {
      if (this.pending_backstroke) {
        this.choice_destroy(this.pending_backstroke.find("a").first());
        return this.clear_backstroke();
      } else {
        this.pending_backstroke = this.search_container.siblings("li.search-choice").last();
        return this.pending_backstroke.addClass("search-choice-focus");
      }
    };
    Chosen.prototype.clear_backstroke = function() {
      if (this.pending_backstroke) {
        this.pending_backstroke.removeClass("search-choice-focus");
      }
      return this.pending_backstroke = null;
    };
    Chosen.prototype.keyup_checker = function(evt) {
      var stroke, _ref;
      stroke = (_ref = evt.which) != null ? _ref : evt.keyCode;
      this.search_field_scale();
      switch (stroke) {
        case 8:
          if (this.is_multiple && this.backstroke_length < 1 && this.choices > 0) {
            return this.keydown_backstroke();
          } else if (!this.pending_backstroke) {
            this.result_clear_highlight();
            return this.results_search();
          }
          break;
        case 13:
          evt.preventDefault();
          if (this.results_showing) {
            return this.result_select();
          }
          break;
        case 27:
          if (this.results_showing) {
            return this.results_hide();
          }
          break;
        case 9:
        case 38:
        case 40:
        case 16:
          break;
        default:
          return this.results_search();
      }
    };
    Chosen.prototype.keydown_checker = function(evt) {
      var stroke, _ref;
      stroke = (_ref = evt.which) != null ? _ref : evt.keyCode;
      this.search_field_scale();
      if (stroke !== 8 && this.pending_backstroke) {
        this.clear_backstroke();
      }
      switch (stroke) {
        case 8:
          this.backstroke_length = this.search_field.val().length;
          break;
        case 9:
          this.mouse_on_container = false;
          break;
        case 13:
          evt.preventDefault();
          break;
        case 38:
          evt.preventDefault();
          this.keyup_arrow();
          break;
        case 40:
          this.keydown_arrow();
          break;
      }
    };
    Chosen.prototype.search_field_scale = function() {
      var dd_top, div, h, style, style_block, styles, w, _i, _len;
      if (this.is_multiple) {
        h = 0;
        w = 0;
        style_block = "position:absolute; left: -1000px; top: -1000px; display:none;";
        styles = ['font-size', 'font-style', 'font-weight', 'font-family', 'line-height', 'text-transform', 'letter-spacing'];
        for (_i = 0, _len = styles.length; _i < _len; _i++) {
          style = styles[_i];
          style_block += style + ":" + this.search_field.css(style) + ";";
        }
        div = $('<div />', {
          'style': style_block
        });
        div.text(this.search_field.val());
        $('body').append(div);
        w = div.width() + 25;
        div.remove();
        if (w > this.f_width - 10) {
          w = this.f_width - 10;
        }
        this.search_field.css({
          'width': w + 'px'
        });
        dd_top = this.container.height();
        return this.dropdown.css({
          "top": dd_top + "px"
        });
      }
    };
    Chosen.prototype.generate_field_id = function() {
      var new_id;
      new_id = this.generate_random_id();
      this.form_field.id = new_id;
      return new_id;
    };
    Chosen.prototype.generate_random_id = function() {
      var string;
      string = "sel" + this.generate_random_char() + this.generate_random_char() + this.generate_random_char();
      while ($("#" + string).length > 0) {
        string += this.generate_random_char();
      }
      return string;
    };
    Chosen.prototype.generate_random_char = function() {
      var chars, newchar, rand;
      chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZ";
      rand = Math.floor(Math.random() * chars.length);
      return newchar = chars.substring(rand, rand + 1);
    };
    return Chosen;
  })();
  get_side_border_padding = function(elmt) {
    var side_border_padding;
    return side_border_padding = elmt.outerWidth() - elmt.width();
  };
  root.get_side_border_padding = get_side_border_padding;
  SelectParser = (function() {
    function SelectParser() {
      this.options_index = 0;
      this.parsed = [];
    }
    SelectParser.prototype.add_node = function(child) {
      if (child.nodeName === "OPTGROUP") {
        return this.add_group(child);
      } else {
        return this.add_option(child);
      }
    };
    SelectParser.prototype.add_group = function(group) {
      var group_position, option, _i, _len, _ref, _results;
      group_position = this.parsed.length;
      this.parsed.push({
        array_index: group_position,
        group: true,
        label: group.label,
        children: 0,
        disabled: group.disabled
      });
      _ref = group.childNodes;
      _results = [];
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        option = _ref[_i];
        _results.push(this.add_option(option, group_position, group.disabled));
      }
      return _results;
    };
    SelectParser.prototype.add_option = function(option, group_position, group_disabled) {
      if (option.nodeName === "OPTION") {
        if (option.text !== "") {
          if (group_position != null) {
            this.parsed[group_position].children += 1;
          }
          this.parsed.push({
            array_index: this.parsed.length,
            options_index: this.options_index,
            value: option.value,
            text: option.text,
            selected: option.selected,
            disabled: group_disabled === true ? group_disabled : option.disabled,
            group_array_index: group_position
          });
        } else {
          this.parsed.push({
            array_index: this.parsed.length,
            options_index: this.options_index,
            empty: true
          });
        }
        return this.options_index += 1;
      }
    };
    return SelectParser;
  })();
  SelectParser.select_to_array = function(select) {
    var child, parser, _i, _len, _ref;
    parser = new SelectParser();
    _ref = select.childNodes;
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      child = _ref[_i];
      parser.add_node(child);
    }
    return parser.parsed;
  };
  root.SelectParser = SelectParser;
}).call(this);
(function($) {
  $.fn.pagination = function(options) {

    var defaults = {};
    var options = $.extend(defaults, options);

    return this.each(function() {
      var params = $.extend(options, { element: $(this) });

      if (params.element.data('pagination')) {
        params.element.data('pagination').reset();
      } else {
        params.element.data('pagination', new Pagination(params));
      }
    });
  };
})(jQuery);

//

var Pagination = function(options) {

  var defaults = {
    onPrevious: function(pagination) {
      pagination.previous();
    },
    onNext: function(pagination) {
      pagination.next();
    },
    movement: 'vertical'
  };
  options = $.extend(defaults, options);
  this.element = options.element;

  this.parseDOMOptions = function() {
    var options = {};
    if ('horizontal' == this.element.attr('data-movement')) {
      options.movement = 'horizontal';
    }
    return options;
  };
  var domOptions = this.parseDOMOptions();

  options = $.extend(options, domOptions);
  this.options = options;

  this.offset = options.offset || 1; // custom change to get the page right when on a certain page unon initialization --R

  this.previousTrigger = null;
  this.nextTrigger = null;

  this.pager = null;

  this.init = function() {
    this.initDOM();
    this.initPaginationTriggers();
    this.initPager();
    var initialOffset = this.element.attr('data-initial-offset');
    if (initialOffset) {
      this.paginate(initialOffset);
    } else {
      this.element.trigger('paginated', this);
    }
  };

  this.initDOM = function() {
    var a_page = this.element.find('.page');
    if (this.options.movement == 'horizontal') {
      var width = a_page.width()
      this.element.width(a_page.length * width);
    } else {
      this.element.css({
        height: 'auto', overflow: 'visible'
      });
    }
    this.element.wrapAll('<div class="pagination-container" />').parent().css({
      overflow: 'hidden', height: a_page.height(), width: a_page.width()
    });
  };

  this.initPaginationTriggers = function() {
    var pagination = this;
    var pageable_key = this.element.attr('data-pageable');
    var triggers = $('[data-pagination="' + pageable_key + '"]');
    triggers.each(function(e) {
      if ($(this).attr('data-page-direction') == 'previous') {
        pagination.previousTrigger = $(this);
      } else {
        pagination.nextTrigger = $(this);
      }
    });
    triggers.click(function(e) {
      e.preventDefault();
      if (!$(this).hasClass('disabled')) {
        if ($(this).attr('data-page-direction') == 'previous') {
          $.proxy(function() { pagination.options.onPrevious(pagination); }, pagination)();
        } else {
          $.proxy(function() { pagination.options.onNext(pagination); }, pagination)();
        }
      }
    });
    this.toggleTriggers(this.offset, this.maxOffset());
  };

  this.initPager = function() {
    var pagination = this;
    var pageable_key = this.element.attr('data-pageable');
    this.pager = $('[data-pager="' + pageable_key + '"]');

    var pagerFixed = typeof this.pager.attr('data-pager-fixed') == 'undefined'
    if (this.pager.length > 0) {
      if (pagerFixed) {
        this.pager.empty();
      }
      var maxOffset = this.maxOffset();
      if (maxOffset > 1) {
        for (var i = 1; i <= maxOffset; i++) {
          var a;
          if (pagerFixed) {
            a = $('<a href=""/>');
            this.pager.append(a);
          } else {
            a = $(this.pager.find('a')[i - 1]);
          }
          if (i == pagination.offset) {
            a.addClass('active');
          }
          a.attr('data-offset', i);
          a.click(function(e) {
            e.preventDefault();
            pagination.paginate($(this).attr('data-offset'));
          });
        }
      }
    }
  };

  this.previous = function() {
    this.paginate(this.offset - 1);
  };

  this.next = function() {
    this.paginate(this.offset + 1);
  };

  this.maxOffset = this.options.maxOffset || function() {
    var m = this.element.parent().find('li.page').length;
    return (m == 0) ? 1 : m;
  };

  this.paginate = function(offset) {
    offset = parseInt(offset);
    //
    var maxOffset = this.maxOffset();
    if (offset < 1 || offset > maxOffset) {
      // we can't move, toggle triggers to old offset (this.offset)
      this.toggleTriggers(this.offset, maxOffset);
    } else {
      this.move(offset);
    }
    //
    var pagerLinks = this.pager.find('a');
    // console calls are still messing up internet explorer 7
    // console.log( 'pagerLinks: ' + pagerLinks.toString() );
    pagerLinks.removeClass('active');
    $(pagerLinks[offset - 1]).addClass('active');
  };

  this.toggleTriggers = function(offset, maxOffset) {
    if (offset <= 1) {
      this.previousTrigger.addClass('disabled');
    } else {
      this.previousTrigger.removeClass('disabled');
    }
    //
    if (offset >= maxOffset) {
      this.nextTrigger.addClass('disabled');
    } else {
      this.nextTrigger.removeClass('disabled');
    }
  };

  this.move = function(offset) {
    // horizontal
    if (this.options.movement == 'horizontal') {
      var scrollWidth = this.element.parent().width();
      var left = Math.floor(-scrollWidth * (offset - 1)) + 'px';
      if (typeof WebKitCSSMatrix == "undefined") {
        this.element.animate({ marginLeft: left });
      } else {
        this.element.css('-webkit-transition', 'all 0.5s ease-in-out');
        this.element.css('-webkit-transform',  'translate3d(' + left + ', 0px, 0px)');
      }
    // vertical
    } else {
      var scrollHeight = this.element.parent().height();
      var top = Math.floor(-scrollHeight * (offset - 1)) + 'px';
      if (typeof WebKitCSSMatrix == "undefined") {
        this.element.animate({ marginTop: top });
      } else {
        this.element.css('-webkit-transition', 'all 0.5s ease-in-out');
        this.element.css('-webkit-transform',  'translate3d(0px, ' + top + ', 0px)');
      }
    }
    //
    this.offset = offset;
    this.toggleTriggers(this.offset, this.maxOffset());
    this.element.trigger('paginated', this);
  };

  this.reset = function() {
    var a_page = this.element.find('.page');
    this.element.parent('.pagination-container').css({
      height: a_page.height(),
      width: a_page.width()
    });
    this.initPager();
    if (this.options.movement == 'horizontal') {
      this.element.width(a_page.width() * a_page.length);
    } else {
      this.element.height(a_page.height() * a_page.length);
    }
    this.offset == this.maxOffset;
    this.paginate(1);
  };

  this.currentPage = function() {
    return $(this.element.find('.page')[this.offset - 1]);
  };

  //
  this.init();
  return this;
};
(function($){
    $.fn.extend({
        animationTab: function(options){
            var _this = this;
            var defaults = {
                callBack: function(){
                },
                before: function(){
                },
                tabBorder: $(),
                animateTime: 500,
                timer: null
            };
            var opts = $.extend(defaults, options), _this = this;
            opts.before();
            var tabX = [];
            var now = 0;
            var pageWidth = $(_this).find(".tabContent>ul>li").outerWidth(true);
            $(_this).find(".tabContent>ul").width(pageWidth * $(_this).find(".tabContent>ul>li").length);
            $(_this).find(".tabs>a").each(function(i){
                var tabLeft = {
                    "left": $(this).position().left,
                    "width": $(this).outerWidth(),
                    "height": $(this).outerHeight()
                };
                tabX.push(tabLeft);
                $(this).click(function(){
                    move(i);
                    return false;
                })
            });
            $(_this).find(".prev").click(function(){
                now--;
                move(now);
            });
            $(_this).find(".next").click(function(){
                now++;
                move(now);
            });
            
            opts.tabBorder.css({
                "left": tabX[now].left,
                "width": tabX[now].width,
                "height": tabX[now].height
            });
            if (now >= $(_this).find(".tabContent>ul>li").length - 1) {
                $(_this).find(".next").hide();
                now = $(_this).find(".tabContent>ul>li").length - 1;
            }
            if (now <= 0) {
                $(_this).find(".prev").hide();
                now = 0;
            }
            
            
            function move(i){
                $(_this).find(".prev").show();
                $(_this).find(".next").show();
                if (i >= $(_this).find(".tabContent>ul>li").length - 1) {
                    $(_this).find(".next").hide();
                    i = $(_this).find(".tabContent>ul>li").length - 1;
                }
                if (i <= 0) {
                    $(_this).find(".prev").hide();
                    i = 0;
                }
                $(_this).find(".tabContent>ul").animate({
                    "left": -pageWidth * i
                }, opts.animateTime);
                opts.tabBorder.animate({
                    "left": tabX[i].left,
                    "width": tabX[i].width,
                    "height": tabX[i].height
                }, opts.animateTime);
                $(_this).find(".tabs>a").removeClass("active");
                $(_this).find(".tabs>a").eq(i).addClass("active");
                now = i;
            }
        }
        
    })
})(jQuery);

(function(a){var r=a.fn.domManip,d="_tmplitem",q=/^[^<]*(<[\w\W]+>)[^>]*$|\{\{\! /,b={},f={},e,p={key:0,data:{}},h=0,c=0,l=[];function g(e,d,g,i){var c={data:i||(d?d.data:{}),_wrap:d?d._wrap:null,tmpl:null,parent:d||null,nodes:[],calls:u,nest:w,wrap:x,html:v,update:t};e&&a.extend(c,e,{nodes:[],parent:d});if(g){c.tmpl=g;c._ctnt=c._ctnt||c.tmpl(a,c);c.key=++h;(l.length?f:b)[h]=c}return c}a.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(f,d){a.fn[f]=function(n){var g=[],i=a(n),k,h,m,l,j=this.length===1&&this[0].parentNode;e=b||{};if(j&&j.nodeType===11&&j.childNodes.length===1&&i.length===1){i[d](this[0]);g=this}else{for(h=0,m=i.length;h<m;h++){c=h;k=(h>0?this.clone(true):this).get();a.fn[d].apply(a(i[h]),k);g=g.concat(k)}c=0;g=this.pushStack(g,f,i.selector)}l=e;e=null;a.tmpl.complete(l);return g}});a.fn.extend({tmpl:function(d,c,b){return a.tmpl(this[0],d,c,b)},tmplItem:function(){return a.tmplItem(this[0])},template:function(b){return a.template(b,this[0])},domManip:function(d,l,j){if(d[0]&&d[0].nodeType){var f=a.makeArray(arguments),g=d.length,i=0,h;while(i<g&&!(h=a.data(d[i++],"tmplItem")));if(g>1)f[0]=[a.makeArray(d)];if(h&&c)f[2]=function(b){a.tmpl.afterManip(this,b,j)};r.apply(this,f)}else r.apply(this,arguments);c=0;!e&&a.tmpl.complete(b);return this}});a.extend({tmpl:function(d,h,e,c){var j,k=!c;if(k){c=p;d=a.template[d]||a.template(null,d);f={}}else if(!d){d=c.tmpl;b[c.key]=c;c.nodes=[];c.wrapped&&n(c,c.wrapped);return a(i(c,null,c.tmpl(a,c)))}if(!d)return[];if(typeof h==="function")h=h.call(c||{});e&&e.wrapped&&n(e,e.wrapped);j=a.isArray(h)?a.map(h,function(a){return a?g(e,c,d,a):null}):[g(e,c,d,h)];return k?a(i(c,null,j)):j},tmplItem:function(b){var c;if(b instanceof a)b=b[0];while(b&&b.nodeType===1&&!(c=a.data(b,"tmplItem"))&&(b=b.parentNode));return c||p},template:function(c,b){if(b){if(typeof b==="string")b=o(b);else if(b instanceof a)b=b[0]||{};if(b.nodeType)b=a.data(b,"tmpl")||a.data(b,"tmpl",o(b.innerHTML));return typeof c==="string"?(a.template[c]=b):b}return c?typeof c!=="string"?a.template(null,c):a.template[c]||a.template(null,q.test(c)?c:a(c)):null},encode:function(a){return(""+a).split("<").join("&lt;").split(">").join("&gt;").split('"').join("&#34;").split("'").join("&#39;")}});a.extend(a.tmpl,{tag:{tmpl:{_default:{$2:"null"},open:"if($notnull_1){_=_.concat($item.nest($1,$2));}"},wrap:{_default:{$2:"null"},open:"$item.calls(_,$1,$2);_=[];",close:"call=$item.calls();_=call._.concat($item.wrap(call,_));"},each:{_default:{$2:"$index, $value"},open:"if($notnull_1){$.each($1a,function($2){with(this){",close:"}});}"},"if":{open:"if(($notnull_1) && $1a){",close:"}"},"else":{_default:{$1:"true"},open:"}else if(($notnull_1) && $1a){"},html:{open:"if($notnull_1){_.push($1a);}"},"=":{_default:{$1:"$data"},open:"if($notnull_1){_.push($.encode($1a));}"},"!":{open:""}},complete:function(){b={}},afterManip:function(f,b,d){var e=b.nodeType===11?a.makeArray(b.childNodes):b.nodeType===1?[b]:[];d.call(f,b);m(e);c++}});function i(e,g,f){var b,c=f?a.map(f,function(a){return typeof a==="string"?e.key?a.replace(/(<\w+)(?=[\s>])(?![^>]*_tmplitem)([^>]*)/g,"$1 "+d+'="'+e.key+'" $2'):a:i(a,e,a._ctnt)}):e;if(g)return c;c=c.join("");c.replace(/^\s*([^<\s][^<]*)?(<[\w\W]+>)([^>]*[^>\s])?\s*$/,function(f,c,e,d){b=a(e).get();m(b);if(c)b=j(c).concat(b);if(d)b=b.concat(j(d))});return b?b:j(c)}function j(c){var b=document.createElement("div");b.innerHTML=c;return a.makeArray(b.childNodes)}function o(b){return new Function("jQuery","$item","var $=jQuery,call,_=[],$data=$item.data;with($data){_.push('"+a.trim(b).replace(/([\\'])/g,"\\$1").replace(/[\r\t\n]/g," ").replace(/\$\{([^\}]*)\}/g,"{{= $1}}").replace(/\{\{(\/?)(\w+|.)(?:\(((?:[^\}]|\}(?!\}))*?)?\))?(?:\s+(.*?)?)?(\(((?:[^\}]|\}(?!\}))*?)\))?\s*\}\}/g,function(m,l,j,d,b,c,e){var i=a.tmpl.tag[j],h,f,g;if(!i)throw"Template command not found: "+j;h=i._default||[];if(c&&!/\w$/.test(b)){b+=c;c=""}if(b){b=k(b);e=e?","+k(e)+")":c?")":"";f=c?b.indexOf(".")>-1?b+c:"("+b+").call($item"+e:b;g=c?f:"(typeof("+b+")==='function'?("+b+").call($item):("+b+"))"}else g=f=h.$1||"null";d=k(d);return"');"+i[l?"close":"open"].split("$notnull_1").join(b?"typeof("+b+")!=='undefined' && ("+b+")!=null":"true").split("$1a").join(g).split("$1").join(f).split("$2").join(d?d.replace(/\s*([^\(]+)\s*(\((.*?)\))?/g,function(d,c,b,a){a=a?","+a+")":b?")":"";return a?"("+c+").call($item"+a:d}):h.$2||"")+"_.push('"})+"');}return _;")}function n(c,b){c._wrap=i(c,true,a.isArray(b)?b:[q.test(b)?b:a(b).html()]).join("")}function k(a){return a?a.replace(/\\'/g,"'").replace(/\\\\/g,"\\"):null}function s(b){var a=document.createElement("div");a.appendChild(b.cloneNode(true));return a.innerHTML}function m(o){var n="_"+c,k,j,l={},e,p,i;for(e=0,p=o.length;e<p;e++){if((k=o[e]).nodeType!==1)continue;j=k.getElementsByTagName("*");for(i=j.length-1;i>=0;i--)m(j[i]);m(k)}function m(j){var p,i=j,k,e,m;if(m=j.getAttribute(d)){while(i.parentNode&&(i=i.parentNode).nodeType===1&&!(p=i.getAttribute(d)));if(p!==m){i=i.parentNode?i.nodeType===11?0:i.getAttribute(d)||0:0;if(!(e=b[m])){e=f[m];e=g(e,b[i]||f[i],null,true);e.key=++h;b[h]=e}c&&o(m)}j.removeAttribute(d)}else if(c&&(e=a.data(j,"tmplItem"))){o(e.key);b[e.key]=e;i=a.data(j.parentNode,"tmplItem");i=i?i.key:0}if(e){k=e;while(k&&k.key!=i){k.nodes.push(j);k=k.parent}delete e._ctnt;delete e._wrap;a.data(j,"tmplItem",e)}function o(a){a=a+n;e=l[a]=l[a]||g(e,b[e.parent.key+n]||e.parent,null,true)}}}function u(a,d,c,b){if(!a)return l.pop();l.push({_:a,tmpl:d,item:this,data:c,options:b})}function w(d,c,b){return a.tmpl(a.template(d),c,b,this)}function x(b,d){var c=b.options||{};c.wrapped=d;return a.tmpl(a.template(b.tmpl),b.data,c,b.item)}function v(d,c){var b=this._wrap;return a.map(a(a.isArray(b)?b.join(""):b).filter(d||"*"),function(a){return c?a.innerText||a.textContent:a.outerHTML||s(a)})}function t(){var b=this.nodes;a.tmpl(null,null,null,this).insertBefore(b[0]);a(b).remove()}})(jQuery)
$.fn.serializeObject = function()
{
    var o = {};
    var a = this.serializeArray();
    $.each(a, function() {
        if (o[this.name] !== undefined) {
            if (!o[this.name].push) {
                o[this.name] = [o[this.name]];
            }
            o[this.name].push(this.value || '');
        } else {
            o[this.name] = this.value || '';
        }
    });
    return o;
};
(function() {
  var ua, uaClass, uaClasses, _i, _len;
  this.App = {
    init: function() {}
  };
  _.mixin({
    toJSON: function(object) {
      if (_.isArray(object)) {
        return _.map(object, function(element) {
          return _.toJSON(element);
        });
      } else if (typeof object === 'object' && typeof object.toJSON === 'function') {
        return object.toJSON();
      } else {
        return object;
      }
    },
    pluralize: function(string) {
      var exceptions;
      exceptions = {
        'person': 'people'
      };
      if (exceptions[string]) {
        return exceptions[string];
      } else {
        return string + 's';
      }
    }
  });
  $(function() {
    App.init();
    App.Text.init();
    App.initUserAgentSwitches();
    App.initButtons();
    App.initConstants();
    App.initGallery();
    App.initPopups();
    App.initOverlays();
    App.initHelpMouseHandlers();
    App.initPromotionContainer();
    App.initForm();
    App.initTabs();
    App.initPagination();
    App.initTooltip();
    App.wizard.init();
    App.initJQueryUI();
    App.initChatStatus();
    App.initUserNotifications();
    App.initIdScroller();
    App.initIdFocus();
    return App.initTabSwitch();
  });
  ua = navigator.userAgent.toLowerCase();
  uaClasses = ['webkit', 'presto', 'gecko', 'msie'];
  for (_i = 0, _len = uaClasses.length; _i < _len; _i++) {
    uaClass = uaClasses[_i];
    if (ua.indexOf(uaClass) !== -1) {
      $('html').addClass(uaClass);
      break;
    }
  }
}).call(this);
(function() {
  this.App.initButtons = function() {
    return $('.button[disabled], .button.disabled').live('click', function(e) {
      e.stopPropagation();
      return e.preventDefault();
    });
  };
}).call(this);
(function() {
  var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
  this.App.setUserOnlineState = function(onlineState) {
    var state;
    $('.chat-status').find('a').removeClass('current');
    state = $('.chat-status').find("[data-class=" + onlineState + "]");
    state.addClass('current');
    $('.chat-status').find('.current-chat-status span').attr('class', onlineState);
    $('.chat-status').find('.current-chat-status span').html(state.attr('data-text'));
    if (onlineState === "offline") {
      return $('.button[data-action=open-chat]').hide();
    }
  };
  this.App.initChatStatus = function() {
    $.get('/api/v1/profile', __bind(function(data) {
      return this.setUserOnlineState(data.user.online_state);
    }, this));
    $('.current-chat-status').click(function(e) {
      var $chatStatus, $dropDown, $el, className;
      e.preventDefault();
      e.stopPropagation();
      $el = $(this);
      $chatStatus = $el.parents('.chat-status');
      $dropDown = $el.parent().find('.drop-down');
      if ($dropDown.css('display') !== 'none') {
        $dropDown.fadeOut(300);
        return;
      }
      $('html').bind('click', function(e) {
        $('html').unbind('click', arguments.callee);
        return $dropDown.fadeOut(300);
      });
      className = $chatStatus.find('.current-chat-status span').attr('class');
      $dropDown.find('a').removeClass('current');
      $dropDown.find("[data-class=" + className + "]").addClass('current');
      return $dropDown.fadeIn(300);
    });
    $('.chat-status [data-class]').click(function(e) {
      var $chatStatus, $el, $elDataClass, $elDataText;
      e.preventDefault();
      $el = $(this);
      $chatStatus = $el.parents('.chat-status');
      $elDataClass = $el.attr('data-class');
      $elDataText = $el.attr('data-text');
      $chatStatus.find('.current-chat-status span').attr('class', $elDataClass).text($elDataText);
      $chatStatus.find('.drop-down').fadeOut(300);
      if ($elDataClass === "offline") {
        $('.button[data-action=open-chat]').hide();
      } else {
        $('.button[data-action=open-chat]').show();
      }
      return $.ajax({
        type: 'PUT',
        url: '/api/v1/profile',
        data: {
          current_user: {
            online_state: $el.attr('data-class')
          }
        }
      });
    });
    return $('.chat-status .drop-down').click(function(e) {
      if ($(e.target).is('a')) {
        return;
      }
      e.preventDefault();
      return e.stopPropagation();
    });
  };
}).call(this);
(function() {
  this.App.initConstants = function() {
    return App.colors = {
      f01: '#764660',
      f02: '#81556C',
      f03: '#FCF4E9',
      f04: '#FEFBF8',
      f05: '#4F223A',
      f06: '#F3EFB6',
      f07: '#D1C1CA',
      f08: '#8f8f8f',
      f09: '#e1d7dc',
      f10: '#f1ecec'
    };
  };
}).call(this);
(function() {
  this.App.ContactFilter = {};
  this.App.ContactFilter.init = function() {
    return $('.simple_form.contact_filter').live('ajax:before', function(e) {
      $('.number-amount').hide();
      return $('.spinner-small-contact').css('display', 'inline-block');
    });
  };
}).call(this);
(function() {
  this.App.DateRequestWidget = {};
  this.App.DateRequestWidget.init = function(defaultDate, calendarOptions) {
    var $dateField, $dpWidget, $selectedDate, $selectedTime, $timeField, addDatePickerEvent;
    $dpWidget = $('.datepicker-widget');
    $dateField = $('#meeting_time_date');
    $timeField = $('#meeting_time_time');
    $selectedDate = $('#datepicker-widget-selected-date');
    $selectedTime = $('#datepicker-widget-time-select');
    $('.date_request-selection.pagination').bind('paginated', function(e, pagination) {
      var li;
      li = pagination.currentPage();
      return li.find('.date_request-radio').attr({
        checked: 'checked'
      });
    });
    $('#reset-date_request-draft[data-action-reset-form]').click(function(e) {
      return $('.date_request-selection.pagination').data('pagination').paginate(1);
    });
    $dateField.live('focus', function() {
      var date;
      addDatePickerEvent();
      date = $(this).val();
      App.DateRequestWidget.fetchDates(date, false, App.DateRequestWidget.insertDates);
      return false;
    });
    $timeField.live('mousedown', function(e) {
      var date;
      addDatePickerEvent();
      date = $dateField.val();
      App.DateRequestWidget.fetchDates(date, false, App.DateRequestWidget.insertDates);
      return e.preventDefault();
    });
    $('.datepicker-widget-done-button').live('click', function() {
      $('#date_request_meeting_time').val($selectedDate.html() + ' ' + $selectedTime.val());
      $dateField.val($selectedDate.html());
      $timeField.val($selectedTime.val());
      $dateField.removeAttr('disabled');
      $timeField.removeAttr('disabled');
      $dpWidget.hide();
      return false;
    });
    $('.datepicker-widget-cancel-button').live('click', function() {
      $('.datepicker-widget').hide();
      $dateField.removeAttr('disabled');
      $timeField.removeAttr('disabled');
      return false;
    });
    return addDatePickerEvent = function() {
      var height, pos, width;
      pos = $dateField.position();
      width = $dateField.width();
      height = $dateField.height();
      $dpWidget.css({
        "left": pos.left + "px",
        "top": (pos.top + height + 8) + "px"
      }).show();
      $dateField.attr('disabled', true);
      return $timeField.attr('disabled', true);
    };
  };
  this.App.DateRequestWidget.fetchDates = function(date, renderLinks, completeCallback) {
    var links, queryString;
    links = renderLinks === true ? links = 1 : links = 0;
    queryString = "on_date=" + this.ensureDate(date + "&render_links=" + links);
    return $.ajax({
      url: "/date_requests",
      data: queryString,
      complete: function(data) {
        return completeCallback(data);
      }
    });
  };
  this.App.DateRequestWidget.insertDates = function(data) {
    return $('.datepicker-widget .dates ul').html(data.responseText);
  };
  this.App.DateRequestWidget.ensureDate = function(date) {
    var curDate, day, month, year;
    if (!date.length) {
      curDate = new Date.now();
      day = String(curDate.getDate());
      month = String(curDate.getMonth() + 1);
      year = curDate.getFullYear();
      if (day.length !== 2) {
        day = "0" + day;
      }
      if (month.length !== 2) {
        month = "0" + day;
      }
      return date = day + '.' + month + '.' + year;
    } else {
      return date;
    }
  };
}).call(this);
(function() {
  this.App.initEvalStats = function(container, entries, overwriteWidth, overwriteHeight, chartButtonTruePath, chartButtonNullPath, chartButtonFalsePath) {
    var additionalWidth, chartButtonFalseImage, chartButtonNullImage, chartButtonTrueImage, color, createRandomEntries, difference, drawBorder, drawLine, fontSize, fontType, getEntriesMax, getRandom, getVisualRound, gfxHeight, gfxWidth, gfxX, gfxY, height, i, lowerBorderY, lowerLineX1, lowerLineX2, lowerLineY, maxValue, numEntries, offsetX, offsetY, paper, paperDiv, posX, posY1, posY2, remainingWidth, roundList, scaleArea, smallFontSize, spaceBetweenElements, spaceBottom, spaceLeft, spaceRight, stepY, text, txtElement, txtNumber, txtNumbers, upperLineX1, upperLineX2, upperLineY, width, widthOfElement, zeroLine1Y, zeroLine2Y, zeroLineX1, zeroLineX2, zeroOffset;
    drawBorder = function(p, x, y, w, h, enableBorder, fillColor) {
      var border;
      border = p.path("M" + x + " " + y + " L" + (x + w) + " " + y + " " + "L" + (x + w) + " " + (y + h) + " " + "L" + x + " " + (y + h) + " " + "L" + x + " " + y);
      if (!fillColor) {
        fillColor = "#eee";
      }
      if (enableBorder) {
        border.attr({
          stroke: "#000"
        });
      } else {
        border.attr({
          stroke: fillColor
        });
      }
      border.attr({
        opacity: "1.0"
      });
      border.attr({
        fill: fillColor
      });
      return border;
    };
    drawLine = function(p, x1, y1, x2, y2, fillColor) {
      var line;
      if (!fillColor) {
        fillColor = "#000";
      }
      line = p.path("M" + x1 + " " + y1 + " L" + x2 + " " + y2);
      line.attr({
        stroke: fillColor
      });
      return line;
    };
    getRandom = function(min, max) {
      return min + parseInt(Math.random() * (max - min + 1));
    };
    getVisualRound = function(value, roundList) {
      var digits, i;
      i = 0;
      while (i < roundList.length) {
        if (value <= roundList[i]) {
          return roundList[i];
        }
        i++;
      }
      digits = 1;
      while (value > Math.pow(10, digits - 1)) {
        digits += 1;
      }
      return Math.pow(10, digits - 1);
    };
    createRandomEntries = function(num) {
      var i, maxVal, out, rv, txtContent;
      i = 0;
      out = [];
      while (i < num) {
        rv = getRandom(0, 3);
        if (rv === 0) {
          txtContent = "Hello";
        } else if (rv === 1) {
          txtContent = "Wow";
        } else if (rv === 2) {
          txtContent = "This is a longer line";
        } else if (rv === 3) {
          txtContent = "Dideldum";
        }
        maxVal = 10;
        out[i] = [txtContent, getRandom(0, getRandom(0, maxVal)), getRandom(0, getRandom(0, getRandom(0, maxVal)))];
        i++;
      }
      return out;
    };
    getEntriesMax = function(entries) {
      var i, max;
      i = 0;
      max = 0;
      while (i < entries.length) {
        if (Math.abs(entries[i][1]) > max) {
          max = entries[i][1];
        }
        if (Math.abs(entries[i][2]) > max) {
          max = entries[i][2];
        }
        i++;
      }
      return max;
    };
    numEntries = entries.length;
    paperDiv = container;
    width = paperDiv.width();
    height = paperDiv.height();
    if (overwriteWidth && overwriteWidth > 0) {
      width = overwriteWidth;
    }
    if (overwriteHeight && overwriteHeight > 0) {
      height = overwriteHeight;
    }
    offsetX = 5;
    offsetY = 5;
    if (width <= 0) {
      width = 600;
    }
    if (height <= 0) {
      height = width;
    }
    paper = Raphael(paperDiv[0], width, height);
    spaceLeft = 50;
    spaceRight = 38;
    spaceBottom = 164;
    gfxWidth = width - spaceLeft - spaceRight - offsetX * 2;
    gfxHeight = height - spaceBottom - offsetY * 2;
    gfxX = spaceLeft + offsetX;
    gfxY = 0 + offsetY;
    zeroOffset = 13;
    zeroLine1Y = gfxY + gfxHeight / 2 - zeroOffset / 2;
    zeroLineX1 = gfxX;
    zeroLineX2 = gfxX + gfxWidth;
    zeroLine2Y = gfxY + gfxHeight / 2 + zeroOffset / 2;
    scaleArea = (gfxHeight / 2) * .875;
    upperLineY = zeroLine1Y - scaleArea;
    upperLineX1 = gfxX;
    upperLineX2 = gfxX + gfxWidth;
    lowerLineY = zeroLine2Y + scaleArea;
    lowerLineX1 = gfxX;
    lowerLineX2 = gfxX + gfxWidth;
    lowerBorderY = zeroLine2Y + gfxHeight / 2;
    remainingWidth = gfxWidth;
    widthOfElement = 18;
    remainingWidth -= numEntries * widthOfElement;
    spaceBetweenElements = remainingWidth / (numEntries + 1);
    roundList = [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 30, 40, 50, 60, 70, 80, 90, 100, 150, 200, 250, 500, 1000, 2000, 5000];
    maxValue = getVisualRound(getEntriesMax(entries), roundList);
    txtElement = [];
    txtNumber = [];
    i = 1;
    stepY = (zeroLine1Y - upperLineY) / maxValue;
    posY1 = zeroLine1Y;
    posY2 = zeroLine2Y;
    if (maxValue <= 10) {
      while (i < maxValue) {
        posY1 -= stepY;
        posY2 += stepY;
        drawLine(paper, zeroLineX1, posY1, zeroLineX2, posY1, "#e3dbde");
        drawLine(paper, zeroLineX1, posY2, zeroLineX2, posY2, "#e3dbde");
        i++;
      }
    }
    drawBorder(paper, zeroLineX1, zeroLine1Y, zeroLineX2 - zeroLineX1, zeroLine2Y - zeroLine1Y, false, "#f1ecee");
    drawLine(paper, zeroLineX1, zeroLine1Y, zeroLineX2, zeroLine1Y, "#a68597");
    drawLine(paper, zeroLineX1, zeroLine2Y, zeroLineX2, zeroLine2Y, "#a68597");
    drawLine(paper, upperLineX1, upperLineY, upperLineX2, upperLineY, "#a68597");
    drawLine(paper, lowerLineX1, lowerLineY, lowerLineX2, lowerLineY, "#a68597");
    drawLine(paper, upperLineX1, upperLineY / 2 + zeroLine1Y / 2, upperLineX2, upperLineY / 2 + zeroLine1Y / 2, "#a68597");
    drawLine(paper, lowerLineX1, lowerLineY / 2 + zeroLine2Y / 2, lowerLineX2, lowerLineY / 2 + zeroLine2Y / 2, "#a68597");
    drawLine(paper, upperLineX1, upperLineY, lowerLineX1, lowerLineY, "#a68597");
    drawLine(paper, upperLineX2, upperLineY, lowerLineX2, lowerLineY, "#a68597");
    fontType = "Tahoma, Verdana, Times, Arial";
    fontSize = 13;
    smallFontSize = 11;
    posX = zeroLineX1 + spaceBetweenElements;
    i = 0;
    while (i < numEntries) {
      difference = entries[i][1] - entries[i][2];
      drawLine(paper, posX + widthOfElement / 2, upperLineY, posX + widthOfElement / 2, lowerLineY + 10, "#a68597");
      if (entries[i][1] !== 0) {
        drawBorder(paper, posX, zeroLine1Y - scaleArea * entries[i][1] / maxValue, widthOfElement, scaleArea * entries[i][1] / maxValue - 1, false, "#784060");
      }
      if (entries[i][2] !== 0) {
        drawBorder(paper, posX, zeroLine2Y + 1, widthOfElement, scaleArea * entries[i][2] / maxValue - 1, false, "#784060");
      }
      color = "#a5a5a5";
      if (entries[i][1] - entries[i][2] > 0) {
        color = "#668d45";
      }
      if (entries[i][1] - entries[i][2] < 0) {
        color = "#d70043";
      }
      additionalWidth = 10;
      drawBorder(paper, posX - additionalWidth / 2, zeroLine1Y + 1, widthOfElement + additionalWidth, zeroLine2Y - zeroLine1Y - 2, false, color);
      text = entries[i][1] - entries[i][2];
      if (entries[i][1] > entries[i][2]) {
        text = "+" + text;
      }
      if (entries[i][1] === 0 && entries[i][2] === 0) {
        text = "?";
      }
      txtNumber[i] = paper.text(posX + widthOfElement / 2, zeroLine1Y / 2 + zeroLine2Y / 2 + 4, text);
      txtNumber[i].attr({
        'font-family': fontType,
        'font-size': smallFontSize,
        'text-anchor': 'center',
        'fill': '#ffffff'
      });
      txtElement[i] = paper.text(posX + widthOfElement / 2 + 5, lowerBorderY + 5, entries[i][0]);
      txtElement[i].rotate(-40, posX + widthOfElement / 2, lowerBorderY + 5);
      txtElement[i].attr({
        'font-family': fontType,
        'font-size': fontSize,
        'text-anchor': 'end',
        'fill': '#784060'
      });
      posX += widthOfElement + spaceBetweenElements;
      i++;
    }
    if (chartButtonTruePath) {
      chartButtonTrueImage = paper.image(chartButtonTruePath, offsetX, upperLineY - 1, 46, 106);
    }
    if (chartButtonNullPath) {
      chartButtonNullImage = paper.image(chartButtonNullPath, offsetX, zeroLine1Y / 2 + zeroLine2Y / 2 - 16 / 2, 46, 16);
    }
    if (chartButtonFalsePath) {
      chartButtonFalseImage = paper.image(chartButtonFalsePath, offsetX, lowerLineY - 106 + 1, 46, 106);
    }
    txtNumbers = [];
    txtNumbers[0] = paper.text(zeroLineX2 + 15, zeroLine1Y / 2 + zeroLine2Y / 2 + 4, "0");
    txtNumbers[0].attr({
      'font-family': fontType,
      'font-size': fontSize,
      'text-anchor': 'start',
      'fill': '#784060'
    });
    txtNumbers[1] = paper.text(zeroLineX2 + 7, upperLineY + 4, "+" + maxValue);
    txtNumbers[1].attr({
      'font-family': fontType,
      'font-size': fontSize,
      'text-anchor': 'start',
      'fill': '#784060'
    });
    txtNumbers[2] = paper.text(zeroLineX2 + 7, lowerLineY + 4, -maxValue);
    txtNumbers[2].attr({
      'font-family': fontType,
      'font-size': fontSize,
      'text-anchor': 'start',
      'fill': '#784060'
    });
    txtNumbers[3] = paper.text(zeroLineX2 + 7, upperLineY / 2 + zeroLine1Y / 2 + 4, "+" + maxValue / 2);
    txtNumbers[3].attr({
      'font-family': fontType,
      'font-size': fontSize,
      'text-anchor': 'start',
      'fill': '#784060'
    });
    txtNumbers[4] = paper.text(zeroLineX2 + 7, lowerLineY / 2 + zeroLine2Y / 2 + 4, -maxValue / 2);
    txtNumbers[4].attr({
      'font-family': fontType,
      'font-size': fontSize,
      'text-anchor': 'start',
      'fill': '#784060'
    });
    return paper.safari();
  };
}).call(this);
App.facebook = {};

App.facebook.init = function(options) {
  FB.init({
    appId: options.appID,
    status: true,
    cookie: true,
    xfbml: true
  });

  FB.getLoginStatus(App.facebook.updateFacebookToken);
  FB.Event.subscribe('auth.login', App.facebook.updateFacebookToken);
  FB.Event.subscribe('auth.authResponseChange', App.facebook.updateFacebookToken);
}

App.facebook.updateFacebookToken = function(response) {
  if(response.status == 'connected') {
    var facebookData = response.authResponse
    var data = '_method=put&uid=' + facebookData.userID  + '&access_token=' + facebookData.accessToken

    $.post('/facebook_token', data, function(data, textStatus, jqXHR) {
      // currently noop
    })
  }
}

App.facebook.filterCriteria = {
  name: null,
  single: null,
  sex: null
}

App.facebook.friendSelector = (function(app, $) {

  var self = null,
  friends = null,
  counter = 0,
  disabledFriends = null,
  multipleSelect = null,
  filterCriteria = null,
  filterTimeout = null,
  FRIEND_NORMAL = "friend-normal",
  FRIEND_SELECTED = "friend-selected",
  FRIEND_DISABLED = "friend-disabled",

  init = function(options) {
    self = app.facebook.friendSelector;
    friends = options.friends;
    counter = options.counter;
    //console.log("Friends Array", options.disabledFriends);
    disabledFriends = options.disabledFriends || [];
    multipleSelect = options.multipleSelect;

    filterCriteria = app.facebook.filterCriteria;
    //app.image().init({el: $(".fb-friend img")}); //performance!
    selectAllButton = $("#fb-select-all");
    if (!multipleSelect) {
      selectAllButton.hide();
    }

    setDisabledFriends();
    initEvents();
  },

  setDisabledFriends = function() {
    for (var i = 0, max = disabledFriends.length; i < max; i++) {
      $("#" + disabledFriends[i])
        .removeClass(FRIEND_NORMAL)
        .addClass(FRIEND_DISABLED);
    }
  },

  initEvents = function() {
    $("#fb-friends-search").keyup(onFilterKeyUp);
    $('a[data-action=clearSearch]').click(onClearSearchClicked);
    $("#fb-friends-relationship-status").change(onRelationShipStatusChanged);
    $("#fb-friends-sex").change(onSexChanged);
    $("#fb-select-all").click(onSelectAllClick);
    $(".friendsSelectBox").delegate("ul li", "click", onFriendClick);
  },
  
  onClearSearchClicked = function(ev) {
    ev.preventDefault();
    $('#fb-friends-search').val("");
    onFilterKeyUp(ev);
  },

  onFilterKeyUp = function(ev) {
    filterCriteria.name = $(ev.currentTarget).val();
    updateFilter();
  },

  onRelationShipStatusChanged = function(ev) {
    filterCriteria.single = $(ev.currentTarget).is(":checked") ? true : null;
    updateFilter(); 
  },

  onSexChanged = function(ev) {
    var val = $(ev.currentTarget).val();
    filterCriteria.sex = val == "all" ? null : val;
    updateFilter();
  },

  onSelectAllClick = function(ev) {
    ev.preventDefault();

    var el = $(ev.currentTarget);
    var selected = el.data("selected");

    if (selected) {
      var friendNodes = $(".fb-friend.friend-selected");
      deselectFriend(friendNodes);
    } else {
      var selectedCount = $(".fb-friend.friend-selected").length;
      var friendNodes = $(".fb-friend.friend-normal:visible:lt("+ (30 - (counter + selectedCount)) +")");
      selectFriend(friendNodes);
    }
    setSelectAllButton(!selected);    
    triggerSelectionChangedEvent();
  },

  setSelectAllButton = function(selected) {
    selectAllButton.html(selected ? "Keine auswählen" : "Automatisch auswählen");
    selectAllButton.data("selected", selected);
  },

  onFriendClick = function(ev) {
    var el = $(ev.currentTarget);
    if (isFriendDisabled(el)) {
      return;
    }
    if (multipleSelect) {      
      toggleSelectedFriend(el);
      triggerSelectionChangedEvent();
    } else {
      deselectFriend($("." + FRIEND_SELECTED));
      selectFriend(el); 
    }
  },

  triggerSelectionChangedEvent = function() {
    $(self).trigger("selectionChanged", {selectedFriends: getSelectedFriends()});
  },

  isFriendDisabled = function(el) {
    return el.hasClass(FRIEND_DISABLED);
  },

  selectFriend = function(el) {
    el.removeClass(FRIEND_NORMAL);
    enabledElements(el).addClass(FRIEND_SELECTED);
  },

  deselectFriend = function(el) {
    enabledElements(el).removeClass(FRIEND_SELECTED);
    enabledElements(el).addClass(FRIEND_NORMAL);
  },

  enabledElements = function(el) {
    return el.not("." + FRIEND_DISABLED).not(":hidden");
  },

  toggleSelectedFriend = function(el) {
    if (el.hasClass(FRIEND_NORMAL)) {
      if($('.' + FRIEND_SELECTED).size() < 30) {
        selectFriend(el);
      }
    } else if (el.hasClass(FRIEND_SELECTED)) {
      deselectFriend(el);
    }
  },

  updateFilter = function() {
    clearTimeout(filterTimeout);
    filterTimeout = setTimeout($.proxy(showFilter, this), 250);
  },

  showFilter = function() {
    var friend  = null;
    for (var i = 0, max = friends.length; i < max; i++) {
      friend = friends[i];
      if (friendMatchesFilterCriteria(friend)) {
        $("#" + friend.uid).show();
      } else {
        $("#" + friend.uid).hide();
      }
    }
  },

  friendMatchesFilterCriteria = function(friend) {
    var matchesName = filterCriteria.name == null || (friend.name.toLowerCase().indexOf(filterCriteria.name.toLowerCase()) != -1),
    matchesSingle = filterCriteria.single == null || (filterCriteria.single && friend.relationship_status == "Single"),
    matchesSex = filterCriteria.sex == null || (filterCriteria.sex == friend.sex);

    return matchesName && matchesSingle && matchesSex;
  },

  getSelectedFriends = function() {
    var selectedFriends = [];
    $("." + FRIEND_SELECTED).each(function(index, el) {
      selectedFriends.push(el.id);
    });
    return selectedFriends;
  };

  return {
    init: init,
    getSelectedFriends: getSelectedFriends
  }

}(App, jQuery));
(function() {
  this.App.createHeart = function(paper, position, element) {
    var path;
    if (position === 0) {
      if (element === 0) {
        path = paper.path("M499.996,324.274c11.559-17.623,4.003-26.847,4.646-39.447      c0.645-12.599,6.35-31.428,41.15-34.051c22.147-1.667,42.293-21.475,42.93-48.081c0.672-28.288-22.224-51.549-50.519-51.944      c-15.191-0.212-28.684,4.834-38.208,15.205c-9.526-10.371-23.021-15.417-38.21-15.205c-28.294,0.395-51.191,23.656-50.519,51.944      c0.638,26.606,20.781,46.414,42.927,48.081c34.802,2.623,40.511,21.452,41.154,34.051      C495.992,297.427,488.435,306.651,499.996,324.274");
      }
      if (element === 1) {
        path = paper.path("M499.977,383.748c8.002-12.201,2.772-18.589,3.218-27.312      c0.445-8.725,4.396-21.762,28.493-23.577c15.333-1.157,29.282-14.87,29.723-33.292c0.465-19.588-15.387-35.693-34.977-35.967      c-10.521-0.147-19.863,3.347-26.458,10.529c-6.597-7.182-15.94-10.676-26.458-10.529c-19.587,0.274-35.442,16.379-34.977,35.967      c0.441,18.422,14.39,32.135,29.721,33.292c24.098,1.815,28.05,14.852,28.495,23.577      C497.205,365.159,491.974,371.547,499.977,383.748");
      }
      if (element === 2) {
        path = paper.path("M500.023,419.529c4.958-7.559,1.717-11.517,1.994-16.921      c0.276-5.403,2.725-13.48,17.649-14.606c9.499-0.714,18.141-9.211,18.414-20.622c0.289-12.135-9.533-22.112-21.668-22.282      c-6.518-0.09-12.306,2.074-16.389,6.522c-4.086-4.448-9.875-6.612-16.39-6.522c-12.135,0.17-21.957,10.147-21.669,22.282      c0.274,11.411,8.914,19.908,18.412,20.622c14.928,1.126,17.376,9.203,17.652,14.606      C498.307,408.012,495.064,411.97,500.023,419.529");
      }
      if (element === 3) {
        path = paper.path("M499.993,454.052c3.699-5.638,1.282-8.589,1.488-12.62      c0.205-4.03,2.032-10.053,13.164-10.892c7.084-0.533,13.53-6.87,13.732-15.381c0.215-9.05-7.109-16.491-16.161-16.617      c-4.859-0.069-9.175,1.546-12.223,4.864c-3.048-3.318-7.365-4.933-12.223-4.864c-9.051,0.126-16.377,7.567-16.162,16.617      c0.204,8.511,6.649,14.848,13.733,15.381c11.133,0.839,12.959,6.862,13.165,10.892      C498.712,445.463,496.294,448.414,499.993,454.052");
      }
      if (element === 4) {
        path = paper.path("M491.197,458.95c5.415,1.021,7.854,4.535,7.854,6.89      c0,2.325-0.74,4.669-2.324,6.33c1.068-0.111,2.152,0.83,3.25,0.83c1.112,0,2.21-0.938,3.292-0.824      c-1.587-1.662-2.328-4.008-2.328-6.336c0-2.354,2.438-5.868,7.851-6.89c4.282-0.806,8.101-4.297,8.225-9.48      c0.131-5.51-4.238-9.673-9.751-9.751c-2.96-0.04-5.413,1.241-7.27,3.262c-1.857-2.021-4.31-3.302-7.27-3.262      c-5.513,0.078-9.883,4.241-9.749,9.751C483.1,454.653,486.916,458.145,491.197,458.95z");
      }
    }
    if (position === 1) {
      if (element === 0) {
        path = paper.path("M614.975,366.127c20.182-6.068,20.324-17.992,28.917-27.229      c8.595-9.236,25.067-19.993,53.412,0.371c18.035,12.958,46.201,10.736,63.79-9.233c18.7-21.239,16.113-53.775-5.307-72.267      c-11.498-9.928-25.077-14.735-39.041-12.913c-0.629-14.069-7.722-26.608-19.493-36.211c-21.927-17.884-54.419-14.787-72.091,7.315      c-16.615,20.789-13.916,48.912,1.975,64.425c24.974,24.381,17.242,42.474,9.635,52.538      C629.167,342.989,617.448,345.198,614.975,366.127");
      }
      if (element === 1) {
        path = paper.path("M576.729,411.673c13.971-4.202,14.07-12.458,20.021-18.853      c5.949-6.396,17.357-13.844,36.982,0.255c12.487,8.973,31.989,7.436,44.169-6.392c12.947-14.706,11.158-37.233-3.675-50.037      c-7.961-6.875-17.362-10.204-27.031-8.942c-0.436-9.741-5.348-18.424-13.498-25.073c-15.184-12.383-37.68-10.238-49.914,5.066      c-11.506,14.394-9.638,33.866,1.365,44.607c17.291,16.882,11.938,29.41,6.671,36.378      C586.555,395.651,578.44,397.181,576.729,411.673");
      }
      if (element === 2) {
        path = paper.path("M553.762,439.108c8.656-2.602,8.718-7.716,12.403-11.679      c3.687-3.961,10.753-8.575,22.909,0.16c7.738,5.557,19.818,4.605,27.363-3.961c8.021-9.109,6.913-23.066-2.277-30.998      c-4.932-4.257-10.757-6.319-16.745-5.539c-0.271-6.034-3.313-11.412-8.362-15.531c-9.403-7.671-23.341-6.343-30.92,3.137      c-7.128,8.917-5.971,20.98,0.845,27.635c10.712,10.457,7.396,18.217,4.135,22.535C559.851,429.186,554.824,430.131,553.762,439.108");
      }
      if (element === 3) {
        path = paper.path("M531.547,465.536c6.455-1.941,6.501-5.757,9.25-8.711      c2.749-2.955,8.02-6.395,17.087,0.118c5.767,4.146,14.779,3.435,20.405-2.955c5.984-6.793,5.155-17.201-1.697-23.116      c-3.68-3.176-8.022-4.715-12.488-4.132c-0.203-4.501-2.471-8.512-6.236-11.582c-7.014-5.723-17.409-4.732-23.061,2.337      c-5.317,6.652-4.453,15.648,0.631,20.611c7.988,7.8,5.514,13.587,3.08,16.807C536.086,458.134,532.338,458.84,531.547,465.536");
      }
      if (element === 4) {
        path = paper.path("M523.241,473.958c-1.507,1.795-3.601,3.119-5.902,3.358      c1.38,1.56,3.333,3.044,5.074,4.306c-0.182-2.326,0.76-4.639,2.278-6.448c1.515-1.805,5.639-2.931,10.441-0.23      c3.802,2.135,8.968,1.912,12.393-1.978c3.644-4.138,2.973-10.134-1.2-13.736c-2.239-1.935-4.945-2.531-7.667-2.176      c-0.122-2.739-1.178-5.299-3.473-7.17c-4.271-3.483-10.292-3.103-13.735,1.203c-3.235,4.05-2.557,9.177,0.204,12.547      C525.148,467.895,524.755,472.152,523.241,473.958z");
      }
    }
    if (position === 2) {
      if (element === 0) {
        path = paper.path("M676.142,472.1c19.361,8.325,27.136-0.717,39.655-2.269      c12.521-1.551,32.056,0.8,40.677,34.621c5.484,21.517,28.488,37.923,54.8,33.936c27.976-4.25,46.911-30.834,42.391-58.769      c-2.429-14.998-9.738-27.41-21.604-34.99c8.562-11.18,11.188-25.345,8.345-40.268c-5.299-27.795-32.18-46.31-59.924-40.739      c-26.092,5.244-42.102,28.521-39.902,50.618c3.456,34.73-14.098,43.619-26.393,46.439      C701.889,463.498,691.493,457.657,676.142,472.1");
      }
      if (element === 1) {
        path = paper.path("M617.567,482.401c13.407,5.764,18.79-0.496,27.456-1.571      c8.67-1.075,22.195,0.553,28.166,23.97c3.797,14.9,19.725,26.26,37.941,23.497c19.373-2.942,32.482-21.351,29.353-40.692      c-1.681-10.384-6.741-18.976-14.96-24.225c5.929-7.743,7.747-17.551,5.778-27.882c-3.668-19.246-22.28-32.065-41.491-28.208      c-18.066,3.629-29.15,19.747-27.626,35.048c2.392,24.046-9.763,30.202-18.278,32.154      C635.396,476.445,628.196,472.401,617.567,482.401");
      }
      if (element === 2) {
        path = paper.path("M582.339,488.653c8.305,3.571,11.638-0.306,17.009-0.974      c5.371-0.664,13.75,0.346,17.447,14.853c2.354,9.229,12.22,16.266,23.505,14.554c12-1.823,20.122-13.226,18.185-25.207      c-1.043-6.433-4.179-11.757-9.268-15.008c3.672-4.797,4.798-10.872,3.578-17.273c-2.271-11.923-13.802-19.864-25.702-17.473      c-11.192,2.248-18.06,12.232-17.115,21.711c1.483,14.896-6.048,18.709-11.322,19.919      C593.382,484.965,588.923,482.459,582.339,488.653");
      }
      if (element === 3) {
        path = paper.path("M548.333,494.615c6.195,2.664,8.681-0.228,12.686-0.725      c4.007-0.496,10.254,0.256,13.014,11.075c1.755,6.884,9.114,12.133,17.529,10.854c8.948-1.357,15.008-9.863,13.562-18.799      c-0.776-4.798-3.116-8.767-6.911-11.193c2.737-3.576,3.579-8.108,2.67-12.882c-1.695-8.892-10.295-14.814-19.171-13.032      c-8.345,1.677-13.47,9.123-12.764,16.192c1.104,11.111-4.512,13.954-8.445,14.856      C556.569,491.863,553.244,489.994,548.333,494.615");
      }
      if (element === 4) {
        path = paper.path("M563.707,499.281c-0.473-2.923-2.163-5.118-4.474-6.594      c1.666-2.178,2.502-4.818,1.949-7.726c-1.032-5.416-5.892-8.995-11.298-7.908c-5.08,1.023-7.855,5.384-7.905,9.743      c-0.065,5.51-3.102,8.521-5.423,8.929c-2.354,0.415-4.859,0.059-6.792-1.303c0.126,2.265,0.563,4.625,1.154,6.758      c1.348-1.967,3.595-3.174,5.965-3.591c2.321-0.411,6.204,1.379,8.15,6.534c1.538,4.078,5.637,7.228,10.764,6.45      C561.247,509.745,564.587,504.722,563.707,499.281z");
      }
    }
    if (position === 3) {
      if (element === 0) {
        path = paper.path("M654.875,592.597c9.479,18.822,21.247,16.892,31.833,23.752      c10.589,6.86,24.041,21.218,8.904,52.666c-9.634,20.012-2.559,47.363,20.162,61.224c24.16,14.727,55.756,6.537,70.247-17.769      c7.783-13.047,10.163-27.254,5.945-40.688c13.748-3.062,24.864-12.223,32.278-25.481c13.809-24.697,5.12-56.159-19.712-69.726      c-23.359-12.758-50.584-5.221-63.105,13.121c-19.678,28.824-38.838,24.352-50.07,18.604      C680.124,602.56,675.919,591.399,654.875,592.597");
      }
      if (element === 1) {
        path = paper.path("M603.384,562.831c6.564,13.034,14.711,11.699,22.042,16.447      c7.33,4.753,16.646,14.694,6.165,36.468c-6.67,13.855-1.771,32.793,13.962,42.39c16.727,10.198,38.604,4.528,48.64-12.303      c5.387-9.033,7.035-18.869,4.115-28.171c9.518-2.121,17.216-8.464,22.349-17.646c9.562-17.1,3.546-38.884-13.648-48.276      c-16.173-8.833-35.023-3.613-43.695,9.085c-13.624,19.96-26.891,16.861-34.668,12.883      C620.868,569.729,617.955,562.006,603.384,562.831");
      }
      if (element === 2) {
        path = paper.path("M572.38,544.977c4.064,8.073,9.111,7.246,13.653,10.188      c4.542,2.943,10.311,9.102,3.819,22.59c-4.132,8.582-1.099,20.315,8.647,26.26c10.364,6.32,23.915,2.805,30.133-7.62      c3.339-5.596,4.357-11.688,2.551-17.455c5.895-1.31,10.664-5.24,13.844-10.929c5.924-10.591,2.196-24.087-8.455-29.907      c-10.018-5.473-21.697-2.238-27.068,5.63c-8.44,12.363-16.658,10.444-21.475,7.979C583.209,549.249,581.403,544.464,572.38,544.977");
      }
      if (element === 3) {
        path = paper.path("M542.499,527.682c3.032,6.023,6.797,5.405,10.184,7.6      c3.386,2.193,7.69,6.787,2.847,16.849c-3.08,6.401-0.816,15.149,6.451,19.583c7.729,4.714,17.836,2.092,22.473-5.684      c2.49-4.173,3.252-8.717,1.9-13.014c4.397-0.98,7.956-3.91,10.327-8.153c4.418-7.9,1.637-17.964-6.306-22.306      c-7.473-4.081-16.184-1.67-20.188,4.197c-6.296,9.222-12.424,7.79-16.018,5.954C550.577,530.868,549.229,527.301,542.499,527.682");
      }
      if (element === 4) {
        path = paper.path("M554.979,515.224c-4.552-2.483-9.483-0.925-12.323,2.381      c-3.591,4.179-7.85,4.534-9.894,3.354c-2.111-1.219-3.825-3.155-4.397-5.504c-1.459,1.812-2.74,3.921-3.551,6.098      c2.33-0.695,4.88-0.179,7.004,1.046c2.039,1.178,3.864,5.043,2.04,10.244c-1.44,4.112-0.327,9.163,4.099,11.86      c4.709,2.868,10.498,1.167,13.322-3.568c1.515-2.543,1.632-5.308,0.809-7.927c2.678-0.595,5.015-2.08,6.46-4.663      C561.235,523.73,559.815,517.865,554.979,515.224z");
      }
    }
    if (position === 4) {
      if (element === 0) {
        path = paper.path("M561.125,671.224c-4.838,20.513,5.415,26.6,9.114,38.66      c3.7,12.063,4.776,31.706-27.036,46.066c-20.24,9.136-32.404,34.635-23.91,59.856c9.039,26.814,38.504,40.85,65.231,31.551      c14.35-4.993,25.302-14.346,30.709-27.349c12.499,6.491,26.905,6.621,41.107,1.23c26.452-10.042,40.023-39.727,29.722-66.08      c-9.69-24.79-35.392-36.518-56.774-30.515c-33.603,9.429-45.403-6.317-50.314-17.938      C574.063,695.089,578.011,683.836,561.125,671.224");
      }
      if (element === 1) {
        path = paper.path("M540.816,615.325c-3.354,14.202,3.75,18.418,6.311,26.769      c2.562,8.352,3.308,21.953-18.719,31.896c-14.016,6.325-22.438,23.981-16.557,41.443c6.259,18.566,26.66,28.285,45.165,21.848      c9.938-3.459,17.522-9.934,21.264-18.938c8.654,4.494,18.63,4.587,28.464,0.854c18.316-6.955,27.71-27.507,20.578-45.757      c-6.709-17.16-24.506-25.282-39.309-21.128c-23.267,6.528-31.439-4.37-34.838-12.417      C549.773,631.849,552.508,624.059,540.816,615.325");
      }
      if (element === 2) {
        path = paper.path("M528.544,581.715c-2.074,8.799,2.323,11.409,3.91,16.584      c1.587,5.174,2.049,13.599-11.598,19.757c-8.681,3.92-13.898,14.858-10.253,25.676c3.875,11.504,16.514,17.521,27.979,13.535      c6.155-2.144,10.854-6.155,13.172-11.731c5.359,2.783,11.54,2.84,17.632,0.527c11.346-4.307,17.168-17.041,12.749-28.344      c-4.157-10.633-15.181-15.664-24.354-13.091c-14.414,4.047-19.475-2.708-21.579-7.691      C534.093,591.951,535.789,587.125,528.544,581.715");
      }
      if (element === 3) {
        path = paper.path("M516.771,549.262c-1.546,6.562,1.733,8.508,2.917,12.365      c1.183,3.86,1.526,10.145-8.647,14.738c-6.478,2.923-10.368,11.08-7.65,19.148c2.891,8.577,12.32,13.068,20.869,10.093      c4.59-1.597,8.095-4.588,9.822-8.748c3.998,2.076,8.605,2.117,13.148,0.392c8.465-3.209,12.805-12.708,9.511-21.139      c-3.101-7.929-11.323-11.68-18.163-9.761c-10.749,3.018-14.523-2.021-16.095-5.739      C520.91,556.896,522.175,553.295,516.771,549.262");
      }
      if (element === 4) {
        path = paper.path("M523.374,541.641c-5.437,0.895-8.931-1.574-9.736-3.788      c-0.845-2.322-0.905-4.947,0.211-7.131c-2.192,0.56-4.521,1.372-6.744,2.445c2.265,0.953,3.909,3.006,4.756,5.331      c0.806,2.217-0.282,6.35-5.021,9.161c-3.749,2.223-6.141,6.809-4.483,11.721c1.762,5.223,7.291,7.64,12.497,5.826      c2.796-0.971,4.663-3.016,5.714-5.55c2.436,1.265,5.18,1.627,7.948,0.577c5.153-1.955,7.836-7.36,5.826-12.495      C532.453,542.907,527.675,540.935,523.374,541.641z");
      }
    }
    if (position === 5) {
      if (element === 0) {
        path = paper.path("M438.767,671.189c-16.894,12.601-12.951,23.855-17.87,35.47      c-4.921,11.62-16.726,27.358-50.323,17.909c-21.376-6.013-47.088,5.699-56.794,30.479c-10.313,26.35,3.237,56.042,29.686,66.101      c14.201,5.398,28.604,5.278,41.104-1.208c5.402,13.007,16.353,22.368,30.696,27.367c26.72,9.314,56.196-4.701,65.249-31.514      c8.509-25.215-3.639-50.722-23.873-59.868c-31.802-14.379-30.723-34.023-27.013-46.083      C433.336,697.786,443.595,691.705,438.767,671.189");
      }
      if (element === 1) {
        path = paper.path("M459.142,615.313c-11.696,8.726-8.966,16.521-12.371,24.563      c-3.406,8.042-11.582,18.94-34.844,12.396c-14.803-4.164-32.605,3.948-39.324,21.106c-7.143,18.245,2.241,38.804,20.555,45.767      c9.831,3.74,19.804,3.654,28.459-0.835c3.741,9.006,11.323,15.485,21.255,18.948c18.499,6.45,38.911-3.257,45.179-21.821      c5.892-17.457-2.521-35.12-16.53-41.453c-22.02-9.954-21.271-23.557-18.704-31.906C455.384,633.729,462.488,629.52,459.142,615.313");
      }
      if (element === 2) {
        path = paper.path("M471.349,581.681c-7.246,5.405-5.555,10.232-7.665,15.217      c-2.11,4.981-7.174,11.733-21.585,7.677c-9.168-2.576-20.197,2.446-24.359,13.078c-4.425,11.302,1.385,24.036,12.733,28.352      c6.091,2.315,12.269,2.262,17.631-0.518c2.315,5.577,7.014,9.595,13.166,11.738c11.461,3.994,24.104-2.019,27.987-13.518      c3.649-10.817-1.563-21.755-10.241-25.682c-13.641-6.164-13.176-14.594-11.586-19.766      C469.02,593.089,473.42,590.479,471.349,581.681");
      }
      if (element === 3) {
        path = paper.path("M483.196,549.254c-5.405,4.03-4.143,7.632-5.718,11.348      c-1.572,3.715-5.35,8.752-16.098,5.728c-6.84-1.924-15.063,1.824-18.166,9.751c-3.303,8.431,1.032,17.928,9.495,21.146      c4.541,1.726,9.15,1.689,13.15-0.387c1.728,4.161,5.229,7.156,9.819,8.755c8.547,2.979,17.977-1.506,20.872-10.08      c2.724-8.066-1.163-16.228-7.638-19.153c-10.173-4.6-9.825-10.883-8.638-14.741C481.459,557.76,484.74,555.814,483.196,549.254");
      }
      if (element === 4) {
        path = paper.path("M493.15,547.659c-4.737-2.81-5.826-6.944-5.019-9.161    c0.844-2.32,2.483-4.369,4.742-5.325c-2.357-1.079-4.482-1.798-6.718-2.426c1.103,2.18,1.04,4.792,0.198,7.105    c-0.805,2.212-4.298,4.683-9.737,3.788c-4.298-0.706-9.076,1.27-10.966,6.098c-2.007,5.136,0.674,10.54,5.826,12.497    c2.77,1.05,5.513,0.686,7.948-0.579c1.053,2.536,2.919,4.579,5.715,5.552c5.204,1.812,10.735-0.605,12.496-5.828    C499.292,554.468,496.9,549.882,493.15,547.659z");
      }
    }
    if (position === 6) {
      if (element === 0) {
        path = paper.path("M345.063,592.504c-21.041-1.206-25.257,9.948-36.493,15.686      c-11.236,5.735-30.395,10.203-50.058-18.633c-12.51-18.35-39.732-25.903-63.096-13.161c-24.842,13.552-33.549,45.009-19.755,69.716      c7.407,13.265,18.521,22.428,32.261,25.498c-4.221,13.436-1.851,27.646,5.922,40.696c14.48,24.312,46.069,32.522,70.238,17.805      c22.728-13.845,29.819-41.191,20.201-61.206c-15.118-31.457-1.662-45.81,8.932-52.663      C323.808,609.388,335.574,611.324,345.063,592.504");
      }
      if (element === 1) {
        path = paper.path("M396.589,562.804c-14.569-0.835-17.488,6.887-25.266,10.859      c-7.78,3.973-21.048,7.065-34.661-12.9c-8.663-12.705-27.511-17.938-43.689-9.114c-17.2,9.386-23.23,31.167-13.676,48.272      c5.127,9.185,12.821,15.531,22.337,17.655c-2.925,9.302-1.281,19.142,4.101,28.179c10.025,16.832,31.897,22.52,48.631,12.327      c15.738-9.585,20.648-28.521,13.987-42.38c-10.468-21.782-1.149-31.719,6.186-36.465      C381.872,574.495,390.019,575.833,396.589,562.804");
      }
      if (element === 2) {
        path = paper.path("M427.561,544.887c-9.025-0.519-10.835,4.267-15.653,6.726      c-4.82,2.461-13.039,4.377-21.472-7.991c-5.365-7.87-17.042-11.108-27.064-5.645c-10.656,5.812-14.39,19.307-8.475,29.903      c3.178,5.688,7.946,9.619,13.841,10.938c-1.813,5.761-0.796,11.855,2.538,17.455c6.212,10.427,19.76,13.95,30.129,7.638      c9.747-5.938,12.788-17.667,8.662-26.252c-6.484-13.495-0.712-19.652,3.834-22.592C418.441,552.127,423.49,552.958,427.561,544.887");
      }
      if (element === 3) {
        path = paper.path("M457.479,527.66c-6.729-0.386-8.08,3.183-11.672,5.021      c-3.595,1.833-9.724,3.265-16.015-5.963c-4.001-5.87-12.709-8.286-20.184-4.207c-7.946,4.335-10.733,14.397-6.32,22.3      c2.369,4.246,5.925,7.176,10.321,8.157c-1.352,4.297-0.593,8.845,1.893,13.018c4.632,7.779,14.74,10.405,22.47,5.697      c7.271-4.431,9.54-13.179,6.463-19.582c-4.838-10.062-0.531-14.653,2.856-16.846C450.68,533.061,454.445,533.683,457.479,527.66");
      }
      if (element === 4) {
        path = paper.path("M466.133,532.842c-1.825-5.2,0-9.066,2.041-10.243    c2.108-1.217,4.637-1.734,6.954-1.062c-0.815-2.068-2.112-4.146-3.516-6.029c-0.585,2.325-2.289,4.241-4.383,5.452    c-2.042,1.179-6.304,0.826-9.895-3.355c-2.839-3.303-7.771-4.862-12.32-2.381c-4.839,2.643-6.258,8.507-3.572,13.322    c1.446,2.582,3.784,4.067,6.459,4.663c-0.82,2.62-0.704,5.383,0.812,7.927c2.821,4.735,8.612,6.436,13.32,3.566    C466.46,542.006,467.573,536.954,466.133,532.842z");
      }
    }
    if (position === 7) {
      if (element === 0) {
        path = paper.path("M323.865,471.995c-15.34-14.45-25.739-8.614-38.035-11.442      c-12.293-2.829-29.843-11.724-26.366-46.454c2.213-22.096-13.783-45.383-39.873-50.643c-27.739-5.585-54.631,12.911-59.946,40.706      c-2.853,14.921-0.234,29.085,8.321,40.27c-11.871,7.577-19.189,19.986-21.624,34.979c-4.539,27.932,14.382,54.528,42.356,58.79      c26.309,4.007,49.321-12.383,54.819-33.898c8.64-33.815,28.177-36.159,40.697-34.598      C296.733,471.263,304.5,480.311,323.865,471.995");
      }
      if (element === 1) {
        path = paper.path("M382.429,482.368c-10.623-10.005-17.822-5.965-26.336-7.923      c-8.514-1.959-20.664-8.119-18.257-32.164c1.533-15.3-9.544-31.424-27.608-35.065c-19.207-3.869-37.827,8.939-41.507,28.184      c-1.977,10.332-0.161,20.139,5.763,27.883c-8.221,5.245-13.289,13.838-14.975,24.221c-3.141,19.337,9.959,37.753,29.329,40.705      c18.216,2.775,34.15-8.576,37.955-23.472c5.986-23.413,19.512-25.035,28.18-23.955C363.64,481.86,369.019,488.126,382.429,482.368");
      }
      if (element === 2) {
        path = paper.path("M417.67,488.553c-6.581-6.198-11.042-3.695-16.314-4.909      c-5.273-1.214-12.802-5.029-11.311-19.925c0.95-9.479-5.911-19.467-17.103-21.721c-11.898-2.397-23.434,5.536-25.711,17.459      c-1.224,6.4-0.101,12.476,3.568,17.273c-5.091,3.25-8.23,8.572-9.275,15.003c-1.946,11.981,6.169,23.39,18.168,25.218      c11.284,1.717,21.155-5.313,23.514-14.541c3.705-14.503,12.086-15.509,17.457-14.84      C406.031,488.239,409.364,492.118,417.67,488.553");
      }
      if (element === 3) {
        path = paper.path("M451.661,494.593c-4.907-4.624-8.233-2.758-12.167-3.661      c-3.933-0.906-9.547-3.751-8.436-14.861c0.709-7.069-4.409-14.519-12.753-16.201c-8.875-1.787-17.478,4.13-19.179,13.022      c-0.912,4.773-0.074,9.305,2.662,12.883c-3.796,2.422-6.139,6.394-6.917,11.189c-1.452,8.936,4.602,17.444,13.549,18.807      c8.418,1.283,15.778-3.961,17.537-10.845c2.765-10.816,9.013-11.565,13.019-11.065      C442.982,494.359,445.465,497.252,451.661,494.593");
      }
      if (element === 4) {
        path = paper.path("M454.957,504.123c1.946-5.154,5.83-6.942,8.15-6.534      c2.35,0.414,4.579,1.604,5.931,3.541c0.878-2.296,1.14-4.463,1.14-6.671c-1.926,1.333-4.409,1.678-6.743,1.267      c-2.321-0.408-5.358-3.416-5.424-8.929c-0.048-4.358-2.826-8.719-7.907-9.742c-5.405-1.086-10.261,2.493-11.294,7.908      c-0.555,2.908,0.282,5.548,1.948,7.727c-2.313,1.477-4,3.669-4.474,6.593c-0.88,5.439,2.46,10.463,7.911,11.293      C449.318,511.354,453.418,508.201,454.957,504.123z");
      }
    }
    if (position === 8) {
      if (element === 0) {
        path = paper.path("M384.239,365.195c-2.463-20.93-14.18-23.145-21.782-33.213      c-7.599-10.069-15.325-28.164,9.663-52.534c15.898-15.505,18.613-43.625,2.008-64.425c-17.66-22.109-50.149-25.226-72.087-7.35      c-11.776,9.596-18.875,22.13-19.511,36.197c-13.964-1.826-27.546,2.975-39.049,12.896c-21.431,18.479-24.033,51.016-5.343,72.261      c17.578,19.98,45.742,22.218,63.783,9.27c28.355-20.351,44.827-9.587,53.415-0.344      C363.925,347.195,364.059,359.119,384.239,365.195");
      }
      if (element === 1) {
        path = paper.path("M422.434,410.786c-1.707-14.493-9.818-16.024-15.082-22.997      c-5.263-6.975-10.611-19.503,6.689-36.375c11.008-10.734,12.887-30.207,1.39-44.607c-12.226-15.311-34.723-17.467-49.912-5.09      c-8.156,6.644-13.068,15.324-13.508,25.063c-9.669-1.267-19.074,2.059-27.04,8.929c-14.836,12.795-16.639,35.322-3.697,50.033      c12.17,13.836,31.673,15.383,44.162,6.418c19.636-14.088,31.04-6.637,36.985-0.237C408.367,398.32,408.46,406.577,422.434,410.786");
      }
      if (element === 2) {
        path = paper.path("M445.455,438.176c-1.057-8.979-6.083-9.928-9.342-14.246      c-3.259-4.32-6.575-12.082,4.143-22.535c6.82-6.65,7.985-18.711,0.86-27.633c-7.573-9.484-21.51-10.822-30.918-3.152      c-5.052,4.117-8.097,9.492-8.37,15.525c-5.989-0.783-11.815,1.277-16.749,5.531c-9.192,7.928-10.309,21.883-2.292,30.997      c7.541,8.568,19.621,9.528,27.359,3.976c12.161-8.729,19.228-4.112,22.913-0.147C436.74,430.454,436.8,435.568,445.455,438.176");
      }
      if (element === 3) {
        path = paper.path("M467.611,464.652c-0.787-6.697-4.534-7.404-6.967-10.625      c-2.431-3.223-4.902-9.011,3.09-16.807c5.087-4.96,5.956-13.957,0.645-20.609c-5.65-7.072-16.044-8.07-23.063-2.353      c-3.767,3.071-6.037,7.081-6.241,11.581c-4.465-0.585-8.813,0.951-12.491,4.125c-6.856,5.911-7.688,16.32-1.71,23.115      c5.624,6.395,14.633,7.107,20.406,2.965c9.07-6.508,14.338-3.064,17.085-0.107C461.112,458.895,461.155,462.706,467.611,464.652");
      }
      if (element === 4) {
        path = paper.path("M464.855,474.943c4.804-2.699,8.929-1.575,10.446,0.23      c1.506,1.797,2.447,4.093,2.281,6.404c1.834-1.077,3.626-2.161,5.034-4.263c-2.288-0.249-4.369-1.57-5.867-3.356      c-1.514-1.805-1.908-6.062,1.586-10.326c2.761-3.369,3.439-8.498,0.204-12.546c-3.444-4.306-9.464-4.685-13.738-1.202      c-2.292,1.87-3.35,4.43-3.471,7.17c-2.722-0.355-5.426,0.241-7.667,2.176c-4.172,3.602-4.843,9.599-1.199,13.736      C455.89,476.857,461.057,477.078,464.855,474.943z");
      }
    }
    return path;
  };
  this.App.createBorderArrow = function(paper, position) {
    var path;
    if (position === 0) {
      path = paper.path("M614.472,119.855c-32.011-9.51-65.687-15.146-100.497-16.341l-13.443,23.283L487.076,103.5          c-35.733,1.142-70.295,6.927-103.088,16.815l-3.686-12.113C418.202,96.771,458.377,90.6,500,90.6          c41.021,0,80.626,5.998,118.041,17.108L614.472,119.855L614.472,119.855z");
    }
    if (position === 1) {
      path = paper.path("M836.075,285.579c-18.407-27.862-40.586-53.824-66.481-77.112l-25.266,9.197l4.673-26.497          c-28.107-22.105-58.305-39.879-89.779-53.379l4.958-11.649c36.381,15.603,71.128,36.7,103.017,63.458          c31.417,26.365,57.907,56.418,79.422,88.975L836.075,285.579L836.075,285.579z");
    }
    if (position === 2) {
      path = paper.path("M909.5,554.382l-12.585-1.405c3.808-33.177,3.511-67.32-1.357-101.81l-25.271-9.193l20.614-17.297          c-7.324-34.991-19.039-68.022-34.467-98.595l11.291-5.741c17.841,35.335,30.892,73.836,38.12,114.832          C912.968,475.564,913.943,515.609,909.5,554.382L909.5,554.382z");
    }
    if (position === 3) {
      path = paper.path("M901.938,596.824c-9.048,38.534-23.796,76.421-44.611,112.473          c-20.508,35.516-45.503,66.821-73.833,93.667l-8.734-9.17c24.241-22.963,45.964-49.315,64.403-78.859l-13.444-23.287h26.898          c16.881-31.518,29.152-64.345,36.985-97.687L901.938,596.824L901.938,596.824z");
    }
    if (position === 4) {
      path = paper.path("M749.149,834.12c-31.703,23.706-67.353,43.249-106.469,57.488          c-38.539,14.027-77.815,21.939-116.769,24.289l-0.801-12.638c33.337-2.01,66.917-8.241,100.031-19.023l4.667-26.469          l20.603,17.294c33.193-13.29,63.693-30.552,91.127-51.06L749.149,834.12L749.149,834.12z");
    }
    if (position === 5) {
      path = paper.path("M377.242,884.316c33.97,11.152,68.426,17.532,102.622,19.452l-0.673,12.648          c-39.525-2.222-79.391-10.166-118.508-24.406c-38.544-14.021-73.716-33.203-105.066-56.438l7.512-10.192          c26.824,19.887,56.549,36.698,88.849,49.724l20.595-17.283L377.242,884.316L377.242,884.316z");
    }
    if (position === 6) {
      path = paper.path("M227.026,794.282l-8.647,9.26c-28.855-27.105-54.287-58.819-75.1-94.871          c-20.508-35.516-35.118-72.819-44.203-110.77l12.312-2.98c7.767,32.478,19.726,64.456,36.094,95.199h26.885l-13.449,23.303          C179.771,743.8,202.069,770.831,227.026,794.282L227.026,794.282z");
    }
    if (position === 7) {
      path = paper.path("M105.881,418.976l20.595,17.277l-25.284,9.201c-5.081,35.388-5.377,70.432-1.336,104.442l-12.574,1.533          c-4.672-39.309-3.776-79.949,3.458-120.941c7.123-40.395,19.898-78.361,37.335-113.271l11.349,5.629          C124.5,352.72,113.101,384.906,105.881,418.976L105.881,418.976z");
    }
    if (position === 8) {
      path = paper.path("M256.205,185.421l4.67,26.473l-25.276-9.201c-26.649,23.839-49.405,50.493-68.166,79.144l-10.609-6.902          c21.685-33.121,48.499-63.674,80.382-90.434c31.422-26.366,65.618-47.235,101.415-62.769l5.075,11.604          C313.059,146.624,283.637,163.963,256.205,185.421L256.205,185.421z");
    }
    return path;
  };
  this.App.createBorderText = function(paper, position) {
    var path;
    if (position === 0) {
      path = paper.path("M378.768,71.271c-0.969-0.566-2.23-0.62-3.78-0.161c-1.1,0.326-2.035,0.935-2.804,1.827  c-0.77,0.894-1.298,1.816-1.587,2.769l-2.773-9.469l-2.691,0.798l7.389,24.941l2.692-0.798l-3.922-13.237  c0.199-0.873,0.592-1.714,1.175-2.524c0.582-0.81,1.308-1.344,2.176-1.601c0.893-0.265,1.67-0.237,2.331,0.082  c0.661,0.32,1.169,1.078,1.522,2.274l3.822,12.901l2.692-0.798l-4.056-13.686C380.467,72.944,379.738,71.838,378.768,71.271z   M395.739,67.056c-1.347-0.652-2.93-0.749-4.75-0.291c-1.162,0.293-2.214,0.787-3.154,1.479c-0.941,0.693-1.738,1.604-2.393,2.734  l1.696,1.624c0.505-0.985,1.087-1.743,1.748-2.271c0.66-0.529,1.42-0.901,2.28-1.118c1.214-0.306,2.228-0.206,3.04,0.299  c0.814,0.505,1.38,1.389,1.697,2.649l0.8,3.177c-0.782-0.66-1.645-1.073-2.584-1.239s-1.876-0.131-2.809,0.104  c-0.757,0.191-1.436,0.503-2.037,0.936c-0.601,0.433-1.089,0.972-1.463,1.616s-0.612,1.375-0.714,2.191  c-0.104,0.818-0.033,1.705,0.208,2.663c0.242,0.958,0.608,1.777,1.102,2.457s1.057,1.216,1.691,1.605  c0.635,0.39,1.321,0.639,2.059,0.748c0.738,0.109,1.474,0.071,2.204-0.113c0.934-0.235,1.772-0.654,2.52-1.258  c0.746-0.604,1.304-1.395,1.675-2.373l0.496,1.967l2.721-0.686l-3.221-12.782C398.023,69.081,397.086,67.709,395.739,67.056z   M396.84,83.004c-0.599,0.569-1.303,0.954-2.113,1.159c-1.141,0.287-2.135,0.113-2.981-0.523c-0.848-0.635-1.415-1.522-1.701-2.662  c-0.287-1.14-0.207-2.184,0.24-3.132c0.448-0.947,1.242-1.565,2.384-1.853c0.811-0.204,1.613-0.197,2.409,0.02  c0.795,0.217,1.509,0.664,2.137,1.34l0.881,3.496C397.856,81.717,397.438,82.436,396.84,83.004z M407.63,63.96  c-0.741,0.813-1.301,1.765-1.676,2.857l-0.636-2.935l-2.744,0.595l3.991,18.409l2.745-0.594l-2.834-13.073  c0.094-0.42,0.262-0.842,0.503-1.267c0.24-0.424,0.526-0.825,0.856-1.203c0.329-0.378,0.688-0.695,1.07-0.951  c0.383-0.255,0.79-0.43,1.224-0.524c0.304-0.066,0.617-0.094,0.938-0.084l-0.611-2.821C409.314,62.617,408.371,63.147,407.63,63.96z   M434.721,59.111c-0.875-0.641-2.004-0.844-3.388-0.607c-0.563,0.096-1.093,0.286-1.584,0.568c-0.493,0.281-0.943,0.616-1.353,1.002  c-0.408,0.387-0.758,0.81-1.049,1.268c-0.291,0.459-0.516,0.913-0.677,1.362c-0.347-0.943-0.924-1.662-1.734-2.157  s-1.817-0.639-3.021-0.433c-0.564,0.097-1.093,0.286-1.584,0.568c-0.493,0.283-0.938,0.616-1.333,1  c-0.396,0.384-0.735,0.792-1.018,1.222c-0.282,0.431-0.484,0.828-0.606,1.192l-0.415-2.659l-2.769,0.473l3.176,18.567l2.769-0.473  l-2.328-13.608c0.28-0.813,0.73-1.589,1.352-2.329c0.62-0.739,1.34-1.178,2.154-1.318c0.891-0.152,1.594,0.005,2.106,0.471  c0.512,0.467,0.854,1.199,1.024,2.199l2.301,13.455l2.769-0.474l-2.328-13.608c0.113-0.415,0.288-0.821,0.524-1.217  c0.234-0.396,0.502-0.765,0.8-1.106c0.298-0.341,0.638-0.63,1.019-0.867c0.382-0.236,0.778-0.39,1.188-0.46  c0.896-0.153,1.597,0.004,2.099,0.472c0.502,0.468,0.839,1.201,1.01,2.201l2.302,13.455l2.767-0.474l-2.426-14.185  C436.178,60.919,435.596,59.753,434.721,59.111z M455.909,61.465c-0.463-1.149-1.068-2.132-1.818-2.947  c-0.751-0.815-1.629-1.432-2.634-1.85s-2.14-0.553-3.404-0.404c-1.239,0.146-2.299,0.54-3.18,1.18  c-0.881,0.641-1.591,1.444-2.131,2.411c-0.541,0.967-0.901,2.064-1.085,3.289c-0.184,1.226-0.197,2.497-0.042,3.814  c0.156,1.317,0.464,2.551,0.928,3.7c0.463,1.15,1.069,2.138,1.821,2.966c0.751,0.828,1.63,1.451,2.636,1.869  c1.004,0.418,2.127,0.555,3.365,0.409c1.266-0.15,2.338-0.545,3.217-1.184c0.881-0.64,1.59-1.45,2.13-2.43  c0.538-0.98,0.898-2.083,1.083-3.309c0.183-1.225,0.196-2.497,0.042-3.814C456.682,63.848,456.372,62.615,455.909,61.465z   M453.986,68.289c-0.077,0.9-0.269,1.715-0.576,2.444c-0.307,0.73-0.732,1.336-1.277,1.819c-0.546,0.484-1.232,0.774-2.059,0.871  c-0.8,0.094-1.521-0.03-2.165-0.374c-0.643-0.343-1.197-0.834-1.666-1.473c-0.468-0.638-0.844-1.386-1.128-2.243  c-0.284-0.856-0.481-1.762-0.595-2.718c-0.109-0.93-0.126-1.851-0.05-2.763c0.075-0.912,0.268-1.726,0.576-2.444  c0.308-0.717,0.733-1.317,1.279-1.8c0.545-0.483,1.219-0.772,2.02-0.866c0.826-0.097,1.56,0.027,2.203,0.369  c0.643,0.344,1.197,0.829,1.664,1.454c0.466,0.626,0.842,1.373,1.128,2.243c0.285,0.87,0.483,1.769,0.593,2.699  C454.046,66.463,454.063,67.39,453.986,68.289z M468.627,54.314c-1.143,0.086-2.175,0.484-3.099,1.192  c-0.924,0.709-1.627,1.498-2.108,2.369l-0.164-2.686l-2.801,0.211l1.418,18.783l2.801-0.211l-1.039-13.767  c0.379-0.811,0.938-1.55,1.68-2.219c0.74-0.668,1.563-1.037,2.465-1.105c0.93-0.07,1.676,0.128,2.243,0.593  c0.567,0.465,0.897,1.32,0.991,2.565l1.01,13.378l2.801-0.211l-1.068-14.156C473.499,55.654,471.789,54.075,468.627,54.314z   M481.454,50.749c0.359-0.393,0.527-0.85,0.503-1.37c-0.022-0.519-0.231-0.959-0.626-1.318c-0.394-0.358-0.85-0.526-1.369-0.503  c-0.521,0.023-0.959,0.233-1.318,0.626c-0.359,0.394-0.527,0.851-0.503,1.37c0.022,0.52,0.231,0.959,0.626,1.318  c0.393,0.359,0.85,0.527,1.37,0.503C480.656,51.351,481.096,51.142,481.454,50.749z M478.899,54.164l0.863,18.817l2.806-0.129  l-0.864-18.817L478.899,54.164z M501.53,63.035c-0.021-1.378-0.2-2.669-0.532-3.873c-0.333-1.204-0.818-2.249-1.459-3.136  c-0.64-0.887-1.428-1.582-2.36-2.087c-0.934-0.505-2.026-0.748-3.277-0.727c-1.198,0.019-2.262,0.297-3.192,0.832  c-0.931,0.536-1.721,1.25-2.37,2.145c-0.65,0.895-1.142,1.949-1.474,3.164c-0.333,1.215-0.486,2.498-0.465,3.85  c0.023,1.456,0.23,2.786,0.618,3.988c0.388,1.202,0.944,2.234,1.669,3.093c0.725,0.859,1.591,1.527,2.6,2.005  c1.01,0.478,2.138,0.707,3.386,0.686c1.272-0.02,2.432-0.307,3.477-0.857c1.044-0.549,1.935-1.299,2.674-2.247l-1.509-1.614  c-0.586,0.765-1.266,1.347-2.039,1.75c-0.772,0.403-1.576,0.611-2.408,0.625c-0.832,0.014-1.582-0.143-2.25-0.47  s-1.234-0.78-1.698-1.357c-0.466-0.577-0.834-1.274-1.107-2.088c-0.273-0.814-0.431-1.69-0.472-2.625l12.206-0.2L501.53,63.035z   M489.305,62.025c0.014-0.702,0.105-1.432,0.274-2.189c0.169-0.756,0.437-1.45,0.802-2.08s0.836-1.151,1.412-1.564  c0.575-0.412,1.277-0.626,2.106-0.639c0.854-0.014,1.581,0.169,2.185,0.549c0.601,0.38,1.088,0.879,1.461,1.497  c0.373,0.618,0.655,1.303,0.85,2.054c0.193,0.751,0.296,1.49,0.308,2.218L489.305,62.025z M518.551,56.196  c-0.563-0.885-1.255-1.579-2.074-2.081c-0.819-0.501-1.762-0.765-2.827-0.792c-0.962-0.024-1.886,0.219-2.77,0.729  c-0.885,0.511-1.64,1.292-2.264,2.342l0.288-9.902l-2.808-0.07l-0.653,26.004l2.809,0.071l0.067-2.69  c0.52,0.976,1.212,1.76,2.079,2.354c0.866,0.594,1.792,0.904,2.776,0.928c1.062,0.027,2.013-0.183,2.854-0.63  c0.841-0.448,1.565-1.099,2.169-1.955c0.604-0.856,1.07-1.885,1.399-3.086c0.328-1.201,0.511-2.543,0.548-4.024  c0.037-1.456-0.079-2.798-0.347-4.027C519.53,58.139,519.114,57.082,518.551,56.196z M516.878,66.181  c-0.205,0.892-0.501,1.665-0.895,2.318c-0.392,0.653-0.872,1.168-1.437,1.544c-0.568,0.376-1.238,0.555-2.015,0.535  c-0.879-0.022-1.707-0.342-2.48-0.96c-0.775-0.618-1.332-1.347-1.673-2.188l0.22-8.616c0.383-0.823,0.976-1.536,1.781-2.14  c0.805-0.604,1.646-0.895,2.526-0.873c0.776,0.02,1.438,0.231,1.984,0.635c0.545,0.404,0.999,0.942,1.356,1.614  c0.358,0.672,0.617,1.466,0.775,2.38c0.158,0.915,0.224,1.878,0.199,2.892C517.196,64.336,517.08,65.289,516.878,66.181z   M537.281,57.459c-0.564-0.937-1.291-1.695-2.18-2.276c-0.889-0.58-1.957-0.913-3.205-0.997c-1.196-0.08-2.28,0.108-3.251,0.564  s-1.818,1.103-2.541,1.94c-0.722,0.838-1.298,1.847-1.731,3.03c-0.431,1.183-0.691,2.449-0.782,3.798  c-0.099,1.453-0.003,2.794,0.284,4.025c0.286,1.231,0.756,2.305,1.405,3.221c0.651,0.917,1.458,1.655,2.425,2.215  c0.965,0.56,2.07,0.882,3.316,0.965c1.271,0.086,2.45-0.103,3.535-0.565c1.086-0.461,2.037-1.134,2.852-2.017l-1.369-1.734  c-0.647,0.713-1.372,1.237-2.177,1.574s-1.622,0.478-2.452,0.422c-0.831-0.055-1.563-0.274-2.203-0.656  c-0.64-0.381-1.166-0.879-1.58-1.493c-0.415-0.614-0.726-1.339-0.931-2.173c-0.204-0.834-0.288-1.719-0.251-2.655l12.18,0.817  l0.058-0.856c0.093-1.375,0.021-2.676-0.208-3.903C538.243,59.478,537.845,58.396,537.281,57.459z M535.963,63.214l-9.378-0.63  c0.071-0.699,0.225-1.417,0.456-2.158c0.231-0.739,0.556-1.409,0.972-2.006c0.416-0.598,0.929-1.078,1.536-1.441  c0.607-0.362,1.326-0.517,2.152-0.461c0.854,0.057,1.563,0.3,2.131,0.729c0.567,0.429,1.013,0.967,1.332,1.614  c0.32,0.647,0.546,1.353,0.677,2.117C535.971,61.743,536.012,62.488,535.963,63.214z M554.262,59.454  c-0.452-1.122-1.09-1.996-1.91-2.622s-1.709-0.992-2.665-1.096c-1.06-0.116-2.029,0.02-2.909,0.408s-1.657,0.983-2.333,1.785  c-0.677,0.803-1.229,1.795-1.66,2.977c-0.43,1.182-0.724,2.497-0.883,3.944c-0.162,1.473-0.153,2.827,0.026,4.063  c0.179,1.236,0.505,2.318,0.979,3.246c0.475,0.929,1.1,1.67,1.875,2.226c0.776,0.556,1.694,0.892,2.754,1.008  c0.983,0.108,1.944-0.075,2.886-0.547c0.94-0.472,1.735-1.157,2.383-2.054l-0.293,2.675l2.79,0.304l2.83-25.858l-2.791-0.306  L554.262,59.454z M553.062,70.428c-0.453,0.787-1.098,1.437-1.939,1.945c-0.841,0.51-1.713,0.715-2.616,0.616  c-0.776-0.085-1.42-0.352-1.936-0.801c-0.514-0.449-0.921-1.023-1.224-1.723c-0.304-0.7-0.496-1.505-0.579-2.417  s-0.069-1.871,0.041-2.879s0.305-1.954,0.585-2.839c0.279-0.884,0.644-1.636,1.09-2.254c0.447-0.618,0.969-1.09,1.568-1.417  c0.598-0.327,1.285-0.448,2.06-0.363c0.904,0.099,1.712,0.495,2.421,1.187s1.199,1.472,1.471,2.338L553.062,70.428z M573.257,56.356  c0.463,0.071,0.894-0.035,1.291-0.316c0.397-0.281,0.632-0.653,0.702-1.116c0.074-0.487-0.036-0.925-0.331-1.313  c-0.297-0.387-0.677-0.616-1.139-0.686c-0.489-0.075-0.926,0.03-1.311,0.313c-0.384,0.284-0.614,0.67-0.689,1.158  c-0.071,0.462,0.036,0.886,0.319,1.271S572.769,56.282,573.257,56.356z M570.951,73.047c-0.527,0.709-1.225,1.293-2.092,1.752  c-0.869,0.46-1.762,0.62-2.683,0.479c-0.896-0.137-1.573-0.49-2.036-1.06c-0.463-0.57-0.6-1.472-0.412-2.706l2.026-13.301  l-2.775-0.423l-2.15,14.111c-0.258,1.697-0.07,3.008,0.565,3.933c0.634,0.925,1.748,1.509,3.343,1.752  c1.156,0.177,2.249,0.033,3.28-0.427c1.029-0.461,1.89-1.059,2.581-1.796l-0.395,2.583l2.777,0.422l2.837-18.622l-2.775-0.423  L570.951,73.047z M566.548,55.334c0.487,0.074,0.925-0.03,1.31-0.313s0.614-0.656,0.684-1.119c0.074-0.487-0.029-0.924-0.314-1.31  c-0.283-0.385-0.669-0.615-1.157-0.689c-0.463-0.071-0.893,0.035-1.291,0.316c-0.396,0.282-0.634,0.667-0.708,1.155  c-0.07,0.462,0.042,0.887,0.338,1.274C565.705,55.035,566.084,55.264,566.548,55.334z M586.142,62.216  c-0.999,0.461-1.883,1.122-2.652,1.983l0.553-2.952l-2.761-0.517l-3.465,18.516l2.761,0.517l2.461-13.148  c0.25-0.35,0.568-0.674,0.955-0.972c0.388-0.298,0.806-0.557,1.258-0.777c0.449-0.219,0.901-0.373,1.354-0.46  c0.453-0.087,0.896-0.091,1.331-0.009c0.306,0.057,0.606,0.153,0.898,0.287l0.53-2.837  C588.215,61.632,587.141,61.755,586.142,62.216z M597.619,59.464c0.487-0.415,1.112-0.541,1.875-0.379  c0.687,0.146,1.225,0.554,1.614,1.221l1.482-1.719c-0.366-0.53-0.809-0.949-1.327-1.259c-0.52-0.309-1.084-0.529-1.694-0.659  c-1.45-0.308-2.68-0.092-3.688,0.651c-1.009,0.743-1.683,1.915-2.023,3.517l-0.479,2.251l-2.441-0.519l-0.519,2.441l2.44,0.519  l-3.397,15.984l2.747,0.585l3.396-15.983l3.129,0.665l0.52-2.442l-3.128-0.665l0.479-2.251  C596.796,60.532,597.134,59.879,597.619,59.464z M604.525,82.619c-0.298,0.076-0.625,0.072-0.979-0.012  c-0.531-0.126-0.866-0.405-1.005-0.837c-0.138-0.433-0.123-1.002,0.045-1.709l2.779-11.732l3.112,0.737l0.575-2.429l-3.112-0.737  l1.188-5.009l-2.732-0.647l-1.188,5.009l-2.43-0.576l-0.575,2.429l2.43,0.576l-2.897,12.229c-0.651,2.751,0.249,4.417,2.703,4.999  c0.708,0.168,1.319,0.207,1.835,0.115c0.516-0.092,0.978-0.263,1.385-0.514l-0.35-2.247  C605.084,82.425,604.823,82.543,604.525,82.619z M614.904,65.319c0.503,0.13,0.985,0.06,1.444-0.209  c0.459-0.27,0.754-0.657,0.885-1.161c0.131-0.503,0.061-0.984-0.21-1.444c-0.27-0.459-0.657-0.755-1.16-0.885  c-0.504-0.13-0.984-0.06-1.443,0.21c-0.46,0.27-0.756,0.657-0.886,1.16c-0.131,0.504-0.062,0.985,0.209,1.444  C614.013,64.894,614.4,65.189,614.904,65.319z M612.898,67.62l-4.727,18.234l2.719,0.705l4.727-18.234L612.898,67.62z   M631.259,72.721l-0.767,2.621c-0.274-1.191-0.755-2.164-1.441-2.92c-0.688-0.756-1.492-1.269-2.415-1.539  c-1.024-0.299-2-0.341-2.931-0.125c-0.93,0.216-1.796,0.654-2.598,1.313c-0.803,0.659-1.517,1.527-2.143,2.604  c-0.626,1.077-1.145,2.314-1.553,3.711c-0.416,1.423-0.642,2.752-0.678,3.987c-0.036,1.236,0.1,2.345,0.409,3.329  c0.308,0.984,0.797,1.812,1.469,2.481c0.671,0.67,1.519,1.155,2.541,1.454c0.948,0.278,1.931,0.254,2.947-0.073  c1.016-0.326,1.921-0.874,2.715-1.645l-0.886,3.032c-0.255,0.873-0.593,1.587-1.012,2.142c-0.421,0.554-0.893,0.965-1.416,1.232  c-0.525,0.266-1.09,0.413-1.693,0.44c-0.604,0.027-1.218-0.051-1.842-0.233c-1.947-0.569-3.315-1.727-4.104-3.475l-1.849,1.735  c0.619,1.129,1.361,1.996,2.227,2.601c0.866,0.605,1.91,1.087,3.135,1.444c0.947,0.278,1.89,0.417,2.824,0.419  s1.816-0.187,2.646-0.568s1.573-0.982,2.233-1.805c0.661-0.823,1.195-1.934,1.604-3.331l5.271-18.043L631.259,72.721z   M627.483,85.635c-0.584,0.697-1.336,1.235-2.26,1.615c-0.924,0.381-1.823,0.443-2.696,0.188c-0.748-0.218-1.339-0.587-1.769-1.106  c-0.433-0.519-0.737-1.144-0.916-1.873c-0.181-0.73-0.233-1.545-0.159-2.444c0.072-0.899,0.252-1.836,0.536-2.809  c0.285-0.973,0.638-1.859,1.061-2.656c0.422-0.797,0.908-1.462,1.456-1.992c0.547-0.531,1.143-0.899,1.785-1.104  c0.642-0.205,1.338-0.198,2.086,0.021c0.874,0.255,1.599,0.785,2.177,1.59c0.577,0.806,0.923,1.659,1.04,2.559L627.483,85.635z");
    }
    if (position === 1) {
      path = paper.path("M748.209,133.934c0.404-1.178,0.6-2.291,0.582-3.34c-0.018-1.049-0.249-1.996-0.692-2.841  c-0.445-0.845-1.114-1.557-2.009-2.136c-0.829-0.537-1.771-0.806-2.823-0.806s-2.071,0.256-3.051,0.766l1.495-2.238l-2.357-1.526  l-14.137,21.837l2.356,1.526l5.384-8.315c-0.079,1.219,0.102,2.288,0.54,3.207s1.061,1.64,1.865,2.161  c0.893,0.577,1.817,0.889,2.775,0.935c0.957,0.047,1.917-0.136,2.881-0.551c0.962-0.414,1.898-1.048,2.804-1.901  c0.907-0.854,1.765-1.902,2.569-3.146C747.197,136.322,747.803,135.111,748.209,133.934z M745.265,133.423  c-0.335,0.851-0.778,1.703-1.329,2.554s-1.151,1.609-1.797,2.275c-0.646,0.666-1.308,1.174-1.982,1.527  c-0.676,0.352-1.353,0.541-2.031,0.566c-0.681,0.025-1.346-0.173-1.996-0.595c-0.739-0.478-1.271-1.193-1.595-2.147  c-0.325-0.953-0.412-1.876-0.264-2.772l4.684-7.235c0.757-0.502,1.628-0.789,2.616-0.862c0.988-0.073,1.853,0.13,2.59,0.608  c0.651,0.422,1.104,0.948,1.36,1.578c0.254,0.629,0.36,1.325,0.315,2.085C745.79,131.766,745.6,132.572,745.265,133.423z   M759.319,126.393l-14.793,21.397l2.311,1.597l14.793-21.396L759.319,126.393z M732.286,117.535l-9.753,16.116l2.402,1.454  l9.753-16.116L732.286,117.535z M734.867,115.906c0.445,0.269,0.927,0.341,1.443,0.213c0.518-0.127,0.911-0.413,1.181-0.858  c0.271-0.445,0.341-0.926,0.213-1.444c-0.128-0.517-0.412-0.911-0.857-1.18s-0.926-0.34-1.443-0.213  c-0.519,0.127-0.912,0.413-1.181,0.858c-0.271,0.445-0.341,0.926-0.213,1.444C734.137,115.243,734.423,115.636,734.867,115.906z   M728.626,107.041l-4.866,8.628c0.024-1.21-0.217-2.264-0.725-3.163c-0.508-0.898-1.182-1.584-2.019-2.057  c-0.929-0.524-1.874-0.781-2.834-0.771c-0.962,0.011-1.91,0.251-2.849,0.722c-0.938,0.472-1.838,1.166-2.697,2.083  c-0.861,0.918-1.648,2.01-2.364,3.278c-0.728,1.291-1.253,2.54-1.576,3.746c-0.322,1.206-0.448,2.329-0.378,3.369  c0.07,1.039,0.354,1.967,0.848,2.784c0.494,0.816,1.206,1.486,2.136,2.01c0.859,0.485,1.815,0.695,2.866,0.632  c1.051-0.064,2.051-0.381,3-0.95l-1.323,2.344l2.445,1.381l12.782-22.656L728.626,107.041z M722.591,117.739l-4.254,7.541  c-0.728,0.546-1.576,0.888-2.55,1.025c-0.973,0.139-1.855-0.017-2.647-0.464c-0.68-0.383-1.167-0.882-1.463-1.497  c-0.296-0.615-0.444-1.303-0.447-2.066c-0.002-0.763,0.138-1.58,0.42-2.45c0.282-0.871,0.673-1.748,1.171-2.631  c0.498-0.883,1.049-1.676,1.655-2.379c0.606-0.703,1.236-1.251,1.89-1.643c0.654-0.393,1.32-0.622,1.999-0.686  c0.68-0.065,1.357,0.094,2.037,0.477c0.792,0.447,1.378,1.129,1.758,2.044C722.539,115.926,722.683,116.836,722.591,117.739z   M768.063,153.115c0.788-1.067,1.405-2.179,1.854-3.334c0.447-1.156,0.676-2.288,0.686-3.396c0.009-1.108-0.211-2.158-0.658-3.15  c-0.448-0.992-1.185-1.866-2.21-2.622c-1.005-0.741-2.048-1.178-3.127-1.313c-1.081-0.134-2.147-0.033-3.204,0.304  c-1.056,0.337-2.068,0.89-3.04,1.66s-1.85,1.689-2.637,2.756s-1.405,2.178-1.853,3.334s-0.68,2.293-0.696,3.411  c-0.019,1.119,0.198,2.174,0.646,3.166c0.449,0.992,1.174,1.859,2.18,2.599c1.024,0.756,2.077,1.2,3.156,1.333  c1.08,0.134,2.152,0.028,3.215-0.319c1.063-0.347,2.08-0.905,3.053-1.675C766.397,155.101,767.277,154.183,768.063,153.115z   M763.847,153.448c-0.672,0.603-1.368,1.067-2.091,1.39c-0.724,0.323-1.448,0.476-2.178,0.455c-0.729-0.021-1.427-0.277-2.097-0.771  c-0.647-0.478-1.09-1.062-1.325-1.753c-0.233-0.689-0.304-1.427-0.209-2.213c0.096-0.785,0.331-1.589,0.709-2.408  s0.854-1.617,1.423-2.391c0.557-0.753,1.173-1.437,1.853-2.051c0.678-0.614,1.375-1.077,2.09-1.39  c0.716-0.313,1.437-0.459,2.165-0.439c0.728,0.02,1.417,0.269,2.065,0.747c0.669,0.494,1.121,1.086,1.355,1.775  c0.235,0.69,0.309,1.423,0.222,2.198c-0.088,0.776-0.323,1.579-0.709,2.409c-0.387,0.83-0.855,1.622-1.411,2.375  C765.139,152.156,764.517,152.844,763.847,153.448z M793.076,162.13c-0.089-1.082-0.675-2.068-1.761-2.958  c-0.443-0.363-0.932-0.638-1.467-0.825c-0.537-0.188-1.083-0.309-1.645-0.365c-0.56-0.055-1.108-0.043-1.645,0.038  c-0.538,0.081-1.029,0.208-1.474,0.381c0.485-0.88,0.65-1.787,0.493-2.723c-0.156-0.936-0.708-1.791-1.651-2.566  c-0.443-0.363-0.933-0.638-1.467-0.825c-0.536-0.187-1.079-0.305-1.629-0.352c-0.55-0.048-1.08-0.037-1.591,0.032  c-0.511,0.069-0.943,0.176-1.298,0.322l1.736-2.056l-2.171-1.781l-11.947,14.563l2.171,1.781l8.757-10.673  c0.797-0.321,1.68-0.489,2.646-0.504c0.965-0.015,1.767,0.24,2.406,0.765c0.699,0.573,1.041,1.207,1.024,1.899  c-0.016,0.693-0.346,1.431-0.989,2.215l-8.658,10.553l2.172,1.781l8.757-10.673c0.388-0.187,0.809-0.321,1.263-0.402  s0.907-0.121,1.36-0.12c0.452,0.001,0.892,0.069,1.321,0.202c0.429,0.133,0.805,0.332,1.125,0.596  c0.705,0.577,1.043,1.209,1.02,1.895c-0.024,0.685-0.358,1.421-1.002,2.205l-8.657,10.553l2.172,1.78l9.128-11.126  C792.664,164.415,793.164,163.211,793.076,162.13z M805.994,174.128c-0.201-1.483-0.996-2.856-2.386-4.118  c-0.887-0.807-1.88-1.411-2.978-1.811c-1.099-0.4-2.299-0.561-3.602-0.48l-0.415,2.312c1.101-0.125,2.052-0.058,2.858,0.2  c0.805,0.258,1.536,0.685,2.193,1.282c0.926,0.842,1.403,1.742,1.433,2.699c0.028,0.958-0.396,1.917-1.27,2.879l-2.203,2.424  c0.117-1.018-0.016-1.963-0.397-2.838s-0.929-1.636-1.641-2.282c-0.577-0.525-1.213-0.918-1.906-1.179  c-0.693-0.262-1.412-0.37-2.155-0.326c-0.743,0.045-1.483,0.251-2.221,0.617c-0.738,0.366-1.438,0.915-2.104,1.646  c-0.666,0.732-1.144,1.49-1.438,2.277c-0.294,0.787-0.428,1.553-0.401,2.297c0.027,0.744,0.199,1.455,0.517,2.129  c0.316,0.674,0.754,1.266,1.313,1.773c0.711,0.647,1.525,1.114,2.44,1.402c0.916,0.288,1.882,0.315,2.902,0.083l-1.363,1.5  l2.081,1.888l8.865-9.754C805.571,177.151,806.196,175.611,805.994,174.128z M798.228,181.054l-2.425,2.667  c-0.856,0.281-1.687,0.33-2.49,0.146c-0.804-0.185-1.515-0.557-2.134-1.12c-0.87-0.791-1.276-1.715-1.213-2.77  c0.06-1.057,0.485-2.02,1.276-2.89c0.79-0.87,1.704-1.381,2.742-1.532c1.037-0.151,1.991,0.169,2.862,0.96  c0.618,0.562,1.057,1.235,1.315,2.018C798.422,179.316,798.444,180.157,798.228,181.054z M803.696,193.836  c-0.393-0.38-0.537-0.791-0.435-1.233c0.102-0.442,0.406-0.924,0.911-1.446l8.389-8.66l2.298,2.225l1.736-1.793l-2.297-2.225  l3.581-3.698l-2.018-1.954l-3.582,3.698l-1.793-1.737l-1.736,1.793l1.794,1.737l-8.744,9.027c-1.966,2.031-2.045,3.924-0.233,5.679  c0.523,0.506,1.03,0.852,1.52,1.038c0.489,0.185,0.973,0.274,1.451,0.266l0.85-2.109c-0.275,0.023-0.561-0.01-0.856-0.097  C804.236,194.26,803.957,194.089,803.696,193.836z M823.644,185.341c0.533,0.002,0.984-0.179,1.354-0.545  c0.37-0.366,0.556-0.816,0.559-1.349c0.003-0.533-0.179-0.985-0.545-1.354c-0.367-0.37-0.816-0.555-1.35-0.558  s-0.984,0.179-1.354,0.545c-0.37,0.367-0.556,0.816-0.558,1.349c-0.005,0.533,0.179,0.984,0.545,1.354  C822.659,185.152,823.109,185.338,823.644,185.341z M819.395,185.734l-13.383,13.256l1.976,1.995l13.383-13.256L819.395,185.734z   M824.299,204.338c-0.131-0.823-0.363-1.639-0.696-2.45c-0.334-0.811-0.62-1.578-0.854-2.303c-0.235-0.724-0.366-1.395-0.393-2.012  c-0.028-0.617,0.205-1.157,0.698-1.62c0.549-0.516,1.223-0.739,2.021-0.668c0.798,0.071,1.555,0.485,2.267,1.243  c0.623,0.662,1.06,1.403,1.311,2.22s0.311,1.609,0.175,2.378l2.302-0.343c0.066-0.991-0.064-1.983-0.392-2.978  c-0.328-0.994-0.919-1.946-1.772-2.855c-0.643-0.682-1.312-1.204-2.009-1.566c-0.696-0.361-1.394-0.572-2.091-0.63  c-0.696-0.058-1.361,0.023-1.994,0.242c-0.632,0.22-1.204,0.57-1.716,1.051c-0.795,0.748-1.279,1.524-1.451,2.328  c-0.172,0.804-0.188,1.614-0.048,2.427c0.142,0.813,0.378,1.625,0.712,2.436c0.333,0.811,0.618,1.578,0.854,2.303  c0.233,0.725,0.347,1.413,0.336,2.066s-0.283,1.229-0.813,1.727c-0.664,0.624-1.426,0.886-2.287,0.785  c-0.86-0.1-1.666-0.549-2.413-1.344c-0.695-0.739-1.171-1.577-1.427-2.514c-0.257-0.936-0.324-1.835-0.206-2.696L812,201.904  c-0.237,2.328,0.569,4.477,2.423,6.448c0.657,0.7,1.353,1.241,2.087,1.622c0.733,0.381,1.457,0.61,2.172,0.688  c0.715,0.077,1.412-0.007,2.091-0.253c0.679-0.246,1.303-0.635,1.871-1.17c0.813-0.765,1.327-1.568,1.537-2.408  C824.39,205.992,824.43,205.16,824.299,204.338z M826.762,217.351c-0.127-0.737-0.078-1.488,0.148-2.257  c0.227-0.768,0.604-1.531,1.133-2.288c0.528-0.758,1.176-1.47,1.938-2.138s1.548-1.21,2.36-1.626  c0.809-0.416,1.609-0.685,2.401-0.808c0.791-0.123,1.543-0.074,2.256,0.149c0.715,0.222,1.345,0.646,1.894,1.272  c0.479,0.547,0.799,1.14,0.96,1.777c0.16,0.637,0.157,1.373-0.008,2.21l2.438-0.115c0.154-0.929,0.133-1.861-0.063-2.795  c-0.196-0.934-0.731-1.899-1.604-2.897c-0.805-0.92-1.715-1.574-2.729-1.963c-1.017-0.39-2.074-0.542-3.176-0.459  c-1.103,0.083-2.223,0.382-3.362,0.896s-2.237,1.234-3.294,2.159c-1.055,0.925-1.914,1.918-2.573,2.98  c-0.66,1.062-1.11,2.138-1.348,3.228c-0.238,1.09-0.231,2.163,0.021,3.221c0.252,1.057,0.78,2.046,1.586,2.965  c0.874,0.997,1.756,1.659,2.647,1.985c0.889,0.326,1.815,0.466,2.777,0.419l0.436-2.403c-1.593,0.116-2.868-0.374-3.827-1.469  C827.225,218.768,826.888,218.087,826.762,217.351z M849.243,219.565c-1.119-0.369-2.174-0.505-3.165-0.407l7.688-6.185  l-1.768-2.183l-20.217,16.37l1.768,2.182l10.729-8.688c0.883-0.15,1.81-0.11,2.781,0.119c0.971,0.229,1.743,0.694,2.312,1.398  c0.586,0.724,0.857,1.452,0.815,2.185s-0.548,1.492-1.519,2.277l-10.456,8.467l1.767,2.184l11.094-8.982  c1.334-1.08,2.077-2.177,2.229-3.29c0.152-1.114-0.279-2.299-1.298-3.555C851.282,220.565,850.362,219.934,849.243,219.565z");
    }
    if (position === 2) {
      path = paper.path("M923.046,350.848c0.501-1.41,0.425-2.995-0.229-4.754  c-0.417-1.124-1.021-2.115-1.813-2.975c-0.791-0.861-1.785-1.554-2.979-2.08l-1.429,1.863c1.034,0.394,1.849,0.891,2.447,1.49  c0.596,0.599,1.049,1.313,1.358,2.145c0.437,1.174,0.447,2.192,0.034,3.056c-0.414,0.864-1.23,1.523-2.448,1.976l-3.069,1.142  c0.569-0.851,0.887-1.753,0.948-2.705c0.063-0.953-0.074-1.88-0.409-2.781c-0.271-0.731-0.656-1.372-1.152-1.922  c-0.496-0.55-1.085-0.977-1.766-1.278c-0.682-0.302-1.434-0.459-2.256-0.472c-0.822-0.013-1.697,0.153-2.624,0.497  c-0.926,0.344-1.699,0.799-2.321,1.363s-1.095,1.183-1.411,1.856c-0.319,0.673-0.492,1.382-0.521,2.128  c-0.026,0.745,0.09,1.471,0.354,2.178c0.336,0.901,0.843,1.69,1.524,2.366c0.682,0.676,1.528,1.144,2.541,1.406l-1.899,0.707  l0.979,2.633l12.355-4.595C921.281,353.339,922.545,352.258,923.046,350.848z M914.07,351.163c-0.129,0.815-0.496,1.572-1.1,2.27  l-3.379,1.257c-0.89-0.143-1.649-0.48-2.279-1.013c-0.63-0.533-1.09-1.19-1.382-1.974c-0.41-1.102-0.346-2.109,0.192-3.02  c0.539-0.912,1.359-1.572,2.462-1.982c1.102-0.41,2.147-0.444,3.14-0.102c0.992,0.342,1.692,1.064,2.102,2.167  C914.117,349.549,914.198,350.348,914.07,351.163z M929.565,367.099l-13.201,4.3c-0.87-0.153-1.705-0.513-2.506-1.082  c-0.8-0.569-1.345-1.296-1.633-2.181c-0.281-0.861-0.271-1.626,0.031-2.295c0.301-0.669,1.045-1.197,2.231-1.584l12.794-4.167  l-0.87-2.67l-13.571,4.421c-1.633,0.531-2.719,1.288-3.26,2.271c-0.542,0.982-0.562,2.24-0.063,3.773  c0.362,1.113,0.98,2.025,1.855,2.739c0.875,0.713,1.797,1.213,2.766,1.499l-2.484,0.81l0.869,2.67l17.911-5.834L929.565,367.099z   M925.375,401.896c1.244-0.025,2.584-0.228,4.016-0.61c1.407-0.376,2.662-0.866,3.766-1.47c1.103-0.604,2-1.302,2.69-2.092  c0.689-0.79,1.16-1.648,1.411-2.577c0.25-0.929,0.236-1.907-0.038-2.937c-0.248-0.929-0.742-1.746-1.481-2.45  c-0.74-0.704-1.702-1.207-2.886-1.51l9.58-2.519l-0.726-2.713l-25.132,6.713l0.726,2.714l2.6-0.694  c-0.789,0.774-1.347,1.66-1.671,2.659c-0.325,0.998-0.361,1.974-0.106,2.925c0.273,1.026,0.744,1.879,1.41,2.561  c0.666,0.681,1.495,1.189,2.487,1.528C923.012,401.763,924.131,401.92,925.375,401.896z M920.352,396.011  c-0.228-0.85-0.154-1.734,0.22-2.651c0.374-0.918,0.916-1.659,1.627-2.223l8.327-2.223c0.897,0.135,1.749,0.503,2.556,1.105  c0.808,0.602,1.323,1.328,1.552,2.178c0.199,0.75,0.183,1.444-0.051,2.083c-0.231,0.638-0.621,1.224-1.164,1.758  s-1.231,1.006-2.063,1.416c-0.833,0.409-1.739,0.745-2.719,1.007c-0.98,0.262-1.926,0.42-2.839,0.477  c-0.914,0.057-1.739-0.011-2.478-0.202c-0.738-0.192-1.366-0.507-1.887-0.943C920.912,397.354,920.552,396.761,920.352,396.011z   M931.528,382.388l2.411-0.644l-0.825-3.09l2.225-0.594c0.879-0.234,1.612-0.229,2.203,0.017c0.592,0.246,0.979,0.72,1.168,1.424  c0.128,0.477,0.108,0.913-0.056,1.307l2.292,0.114c0.202-0.754,0.183-1.583-0.06-2.487c-0.355-1.332-1.089-2.286-2.197-2.864  c-1.11-0.578-2.47-0.652-4.076-0.223l-2.224,0.594l-0.645-2.412l-2.412,0.645l0.646,2.411l-15.788,4.217l0.725,2.712l15.788-4.217  L931.528,382.388z M935.952,407.941c0.425,0.238,0.826,0.523,1.205,0.854c0.377,0.329,0.695,0.687,0.952,1.069  c0.255,0.384,0.432,0.79,0.526,1.223c0.065,0.305,0.095,0.618,0.085,0.939l2.82-0.616c-0.25-1.144-0.783-2.084-1.597-2.825  c-0.813-0.74-1.767-1.297-2.858-1.67l2.934-0.641l-0.6-2.743l-18.403,4.02l0.6,2.742l13.069-2.854  C935.105,407.533,935.528,407.701,935.952,407.941z M942.875,425.788c0.74-1.302,0.939-2.876,0.6-4.721  c-0.217-1.181-0.64-2.262-1.271-3.245c-0.632-0.984-1.487-1.839-2.572-2.565l-1.731,1.587c0.95,0.568,1.668,1.198,2.152,1.893  c0.485,0.692,0.807,1.475,0.967,2.348c0.228,1.23,0.062,2.236-0.496,3.015c-0.558,0.779-1.476,1.286-2.754,1.521l-3.223,0.592  c0.71-0.739,1.178-1.572,1.404-2.499c0.226-0.928,0.253-1.864,0.078-2.81c-0.142-0.768-0.407-1.466-0.802-2.094  c-0.393-0.628-0.899-1.149-1.517-1.564c-0.619-0.416-1.332-0.701-2.141-0.856c-0.809-0.154-1.699-0.144-2.671,0.035  c-0.971,0.178-1.812,0.492-2.522,0.939c-0.711,0.446-1.281,0.975-1.711,1.583c-0.432,0.607-0.726,1.276-0.882,2.006  c-0.155,0.728-0.167,1.464-0.029,2.206c0.174,0.945,0.537,1.811,1.091,2.595c0.554,0.783,1.307,1.391,2.259,1.825l-1.994,0.367  l0.509,2.764l12.965-2.383C940.706,427.936,942.137,427.09,942.875,425.788z M933.98,424.542c-0.269,0.779-0.761,1.461-1.478,2.044  l-3.545,0.652c-0.851-0.295-1.541-0.761-2.068-1.394c-0.529-0.634-0.868-1.361-1.02-2.184c-0.213-1.157,0.026-2.138,0.715-2.941  c0.689-0.804,1.612-1.313,2.769-1.524s2.192-0.064,3.11,0.444c0.916,0.51,1.479,1.343,1.692,2.499  C934.307,422.961,934.247,423.762,933.98,424.542z M946.479,442.928l-13.746,1.948c-0.831-0.301-1.591-0.801-2.28-1.5  s-1.1-1.509-1.23-2.431c-0.127-0.897,0.017-1.648,0.43-2.255c0.412-0.607,1.238-0.998,2.473-1.174l13.321-1.888l-0.394-2.78  l-14.134,2.002c-1.699,0.241-2.9,0.799-3.604,1.674c-0.703,0.874-0.942,2.108-0.716,3.706c0.165,1.158,0.617,2.164,1.354,3.019  c0.737,0.853,1.56,1.505,2.463,1.955l-2.587,0.367l0.395,2.779l18.65-2.643L946.479,442.928z M932.618,463.561  c0.688,0.217,1.421,0.284,2.197,0.204c1.112-0.113,2.006-0.44,2.682-0.981c0.676-0.54,1.212-1.177,1.606-1.91  c0.396-0.733,0.706-1.523,0.933-2.37s0.466-1.63,0.719-2.348s0.554-1.331,0.907-1.838c0.353-0.508,0.865-0.795,1.538-0.864  c0.75-0.077,1.421,0.153,2.014,0.694c0.591,0.54,0.94,1.326,1.047,2.361c0.093,0.905-0.009,1.758-0.306,2.561  c-0.296,0.801-0.73,1.467-1.303,1.997l2.036,1.123c0.655-0.747,1.153-1.615,1.496-2.604c0.342-0.99,0.449-2.104,0.321-3.346  c-0.096-0.932-0.312-1.752-0.646-2.462c-0.334-0.71-0.76-1.301-1.28-1.77c-0.518-0.47-1.096-0.809-1.73-1.018  c-0.636-0.208-1.303-0.277-2.001-0.205c-1.087,0.113-1.942,0.436-2.566,0.971c-0.625,0.534-1.128,1.168-1.51,1.9  c-0.382,0.731-0.685,1.521-0.912,2.368c-0.227,0.847-0.466,1.629-0.718,2.348c-0.253,0.719-0.582,1.335-0.986,1.847  c-0.403,0.513-0.968,0.806-1.692,0.88c-0.905,0.094-1.67-0.161-2.293-0.763c-0.625-0.602-0.992-1.447-1.104-2.533  c-0.104-1.009,0.026-1.963,0.391-2.862c0.365-0.9,0.855-1.656,1.473-2.27l-2.123-1.192c-1.602,1.707-2.262,3.906-1.985,6.597  c0.1,0.957,0.321,1.806,0.673,2.554c0.353,0.748,0.789,1.369,1.311,1.864C931.324,462.988,931.93,463.343,932.618,463.561z   M933.647,481.165l1.539-1.585c-0.792-0.548-1.408-1.198-1.847-1.951c-0.439-0.753-0.687-1.545-0.74-2.375  c-0.055-0.831,0.065-1.587,0.36-2.271c0.293-0.684,0.718-1.271,1.271-1.764c0.554-0.493,1.231-0.895,2.032-1.207  s1.667-0.513,2.6-0.599l0.791,12.182l0.856-0.056c1.375-0.09,2.654-0.33,3.842-0.72c1.187-0.392,2.207-0.929,3.061-1.61  c0.856-0.682,1.513-1.502,1.972-2.459s0.646-2.06,0.565-3.309c-0.077-1.196-0.405-2.245-0.985-3.148s-1.332-1.658-2.258-2.264  c-0.925-0.606-2.003-1.046-3.231-1.318s-2.519-0.365-3.867-0.278c-1.453,0.096-2.77,0.365-3.953,0.813  c-1.183,0.446-2.186,1.051-3.009,1.816s-1.449,1.663-1.877,2.694s-0.603,2.17-0.521,3.415c0.083,1.271,0.426,2.415,1.025,3.431  C931.873,479.62,932.665,480.473,933.647,481.165z M943.124,469.45c0.764,0.132,1.471,0.365,2.117,0.699  c0.647,0.334,1.19,0.778,1.63,1.334c0.44,0.555,0.688,1.245,0.741,2.072c0.056,0.853-0.092,1.588-0.442,2.208  c-0.352,0.619-0.825,1.13-1.426,1.532c-0.599,0.402-1.269,0.718-2.01,0.948c-0.741,0.229-1.474,0.369-2.2,0.416l-0.608-9.378  C941.627,469.262,942.36,469.318,943.124,469.45z M931.38,488.745l13.802-0.328c0.79,0.42,1.5,1.018,2.13,1.792  c0.629,0.774,0.956,1.614,0.977,2.519c0.022,0.932-0.214,1.667-0.708,2.21c-0.493,0.541-1.364,0.827-2.612,0.856l-13.412,0.319  l0.065,2.809l14.192-0.337c3.405-0.081,5.07-1.707,4.994-4.878c-0.026-1.145-0.37-2.195-1.03-3.155s-1.412-1.703-2.257-2.229  l2.691-0.025l-0.067-2.807l-18.831,0.446L931.38,488.745z M947.557,514.838c1.077-0.554,1.889-1.268,2.438-2.142  c0.549-0.875,0.831-1.793,0.849-2.755c0.018-1.066-0.205-2.019-0.671-2.859c-0.468-0.841-1.131-1.56-1.99-2.161  c-0.861-0.6-1.899-1.06-3.116-1.381s-2.553-0.494-4.008-0.52c-1.482-0.026-2.83,0.105-4.045,0.396  c-1.214,0.292-2.263,0.715-3.144,1.271c-0.881,0.557-1.563,1.246-2.045,2.07c-0.481,0.823-0.732,1.77-0.752,2.834  c-0.017,0.988,0.252,1.928,0.809,2.823c0.557,0.894,1.311,1.623,2.264,2.186l-2.691-0.048l-0.051,2.81l26.009,0.458l0.051-2.809  L947.557,514.838z M945.181,514.795l-8.657-0.153c-0.825-0.379-1.53-0.963-2.114-1.753c-0.584-0.791-0.868-1.641-0.853-2.551  c0.014-0.779,0.22-1.446,0.62-1.999c0.399-0.552,0.935-1.011,1.604-1.376s1.454-0.631,2.354-0.797  c0.899-0.166,1.856-0.241,2.871-0.223c1.014,0.018,1.974,0.126,2.881,0.323c0.906,0.197,1.688,0.491,2.344,0.881  c0.657,0.388,1.175,0.865,1.555,1.432c0.381,0.566,0.564,1.239,0.551,2.019c-0.018,0.91-0.338,1.749-0.961,2.52  C946.75,513.886,946.019,514.445,945.181,514.795z");
    }
    if (position === 3) {
      path = paper.path("M898.432,672.629l-1.113,2.577l23.881,10.313l1.113-2.576L898.432,672.629z M902.014,684.758  c-1.357,0.632-2.433,1.798-3.227,3.498c-0.509,1.087-0.791,2.213-0.849,3.38c-0.057,1.168,0.146,2.361,0.608,3.582l2.33-0.289  c-0.444-1.014-0.663-1.942-0.655-2.789c0.008-0.846,0.199-1.67,0.574-2.474c0.529-1.134,1.248-1.855,2.153-2.168  s1.947-0.193,3.125,0.358l2.969,1.387c-1.008,0.189-1.871,0.597-2.594,1.221c-0.722,0.624-1.287,1.372-1.693,2.243  c-0.331,0.707-0.518,1.43-0.563,2.17c-0.044,0.739,0.065,1.458,0.328,2.154s0.679,1.343,1.247,1.938  c0.568,0.597,1.299,1.104,2.195,1.521c0.896,0.418,1.762,0.65,2.601,0.697c0.839,0.049,1.61-0.051,2.313-0.297  c0.702-0.244,1.329-0.619,1.881-1.123c0.55-0.503,0.985-1.095,1.305-1.778c0.407-0.871,0.612-1.787,0.616-2.747  c0.003-0.96-0.257-1.893-0.781-2.797l1.837,0.857l1.189-2.544l-11.942-5.579C905.028,684.268,903.371,684.126,902.014,684.758z   M914.194,691.648c0.522,0.732,0.814,1.513,0.877,2.334c0.063,0.822-0.083,1.611-0.437,2.369c-0.498,1.065-1.262,1.727-2.288,1.982  c-1.028,0.256-2.074,0.135-3.14-0.363c-1.064-0.497-1.822-1.219-2.274-2.166c-0.452-0.945-0.428-1.953,0.068-3.018  c0.354-0.757,0.867-1.375,1.538-1.855c0.67-0.479,1.468-0.749,2.389-0.81L914.194,691.648z M891.654,702.82  c-0.525,1.016-0.729,2.103-0.614,3.262c0.117,1.159,0.42,2.172,0.907,3.039l-2.371-1.272l-1.292,2.493l16.726,8.667l1.292-2.493  l-12.258-6.353c-0.491-0.749-0.825-1.614-1.006-2.596c-0.18-0.982-0.062-1.874,0.355-2.679c0.428-0.826,0.99-1.359,1.684-1.597  c0.694-0.237,1.596-0.069,2.703,0.505l11.911,6.173l1.293-2.493l-12.604-6.53C895.355,699.379,893.113,700.004,891.654,702.82z   M897.451,721.089c-0.876-0.876-1.89-1.645-3.04-2.304s-2.325-1.145-3.524-1.457c-1.199-0.313-2.35-0.409-3.451-0.292  c-1.102,0.12-2.119,0.457-3.054,1.016s-1.719,1.392-2.352,2.496c-0.62,1.083-0.934,2.169-0.943,3.257s0.214,2.138,0.669,3.147  s1.121,1.953,1.997,2.829c0.877,0.877,1.89,1.645,3.041,2.304c1.149,0.659,2.324,1.145,3.523,1.457  c1.199,0.313,2.356,0.413,3.468,0.301c1.113-0.109,2.137-0.446,3.07-1.005c0.936-0.559,1.712-1.379,2.332-2.462  c0.633-1.104,0.955-2.202,0.965-3.291c0.009-1.088-0.22-2.14-0.687-3.157C898.999,722.912,898.327,721.966,897.451,721.089z   M897.022,729.135c-0.4,0.7-0.929,1.206-1.587,1.521c-0.658,0.313-1.383,0.466-2.175,0.462c-0.791-0.004-1.617-0.146-2.475-0.428  c-0.856-0.282-1.704-0.661-2.539-1.141c-0.812-0.466-1.562-1-2.25-1.604c-0.687-0.604-1.227-1.243-1.621-1.917  c-0.393-0.675-0.62-1.374-0.685-2.102c-0.063-0.726,0.105-1.438,0.506-2.138c0.413-0.722,0.949-1.238,1.607-1.551  c0.658-0.313,1.378-0.471,2.158-0.473c0.78-0.003,1.604,0.142,2.474,0.429c0.868,0.288,1.708,0.665,2.521,1.13  c0.835,0.478,1.592,1.016,2.268,1.613c0.677,0.598,1.218,1.235,1.621,1.916c0.403,0.682,0.638,1.385,0.702,2.11  C897.611,727.69,897.436,728.413,897.022,729.135z M870.68,731.444c0.442,0.272,0.923,0.347,1.441,0.223  c0.52-0.124,0.914-0.408,1.187-0.852c0.271-0.442,0.346-0.923,0.222-1.442c-0.123-0.518-0.408-0.914-0.851-1.187  s-0.923-0.346-1.442-0.222c-0.519,0.124-0.915,0.408-1.186,0.852c-0.273,0.442-0.347,0.924-0.224,1.441  C869.952,730.777,870.237,731.173,870.68,731.444z M874.92,733.408l16.054,9.854l1.469-2.394l-16.053-9.854L874.92,733.408z   M886.453,745.308c0.076,0.267,0.102,0.553,0.073,0.859c-0.026,0.307-0.14,0.613-0.336,0.92c-0.295,0.459-0.67,0.682-1.123,0.669  c-0.454-0.013-0.987-0.216-1.598-0.609l-10.143-6.521l1.729-2.689l-2.1-1.35l-1.729,2.689l-4.331-2.783l-1.518,2.36l4.33,2.784  l-1.351,2.101l2.101,1.35l1.35-2.1l10.571,6.796c2.379,1.529,4.25,1.232,5.612-0.89c0.395-0.612,0.633-1.177,0.721-1.692  c0.085-0.518,0.078-1.009-0.024-1.477L886.453,745.308z M866.417,748.417c-1.442,0.399-2.696,1.371-3.761,2.916  c-0.681,0.988-1.146,2.052-1.395,3.193c-0.25,1.143-0.248,2.354,0.007,3.634l2.347,0.101c-0.271-1.073-0.334-2.025-0.186-2.858  c0.147-0.833,0.473-1.615,0.976-2.346c0.71-1.03,1.538-1.625,2.482-1.781c0.944-0.157,1.953,0.133,3.022,0.869l2.697,1.858  c-1.025,0.021-1.945,0.279-2.759,0.775c-0.815,0.496-1.496,1.14-2.042,1.932c-0.442,0.643-0.746,1.325-0.912,2.048  s-0.177,1.449-0.033,2.18s0.447,1.437,0.909,2.117c0.462,0.682,1.1,1.302,1.913,1.862c0.813,0.56,1.631,0.933,2.45,1.119  c0.818,0.186,1.596,0.216,2.329,0.089c0.733-0.125,1.414-0.391,2.041-0.796c0.626-0.405,1.152-0.918,1.58-1.539  c0.546-0.792,0.9-1.66,1.063-2.607c0.162-0.946,0.059-1.908-0.308-2.888l1.67,1.15l1.594-2.313l-10.855-7.478  C869.471,748.431,867.86,748.019,866.417,748.417z M874.319,755.181l2.969,2.045c0.394,0.811,0.554,1.628,0.479,2.448  c-0.075,0.822-0.349,1.577-0.823,2.266c-0.667,0.969-1.527,1.494-2.583,1.574c-1.056,0.083-2.067-0.21-3.035-0.877  c-0.969-0.667-1.597-1.504-1.886-2.512s-0.1-1.997,0.567-2.965c0.473-0.689,1.082-1.214,1.822-1.576S873.4,755.088,874.319,755.181z   M858.366,765.619c-0.099-0.477-0.149-0.967-0.15-1.469s0.058-0.977,0.177-1.421c0.119-0.445,0.309-0.847,0.572-1.201  c0.185-0.251,0.4-0.48,0.649-0.685l-2.321-1.715c-0.694,0.942-1.053,1.962-1.073,3.063c-0.02,1.101,0.189,2.185,0.629,3.252  l-2.416-1.784l-1.668,2.259l15.151,11.191l1.669-2.26l-10.761-7.946C858.618,766.525,858.467,766.098,858.366,765.619z");
    }
    if (position === 4) {
      path = paper.path("M733.145,901.953c-0.129-1.047-0.551-2.204-1.266-3.473l-9.24-16.37l-2.445,1.38  l1.342,2.378c-1.045-0.634-2.076-0.97-3.098-1.006c-1.02-0.035-1.95,0.182-2.788,0.655c-0.929,0.524-1.64,1.194-2.134,2.011  c-0.495,0.816-0.786,1.742-0.873,2.776c-0.088,1.035,0.034,2.153,0.369,3.353c0.333,1.2,0.857,2.433,1.574,3.702  c0.729,1.29,1.522,2.38,2.382,3.268c0.858,0.888,1.749,1.565,2.669,2.031c0.92,0.467,1.854,0.694,2.803,0.681  c0.947-0.014,1.885-0.282,2.814-0.806c0.859-0.485,1.527-1.205,2.005-2.161c0.476-0.955,0.715-1.987,0.718-3.092l1.553,2.751  c0.447,0.792,0.724,1.532,0.827,2.22c0.104,0.688,0.069,1.312-0.105,1.874c-0.177,0.563-0.466,1.069-0.867,1.52  c-0.402,0.45-0.888,0.837-1.452,1.155c-1.767,0.997-3.551,1.168-5.354,0.515l-0.048,2.533c1.24,0.346,2.379,0.419,3.417,0.223  c1.037-0.198,2.112-0.61,3.222-1.236c0.859-0.485,1.616-1.064,2.27-1.73c0.653-0.668,1.132-1.432,1.439-2.29  C733.184,903.954,733.273,903.001,733.145,901.953z M726.387,897.954c-0.372,0.927-0.955,1.615-1.747,2.062  c-0.68,0.384-1.358,0.547-2.029,0.494s-1.332-0.27-1.979-0.65c-0.648-0.382-1.269-0.911-1.861-1.593  c-0.593-0.68-1.139-1.462-1.638-2.346c-0.498-0.883-0.887-1.754-1.161-2.613c-0.276-0.858-0.413-1.67-0.411-2.433  c0.003-0.763,0.154-1.445,0.456-2.049c0.302-0.603,0.792-1.096,1.472-1.479c0.792-0.446,1.679-0.596,2.658-0.447  c0.98,0.147,1.832,0.495,2.558,1.041l4.104,7.269C726.9,896.113,726.76,897.027,726.387,897.954z M703.756,892.487l8.755,16.679  l2.485-1.305l-8.755-16.681L703.756,892.487z M702.24,889.561c0.51,0.158,0.993,0.117,1.454-0.125  c0.461-0.241,0.771-0.616,0.929-1.126c0.158-0.509,0.117-0.992-0.125-1.453c-0.24-0.462-0.616-0.771-1.125-0.93  c-0.51-0.158-0.993-0.117-1.454,0.125c-0.461,0.241-0.771,0.617-0.93,1.126c-0.157,0.509-0.116,0.993,0.125,1.454  C701.357,889.093,701.732,889.403,702.24,889.561z M698.467,896.082c-1.05-0.399-2.303-0.245-3.756,0.464  c-1.031,0.502-1.854,1.258-2.466,2.264c-0.61,1.008-0.98,2.006-1.108,2.992l-4.295-8.884l-2.524,1.23l11.396,23.384l2.523-1.229  l-6.048-12.411c0.054-0.894,0.3-1.788,0.742-2.683s1.07-1.542,1.883-1.938c0.838-0.407,1.609-0.509,2.313-0.304  c0.705,0.207,1.331,0.87,1.878,1.992l5.894,12.096l2.523-1.229l-6.253-12.831C700.418,897.452,699.517,896.481,698.467,896.082z   M686.198,919.603c-0.763,0.336-1.513,0.453-2.253,0.353c-0.739-0.1-1.441-0.372-2.106-0.819s-1.28-1.036-1.844-1.768  c-0.563-0.731-1.049-1.562-1.457-2.49c-0.407-0.927-0.689-1.841-0.843-2.739c-0.153-0.896-0.17-1.743-0.05-2.534  c0.12-0.792,0.393-1.493,0.819-2.106c0.426-0.614,1.019-1.088,1.78-1.423c0.666-0.293,1.328-0.421,1.983-0.383  c0.656,0.038,1.358,0.263,2.106,0.671l0.623-2.361c-0.842-0.424-1.737-0.684-2.687-0.778c-0.951-0.093-2.032,0.127-3.246,0.661  c-1.119,0.493-2.016,1.163-2.691,2.016c-0.678,0.852-1.141,1.815-1.393,2.892c-0.25,1.077-0.301,2.236-0.153,3.476  c0.147,1.242,0.506,2.504,1.07,3.79c0.565,1.286,1.255,2.403,2.07,3.352c0.814,0.948,1.706,1.699,2.674,2.253  s1.994,0.87,3.079,0.946s2.187-0.132,3.305-0.623c1.214-0.533,2.11-1.177,2.691-1.932c0.578-0.751,0.989-1.591,1.232-2.522  l-2.161-1.138C688.381,917.948,687.53,919.017,686.198,919.603z M666.895,910.634c-1.42-0.474-3.003-0.366-4.748,0.322  c-1.115,0.439-2.094,1.063-2.938,1.873c-0.846,0.809-1.52,1.814-2.021,3.02l1.891,1.393c0.374-1.042,0.854-1.868,1.441-2.478  c0.587-0.607,1.292-1.076,2.118-1.4c1.164-0.46,2.182-0.491,3.054-0.096c0.872,0.397,1.546,1.2,2.023,2.409l1.203,3.047  c-0.863-0.554-1.771-0.853-2.724-0.896c-0.954-0.043-1.877,0.111-2.771,0.465c-0.726,0.286-1.358,0.682-1.899,1.189  c-0.541,0.507-0.955,1.104-1.243,1.791c-0.288,0.687-0.431,1.441-0.427,2.265s0.188,1.694,0.55,2.613s0.832,1.684,1.408,2.295  c0.577,0.61,1.205,1.068,1.884,1.374c0.68,0.305,1.394,0.464,2.139,0.477s1.47-0.119,2.172-0.396  c0.894-0.353,1.673-0.878,2.335-1.571c0.662-0.694,1.113-1.55,1.354-2.568l0.744,1.888l2.612-1.031l-4.839-12.263  C669.421,912.349,668.315,911.107,666.895,910.634z M670.036,926.309c-0.52,0.642-1.169,1.114-1.945,1.422  c-1.095,0.432-2.103,0.388-3.024-0.134c-0.922-0.521-1.598-1.328-2.03-2.422c-0.432-1.094-0.485-2.139-0.163-3.137  s1.03-1.713,2.124-2.146c0.779-0.307,1.576-0.402,2.394-0.291c0.816,0.114,1.581,0.465,2.291,1.056l1.323,3.353  C670.88,924.903,670.557,925.669,670.036,926.309z M663.054,907.371c0.438,0.19,0.887,0.195,1.347,0.014  c0.437-0.172,0.754-0.479,0.957-0.923c0.202-0.443,0.218-0.882,0.046-1.318c-0.181-0.459-0.498-0.78-0.948-0.967  c-0.449-0.186-0.893-0.192-1.328-0.021c-0.461,0.181-0.784,0.491-0.976,0.93c-0.19,0.439-0.195,0.888-0.014,1.347  C662.31,906.868,662.615,907.181,663.054,907.371z M658.089,909.877c0.459-0.182,0.784-0.491,0.975-0.93  c0.19-0.439,0.2-0.876,0.028-1.313c-0.183-0.459-0.491-0.784-0.931-0.973c-0.438-0.19-0.888-0.195-1.347-0.014  c-0.436,0.172-0.755,0.48-0.957,0.923s-0.213,0.895-0.031,1.354c0.172,0.437,0.483,0.746,0.935,0.932  C657.211,910.042,657.654,910.049,658.089,909.877z M650.611,920.423c0.183-0.451,0.415-0.886,0.694-1.304  c0.278-0.416,0.592-0.776,0.939-1.08c0.348-0.303,0.729-0.53,1.146-0.678c0.293-0.104,0.601-0.174,0.921-0.204l-0.97-2.72  c-1.104,0.394-1.969,1.04-2.601,1.942c-0.631,0.902-1.063,1.918-1.293,3.049l-1.009-2.829l-2.646,0.943l6.327,17.743l2.646-0.942  l-4.493-12.6C650.315,921.316,650.427,920.876,650.611,920.423z M644.646,927.93c-0.449-1.412-1-2.649-1.651-3.711  c-0.65-1.061-1.388-1.918-2.209-2.57c-0.821-0.653-1.699-1.076-2.635-1.271c-0.935-0.194-1.91-0.129-2.926,0.194  c-0.941,0.3-1.747,0.855-2.415,1.669c-0.67,0.813-1.118,1.761-1.347,2.843l-0.778-2.576l-2.677,0.853l7.886,24.788l2.676-0.852  l-3.003-9.439c0.891,0.836,1.831,1.376,2.82,1.619c0.989,0.245,1.939,0.223,2.854-0.067c1.014-0.322,1.841-0.839,2.486-1.549  c0.644-0.71,1.112-1.567,1.404-2.575c0.291-1.006,0.395-2.131,0.313-3.373C645.361,930.669,645.095,929.342,644.646,927.93z   M642.395,934.151c-0.157,0.745-0.442,1.389-0.854,1.929c-0.413,0.541-0.988,0.929-1.729,1.164  c-0.838,0.267-1.728,0.223-2.669-0.133c-0.943-0.356-1.712-0.874-2.309-1.559l-2.613-8.214c0.093-0.901,0.425-1.758,0.996-2.566  c0.57-0.81,1.275-1.348,2.114-1.614c0.739-0.236,1.435-0.251,2.082-0.049c0.649,0.203,1.254,0.563,1.813,1.082  c0.559,0.518,1.06,1.177,1.505,1.977c0.444,0.799,0.82,1.682,1.128,2.649c0.307,0.966,0.512,1.909,0.616,2.832  C642.578,932.572,642.552,933.405,642.395,934.151z M626.386,935.45c-0.645-0.578-1.361-1-2.15-1.27  c-0.788-0.267-1.619-0.442-2.491-0.525s-1.685-0.189-2.435-0.32c-0.751-0.13-1.405-0.326-1.963-0.591  c-0.559-0.265-0.928-0.722-1.107-1.374c-0.2-0.728-0.084-1.427,0.353-2.1c0.434-0.673,1.152-1.148,2.155-1.425  c0.877-0.24,1.735-0.281,2.575-0.123c0.839,0.159,1.569,0.478,2.186,0.955l0.771-2.194c-0.845-0.522-1.784-0.869-2.815-1.044  c-1.033-0.174-2.15-0.096-3.354,0.236c-0.902,0.249-1.676,0.599-2.321,1.045c-0.645,0.448-1.157,0.967-1.532,1.556  c-0.379,0.59-0.616,1.216-0.718,1.877c-0.1,0.662-0.058,1.331,0.129,2.008c0.29,1.053,0.751,1.843,1.383,2.369  c0.631,0.528,1.339,0.92,2.124,1.175c0.783,0.256,1.612,0.425,2.485,0.508c0.872,0.083,1.685,0.189,2.436,0.319  c0.75,0.131,1.412,0.354,1.982,0.667c0.572,0.313,0.955,0.822,1.148,1.523c0.242,0.877,0.118,1.674-0.372,2.389  c-0.491,0.716-1.262,1.218-2.315,1.509c-0.978,0.27-1.94,0.299-2.889,0.088c-0.947-0.21-1.774-0.568-2.479-1.075l-0.825,2.29  c1.948,1.298,4.227,1.586,6.833,0.867c0.926-0.256,1.73-0.619,2.408-1.089c0.68-0.471,1.221-1.004,1.621-1.602  c0.402-0.597,0.652-1.252,0.752-1.967c0.101-0.716,0.047-1.449-0.16-2.201C627.5,936.855,627.03,936.028,626.386,935.45z   M608.905,945.477c-0.67,0.559-1.41,0.934-2.22,1.122c-0.811,0.191-1.577,0.198-2.3,0.021c-0.723-0.177-1.372-0.499-1.949-0.965  c-0.576-0.465-1.085-1.067-1.525-1.806c-0.44-0.736-0.78-1.56-1.02-2.465l11.884-2.791l-0.196-0.835  c-0.314-1.341-0.763-2.564-1.344-3.671c-0.581-1.104-1.28-2.023-2.093-2.753c-0.814-0.73-1.732-1.242-2.751-1.537  c-1.02-0.295-2.138-0.299-3.356-0.013c-1.168,0.272-2.147,0.771-2.942,1.492c-0.794,0.721-1.414,1.588-1.859,2.6  c-0.446,1.012-0.702,2.147-0.767,3.405c-0.067,1.257,0.055,2.545,0.363,3.859c0.333,1.418,0.817,2.674,1.453,3.766  c0.636,1.093,1.397,1.981,2.289,2.668c0.891,0.685,1.879,1.153,2.967,1.406c1.087,0.252,2.238,0.234,3.453-0.051  c1.24-0.291,2.313-0.817,3.216-1.574c0.903-0.761,1.613-1.683,2.135-2.767l-1.817-1.255  C610.115,944.206,609.574,944.919,608.905,945.477z M599.222,937.174c0.004-0.774,0.117-1.51,0.34-2.203  c0.223-0.692,0.572-1.303,1.047-1.828c0.476-0.524,1.116-0.884,1.923-1.072c0.831-0.196,1.581-0.171,2.251,0.071  c0.669,0.244,1.251,0.628,1.746,1.152c0.497,0.524,0.918,1.134,1.269,1.826c0.348,0.692,0.605,1.394,0.771,2.102l-9.15,2.149  C599.282,938.682,599.217,937.949,599.222,937.174z M590.49,932.864l-2.758,0.524l0.51,2.683c-0.787-0.935-1.657-1.583-2.611-1.944  c-0.956-0.361-1.907-0.452-2.852-0.271c-1.048,0.199-1.937,0.606-2.666,1.222c-0.73,0.616-1.302,1.399-1.716,2.352  s-0.656,2.051-0.723,3.294c-0.068,1.243,0.034,2.58,0.307,4.012c0.277,1.456,0.682,2.741,1.211,3.857  c0.53,1.117,1.156,2.043,1.879,2.778c0.723,0.736,1.535,1.25,2.438,1.541c0.902,0.291,1.877,0.338,2.925,0.139  c0.97-0.185,1.834-0.652,2.59-1.407c0.757-0.752,1.314-1.651,1.67-2.698l0.591,3.104c0.17,0.894,0.194,1.684,0.073,2.367  s-0.354,1.265-0.7,1.741c-0.346,0.476-0.783,0.864-1.308,1.162c-0.525,0.299-1.107,0.509-1.746,0.631  c-1.992,0.378-3.737-0.031-5.235-1.228l-0.854,2.387c1.063,0.724,2.119,1.157,3.166,1.303c1.046,0.144,2.195,0.098,3.447-0.141  c0.97-0.184,1.87-0.488,2.702-0.912c0.833-0.425,1.532-0.993,2.098-1.709c0.563-0.718,0.952-1.592,1.168-2.624  c0.213-1.033,0.183-2.266-0.089-3.695L590.49,932.864z M588.971,949.074c-0.649,0.759-1.42,1.224-2.314,1.394  c-0.766,0.146-1.46,0.087-2.08-0.179s-1.176-0.683-1.667-1.251s-0.911-1.269-1.255-2.104c-0.344-0.834-0.61-1.749-0.8-2.744  c-0.191-0.996-0.279-1.946-0.265-2.849c0.013-0.903,0.144-1.715,0.39-2.437c0.246-0.723,0.609-1.32,1.088-1.795  c0.479-0.476,1.101-0.786,1.867-0.933c0.893-0.17,1.781-0.026,2.661,0.427c0.881,0.454,1.577,1.057,2.091,1.806l1.561,8.199  C590.046,947.494,589.62,948.315,588.971,949.074z");
    }
    if (position === 5) {
      path = paper.path("M414.783,935.939l3.137,0.629l0.489-2.447l-3.135-0.629l1.011-5.048l-2.753-0.552  l-1.011,5.048l-2.447-0.49l-0.49,2.447l2.447,0.489l-2.469,12.323c-0.556,2.772,0.403,4.406,2.876,4.902  c0.713,0.143,1.326,0.159,1.839,0.051c0.512-0.11,0.967-0.297,1.365-0.563l-0.427-2.232c-0.221,0.168-0.478,0.296-0.773,0.382  s-0.622,0.093-0.979,0.022c-0.535-0.108-0.88-0.374-1.033-0.803c-0.153-0.427-0.159-0.996-0.017-1.709L414.783,935.939z   M405.282,931.598c-0.826-0.644-1.846-1.106-3.062-1.387c-0.912-0.211-1.758-0.273-2.539-0.186c-0.78,0.087-1.477,0.299-2.088,0.638  c-0.612,0.34-1.12,0.776-1.523,1.31c-0.404,0.534-0.684,1.144-0.842,1.827c-0.246,1.064-0.217,1.979,0.087,2.742  c0.305,0.765,0.741,1.445,1.31,2.043c0.569,0.599,1.218,1.142,1.945,1.63c0.729,0.488,1.391,0.968,1.989,1.44  c0.598,0.471,1.074,0.98,1.428,1.529c0.354,0.55,0.449,1.179,0.285,1.888c-0.204,0.887-0.693,1.527-1.464,1.923  c-0.772,0.396-1.69,0.471-2.754,0.226c-0.988-0.229-1.85-0.66-2.583-1.297c-0.733-0.636-1.29-1.345-1.67-2.127l-1.815,1.622  c1.098,2.069,2.963,3.407,5.599,4.015c0.937,0.216,1.815,0.279,2.637,0.188s1.55-0.304,2.188-0.636  c0.639-0.334,1.17-0.791,1.599-1.372c0.428-0.582,0.729-1.253,0.904-2.014c0.252-1.088,0.231-2.041-0.061-2.855  c-0.293-0.814-0.722-1.528-1.288-2.139c-0.565-0.61-1.213-1.161-1.94-1.648c-0.729-0.488-1.392-0.967-1.989-1.439  c-0.6-0.472-1.081-0.956-1.446-1.454s-0.472-1.075-0.32-1.734c0.169-0.735,0.606-1.294,1.309-1.68  c0.702-0.385,1.56-0.461,2.574-0.227c0.886,0.204,1.66,0.577,2.323,1.116c0.662,0.54,1.151,1.167,1.468,1.88l1.722-1.563  C406.768,932.995,406.108,932.243,405.282,931.598z M389.427,927.554l-3.639,13.399c-0.604,0.644-1.363,1.145-2.277,1.503  c-0.915,0.358-1.821,0.415-2.721,0.171c-0.874-0.237-1.508-0.665-1.901-1.284c-0.396-0.619-0.43-1.531-0.103-2.734l3.526-12.985  l-2.71-0.735l-3.741,13.775c-0.449,1.656-0.411,2.979,0.114,3.971c0.524,0.991,1.565,1.698,3.122,2.121  c1.129,0.306,2.231,0.288,3.308-0.052c1.076-0.341,1.998-0.838,2.77-1.491l-0.686,2.521l2.71,0.736l4.938-18.18L389.427,927.554z   M374.033,915.695l-7.568,24.888l2.687,0.817l7.569-24.889L374.033,915.695z M359.207,921.174c0.736-0.315,1.598-0.31,2.584,0.02  c0.863,0.287,1.6,0.731,2.209,1.332c0.607,0.601,1.034,1.271,1.281,2.01l1.862-1.395c-0.411-0.903-0.997-1.716-1.757-2.436  c-0.761-0.719-1.733-1.276-2.917-1.671c-0.888-0.296-1.726-0.438-2.51-0.426c-0.786,0.012-1.499,0.157-2.141,0.438  c-0.642,0.279-1.188,0.666-1.641,1.159s-0.789,1.072-1.011,1.738c-0.346,1.035-0.402,1.948-0.173,2.737  c0.23,0.79,0.601,1.509,1.11,2.158c0.51,0.65,1.104,1.252,1.782,1.807c0.678,0.556,1.293,1.097,1.844,1.622  c0.55,0.526,0.977,1.079,1.276,1.658c0.3,0.58,0.335,1.216,0.104,1.906c-0.288,0.863-0.834,1.455-1.64,1.775  s-1.728,0.309-2.763-0.037c-0.963-0.32-1.778-0.832-2.448-1.535c-0.669-0.703-1.157-1.461-1.461-2.275l-1.961,1.442  c0.896,2.163,2.626,3.671,5.191,4.526c0.912,0.304,1.781,0.449,2.61,0.441c0.826-0.013,1.572-0.154,2.238-0.426  c0.666-0.272,1.239-0.677,1.721-1.215c0.479-0.538,0.844-1.179,1.091-1.918c0.354-1.061,0.423-2.011,0.209-2.85  c-0.214-0.838-0.574-1.589-1.079-2.251c-0.506-0.662-1.098-1.27-1.775-1.825c-0.679-0.555-1.294-1.096-1.845-1.621  s-0.984-1.055-1.301-1.584c-0.316-0.53-0.368-1.116-0.154-1.759C357.985,922.007,358.472,921.49,359.207,921.174z M351.01,918.166  c-0.271-1.06-0.746-1.996-1.429-2.809c-0.683-0.813-1.609-1.441-2.78-1.881c-1.122-0.423-2.214-0.556-3.275-0.4  c-1.062,0.156-2.059,0.53-2.993,1.123c-0.934,0.592-1.778,1.393-2.534,2.399c-0.756,1.009-1.371,2.145-1.848,3.409  c-0.514,1.364-0.811,2.675-0.892,3.937c-0.081,1.261,0.057,2.426,0.415,3.489c0.356,1.066,0.917,2.008,1.68,2.821  c0.762,0.815,1.728,1.443,2.896,1.883c1.19,0.448,2.375,0.609,3.55,0.483c1.173-0.127,2.276-0.496,3.313-1.106l-0.81-2.055  c-0.826,0.495-1.672,0.787-2.539,0.877s-1.691-0.012-2.469-0.305c-0.779-0.294-1.419-0.715-1.92-1.265  c-0.502-0.551-0.862-1.181-1.081-1.888c-0.22-0.708-0.308-1.492-0.262-2.35c0.045-0.857,0.221-1.729,0.526-2.614l11.423,4.303  l0.303-0.803c0.486-1.29,0.795-2.556,0.93-3.797C351.347,920.377,351.279,919.227,351.01,918.166z M348.611,921.117  c-0.096,0.77-0.272,1.495-0.529,2.177l-8.797-3.313c0.272-0.647,0.625-1.291,1.062-1.935c0.435-0.642,0.938-1.188,1.51-1.64  c0.572-0.453,1.201-0.764,1.888-0.937c0.688-0.171,1.419-0.11,2.194,0.182c0.799,0.301,1.409,0.738,1.829,1.313  s0.688,1.218,0.809,1.93C348.695,919.607,348.706,920.347,348.611,921.117z M332.608,908.651c-0.577-0.769-1.355-1.362-2.336-1.78  c-0.885-0.377-1.833-0.491-2.843-0.342c-1.01,0.148-1.999,0.596-2.967,1.342l3.919-9.098l-2.583-1.102l-10.197,23.932l2.584,1.101  l1.055-2.476c0.123,1.099,0.478,2.084,1.064,2.955c0.586,0.87,1.332,1.501,2.238,1.887c0.977,0.416,1.938,0.572,2.885,0.467  c0.947-0.106,1.858-0.445,2.737-1.018c0.877-0.573,1.689-1.357,2.438-2.354c0.748-0.995,1.413-2.175,1.994-3.538  c0.571-1.339,0.958-2.629,1.162-3.871c0.204-1.241,0.207-2.377,0.011-3.408C333.572,910.319,333.185,909.42,332.608,908.651z   M330.785,914.72c-0.189,0.909-0.482,1.83-0.881,2.763c-0.397,0.932-0.855,1.775-1.374,2.529c-0.519,0.755-1.081,1.363-1.686,1.826  c-0.605,0.463-1.24,0.763-1.905,0.904c-0.665,0.141-1.354,0.06-2.068-0.245c-0.81-0.345-1.461-0.948-1.952-1.807  c-0.492-0.86-0.742-1.743-0.748-2.651l3.378-7.928c0.659-0.623,1.475-1.067,2.445-1.332c0.972-0.266,1.861-0.226,2.672,0.121  c0.714,0.303,1.25,0.743,1.609,1.32s0.582,1.244,0.667,2.002C331.029,912.98,330.976,913.812,330.785,914.72z M316.473,903.984  c-0.178-1.079-0.573-2.054-1.185-2.922c-0.61-0.867-1.48-1.57-2.609-2.109c-1.082-0.518-2.158-0.742-3.229-0.677  c-1.071,0.064-2.098,0.353-3.078,0.863c-0.98,0.513-1.89,1.238-2.729,2.178c-0.839,0.938-1.549,2.019-2.131,3.238  c-0.628,1.315-1.035,2.598-1.223,3.848c-0.188,1.25-0.149,2.421,0.116,3.513s0.743,2.076,1.435,2.953  c0.69,0.877,1.6,1.584,2.726,2.122c1.149,0.549,2.314,0.809,3.495,0.781c1.18-0.026,2.311-0.301,3.395-0.82l-0.632-2.117  c-0.864,0.424-1.731,0.642-2.604,0.659c-0.872,0.015-1.685-0.156-2.434-0.515c-0.752-0.358-1.354-0.833-1.807-1.424  c-0.453-0.59-0.759-1.248-0.917-1.972c-0.159-0.724-0.179-1.511-0.061-2.362s0.367-1.706,0.747-2.561l11.017,5.258l0.369-0.774  c0.594-1.242,1.01-2.478,1.248-3.703C316.62,906.214,316.651,905.063,316.473,903.984z M313.832,906.722  c-0.16,0.759-0.398,1.468-0.712,2.123l-8.482-4.049c0.325-0.622,0.732-1.234,1.221-1.837c0.488-0.604,1.036-1.105,1.645-1.506  c0.606-0.401,1.261-0.658,1.96-0.771c0.698-0.112,1.423,0.011,2.171,0.366c0.771,0.368,1.341,0.857,1.711,1.465  c0.37,0.608,0.583,1.272,0.642,1.992C314.045,905.224,313.993,905.963,313.832,906.722z M301.777,891.025  c0.462,0.237,0.948,0.275,1.455,0.112c0.508-0.164,0.881-0.476,1.119-0.938c0.238-0.463,0.275-0.948,0.113-1.456  c-0.164-0.507-0.477-0.88-0.938-1.118s-0.947-0.275-1.455-0.113c-0.508,0.164-0.881,0.477-1.118,0.938  c-0.238,0.463-0.276,0.948-0.113,1.455C301.002,890.414,301.314,890.787,301.777,891.025z M299.314,892.828l-8.621,16.748  l2.497,1.285l8.621-16.748L299.314,892.828z M295.672,882.775l-12.324,22.907l2.473,1.33l12.324-22.907L295.672,882.775z");
    }
    if (position === 6) {
      path = paper.path("M161.564,781.99c-1.061-0.293-2.163-0.358-3.307-0.198l2.328-1.897l-1.775-2.176  l-14.599,11.904l1.775,2.175l10.367-8.454c0.417-0.104,0.869-0.146,1.357-0.125c0.486,0.022,0.974,0.096,1.461,0.218  c0.486,0.124,0.931,0.298,1.333,0.523c0.4,0.226,0.742,0.51,1.021,0.853c0.196,0.242,0.363,0.509,0.5,0.801l2.237-1.824  C163.524,782.882,162.624,782.282,161.564,781.99z M153.742,772.901c0.068-1.495-0.465-2.989-1.602-4.481  c-0.727-0.954-1.594-1.726-2.601-2.318c-1.008-0.594-2.159-0.969-3.455-1.125l-0.826,2.198c1.104,0.076,2.029,0.315,2.775,0.714  c0.745,0.399,1.387,0.951,1.925,1.657c0.758,0.995,1.064,1.967,0.921,2.914c-0.146,0.947-0.735,1.814-1.77,2.603l-2.604,1.984  c0.299-0.979,0.34-1.934,0.123-2.863c-0.218-0.93-0.618-1.775-1.201-2.542c-0.473-0.62-1.027-1.122-1.661-1.504  c-0.635-0.383-1.322-0.619-2.061-0.71c-0.739-0.091-1.504-0.022-2.295,0.205c-0.792,0.227-1.58,0.639-2.366,1.238  c-0.786,0.598-1.396,1.258-1.826,1.979c-0.432,0.722-0.703,1.45-0.811,2.188c-0.109,0.737-0.068,1.466,0.121,2.187  c0.19,0.722,0.514,1.382,0.972,1.982c0.583,0.764,1.299,1.371,2.146,1.82c0.849,0.447,1.795,0.649,2.84,0.605l-1.612,1.229  l1.702,2.233l10.484-7.988C152.779,775.798,153.673,774.396,153.742,772.901z M144.853,778.306l-2.868,2.186  c-0.892,0.122-1.718,0.019-2.475-0.308c-0.757-0.325-1.389-0.821-1.896-1.486c-0.713-0.935-0.943-1.917-0.693-2.946  c0.251-1.029,0.844-1.899,1.779-2.612c0.935-0.712,1.927-1.049,2.975-1.01c1.048,0.04,1.928,0.527,2.641,1.462  c0.507,0.665,0.816,1.407,0.931,2.225C145.358,776.631,145.228,777.462,144.853,778.306z M140.72,763.014  c0.83-0.945,1.435-1.906,1.814-2.885c0.379-0.978,0.527-1.946,0.445-2.904c-0.082-0.957-0.429-1.873-1.039-2.746  c-0.551-0.789-1.294-1.388-2.229-1.797c-0.937-0.41-2.012-0.554-3.229-0.434l8.145-5.641l-1.608-2.303l-21.326,14.896l1.609,2.303  l2.206-1.541c-0.478,0.997-0.698,2.021-0.662,3.07c0.035,1.05,0.335,1.978,0.899,2.786c0.607,0.87,1.341,1.512,2.199,1.924  c0.859,0.412,1.813,0.607,2.86,0.587c1.047-0.021,2.152-0.256,3.314-0.704c1.161-0.447,2.35-1.095,3.564-1.944  C138.877,764.848,139.889,763.958,140.72,763.014z M133.504,764.702c-0.839,0.365-1.637,0.584-2.396,0.655  c-0.758,0.071-1.457-0.01-2.095-0.241c-0.639-0.234-1.18-0.668-1.625-1.304c-0.504-0.722-0.738-1.577-0.699-2.567  c0.038-0.99,0.294-1.872,0.77-2.646l7.065-4.936c0.89-0.18,1.816-0.124,2.78,0.166s1.698,0.796,2.202,1.517  c0.444,0.638,0.666,1.295,0.665,1.976c-0.001,0.68-0.165,1.362-0.494,2.05c-0.329,0.687-0.815,1.366-1.457,2.036  c-0.643,0.67-1.379,1.295-2.21,1.875C135.178,763.864,134.343,764.337,133.504,764.702z M129.204,744.189  c0.481,0.074,0.958,0.198,1.428,0.375c0.47,0.176,0.893,0.396,1.268,0.665c0.376,0.269,0.684,0.587,0.925,0.959  c0.17,0.262,0.307,0.544,0.41,0.849l2.421-1.57c-0.637-0.98-1.467-1.676-2.488-2.081c-1.023-0.407-2.111-0.592-3.266-0.556  l2.521-1.634l-1.528-2.356l-15.804,10.25l1.528,2.356l11.223-7.279C128.267,744.107,128.721,744.115,129.204,744.189z   M126.859,733.888c0.307-1.081,0.041-2.314-0.792-3.7c-0.592-0.983-1.416-1.734-2.473-2.256c-1.057-0.521-2.083-0.802-3.078-0.842  l8.47-5.061l-1.447-2.406l-22.289,13.411l1.447,2.406l11.83-7.117c0.896-0.026,1.808,0.142,2.738,0.503  c0.929,0.359,1.628,0.929,2.095,1.705c0.48,0.797,0.648,1.556,0.506,2.275c-0.145,0.721-0.75,1.402-1.819,2.045l-11.529,6.938  l1.449,2.406l12.229-7.359C125.666,735.952,126.553,734.969,126.859,733.888z M116.523,707.407c-0.128,0.47-0.08,0.91,0.146,1.321  c0.235,0.433,0.584,0.718,1.043,0.852c0.458,0.135,0.893,0.09,1.304-0.135c0.433-0.236,0.717-0.585,0.853-1.043  c0.135-0.459,0.083-0.905-0.153-1.338c-0.224-0.411-0.569-0.689-1.034-0.835c-0.465-0.146-0.915-0.101-1.348,0.136  C116.921,706.59,116.651,706.938,116.523,707.407z M117.434,716.311l-12.184,6.657c-0.883,0.01-1.771-0.19-2.662-0.602  c-0.893-0.412-1.562-1.027-2.007-1.843c-0.436-0.795-0.565-1.55-0.393-2.263c0.172-0.714,0.808-1.37,1.902-1.968l11.807-6.452  l-1.347-2.464l-12.526,6.844c-1.506,0.823-2.434,1.768-2.785,2.833c-0.351,1.066-0.14,2.307,0.634,3.722  c0.561,1.027,1.337,1.81,2.328,2.35s1.988,0.861,2.993,0.965l-2.293,1.253l1.349,2.464l16.529-9.031L117.434,716.311z   M119.922,714.683c0.224,0.41,0.569,0.689,1.034,0.835c0.464,0.146,0.901,0.107,1.313-0.117c0.434-0.236,0.714-0.59,0.842-1.061  c0.128-0.469,0.08-0.91-0.144-1.321c-0.237-0.434-0.585-0.717-1.043-0.852c-0.459-0.135-0.905-0.083-1.338,0.153  c-0.411,0.224-0.685,0.565-0.818,1.023C119.633,713.803,119.685,714.249,119.922,714.683z M108.822,705.572l2.229-1.126  l-1.442-2.854l2.055-1.038c0.812-0.411,1.532-0.556,2.16-0.437c0.63,0.12,1.119,0.527,1.472,1.224  c0.315,0.626,0.336,1.3,0.061,2.022l2.269,0.078c0.183-0.617,0.232-1.226,0.148-1.823c-0.084-0.599-0.267-1.176-0.548-1.733  c-0.669-1.322-1.608-2.145-2.819-2.465s-2.547-0.11-4.009,0.628l-2.054,1.038l-1.126-2.228l-2.229,1.126l1.126,2.228l-14.584,7.37  l1.267,2.507l14.584-7.371L108.822,705.572z M100.702,693.298c0.468,0.137,0.924,0.324,1.366,0.561  c0.443,0.234,0.833,0.511,1.17,0.824c0.338,0.315,0.601,0.673,0.79,1.072c0.135,0.282,0.233,0.581,0.297,0.896l2.606-1.238  c-0.503-1.058-1.232-1.854-2.194-2.391c-0.961-0.537-2.016-0.864-3.163-0.979l2.712-1.289l-1.205-2.536l-17.016,8.083l1.205,2.535  l12.083-5.74C99.784,693.093,100.233,693.16,100.702,693.298z M84.543,687.013c-0.668-0.56-1.168-1.221-1.499-1.984  c-0.332-0.765-0.475-1.517-0.428-2.26c0.045-0.741,0.245-1.439,0.602-2.09c0.356-0.649,0.857-1.258,1.505-1.821  c0.648-0.564,1.396-1.046,2.244-1.441l4.86,11.198l0.786-0.343c1.265-0.549,2.389-1.207,3.373-1.976s1.764-1.618,2.338-2.549  c0.572-0.931,0.913-1.924,1.022-2.98c0.109-1.056-0.086-2.159-0.584-3.306c-0.478-1.101-1.141-1.977-1.992-2.63  c-0.851-0.654-1.814-1.11-2.89-1.368c-1.076-0.257-2.238-0.307-3.487-0.148c-1.25,0.158-2.494,0.508-3.733,1.046  c-1.336,0.579-2.485,1.279-3.447,2.099c-0.963,0.821-1.702,1.729-2.218,2.728c-0.517,0.998-0.803,2.056-0.856,3.169  c-0.054,1.116,0.167,2.245,0.664,3.391c0.507,1.169,1.215,2.13,2.124,2.883c0.908,0.754,1.941,1.29,3.1,1.609l0.913-2.013  C86.01,687.978,85.211,687.573,84.543,687.013z M90.988,676.01c0.765-0.134,1.508-0.153,2.229-0.057  c0.721,0.096,1.383,0.33,1.985,0.704c0.601,0.374,1.066,0.94,1.396,1.701c0.341,0.784,0.45,1.526,0.33,2.229  c-0.121,0.701-0.395,1.343-0.823,1.924c-0.428,0.581-0.952,1.104-1.57,1.571c-0.62,0.466-1.265,0.845-1.932,1.134l-3.743-8.622  C89.515,676.338,90.224,676.145,90.988,676.01z M93.448,666.012l-16.178,1.215l12.778-9.978l-1.102-2.836l-15.333,12.559  l1.116,2.872l19.805-1.032L93.448,666.012z");
    }
    if (position === 7) {
      path = paper.path("M68.583,482.478l2.688,0.101l0.105-2.806l-25.995-0.968l-0.104,2.807l9.899,0.369  c-1.087,0.531-1.913,1.229-2.479,2.093c-0.565,0.862-0.866,1.775-0.902,2.736c-0.04,1.066,0.165,2.023,0.615,2.872  c0.449,0.85,1.099,1.582,1.947,2.199c0.85,0.617,1.878,1.099,3.088,1.442c1.212,0.345,2.544,0.544,3.998,0.598  c1.481,0.055,2.831-0.051,4.052-0.317c1.22-0.268,2.274-0.67,3.167-1.21c0.892-0.538,1.586-1.216,2.085-2.029  c0.498-0.814,0.767-1.753,0.807-2.819c0.037-0.987-0.214-1.933-0.753-2.838C70.264,483.803,69.524,483.059,68.583,482.478z   M68.428,488.735c-0.41,0.544-0.954,0.991-1.63,1.344c-0.677,0.353-1.467,0.603-2.37,0.751c-0.904,0.148-1.862,0.205-2.875,0.167  c-1.014-0.038-1.971-0.164-2.874-0.38s-1.679-0.524-2.327-0.926c-0.647-0.4-1.157-0.889-1.525-1.461  c-0.369-0.573-0.539-1.249-0.511-2.029c0.033-0.909,0.371-1.742,1.011-2.499s1.382-1.301,2.227-1.634l8.652,0.321  c0.818,0.396,1.512,0.992,2.08,1.794s0.836,1.657,0.802,2.566C69.058,487.53,68.838,488.191,68.428,488.735z M70.162,462.299  c-0.855-0.719-1.866-1.289-3.033-1.708c-1.166-0.419-2.41-0.682-3.732-0.787c-1.321-0.104-2.592-0.043-3.81,0.187  s-2.301,0.632-3.246,1.209c-0.946,0.576-1.722,1.316-2.329,2.22c-0.605,0.905-0.961,1.991-1.062,3.261  c-0.1,1.245,0.078,2.361,0.534,3.35s1.105,1.842,1.948,2.561s1.848,1.289,3.014,1.707c1.167,0.42,2.41,0.683,3.732,0.787  c1.322,0.105,2.592,0.043,3.81-0.186c1.219-0.229,2.308-0.632,3.266-1.207c0.959-0.575,1.742-1.315,2.348-2.22  c0.606-0.902,0.96-1.977,1.06-3.221c0.101-1.269-0.077-2.398-0.532-3.389C71.674,463.874,71.018,463.02,70.162,462.299z   M70.172,468.053c-0.064,0.805-0.326,1.487-0.789,2.05c-0.462,0.564-1.052,1.013-1.771,1.347c-0.717,0.334-1.523,0.557-2.42,0.668  c-0.895,0.11-1.822,0.128-2.781,0.052c-0.934-0.075-1.84-0.238-2.72-0.491c-0.88-0.252-1.641-0.6-2.283-1.042  c-0.643-0.441-1.148-0.978-1.516-1.606s-0.519-1.346-0.455-2.149c0.066-0.829,0.33-1.526,0.792-2.089  c0.462-0.563,1.045-1.012,1.75-1.347s1.512-0.559,2.42-0.668c0.908-0.11,1.829-0.128,2.763-0.055  c0.96,0.076,1.873,0.241,2.738,0.492c0.867,0.251,1.629,0.6,2.284,1.042c0.657,0.443,1.168,0.98,1.535,1.609  C70.088,466.494,70.238,467.224,70.172,468.053z M57.863,433.782c-0.871,0.646-1.399,1.664-1.584,3.056  c-0.073,0.568-0.051,1.128,0.073,1.682c0.123,0.555,0.31,1.083,0.558,1.589c0.248,0.505,0.547,0.964,0.898,1.378  c0.353,0.414,0.72,0.764,1.102,1.05c-1.005,0.051-1.862,0.39-2.574,1.017s-1.149,1.546-1.31,2.757  c-0.073,0.568-0.051,1.129,0.073,1.683s0.311,1.078,0.561,1.568c0.249,0.492,0.537,0.938,0.865,1.334  c0.328,0.397,0.647,0.709,0.958,0.934l-2.663-0.393l-0.367,2.784l18.674,2.471l0.368-2.784l-13.688-1.812  c-0.693-0.508-1.301-1.168-1.823-1.98c-0.521-0.813-0.728-1.628-0.62-2.448c0.119-0.897,0.478-1.521,1.074-1.873  c0.598-0.351,1.399-0.46,2.404-0.327l13.532,1.79l0.368-2.784l-13.688-1.81c-0.362-0.231-0.698-0.519-1.007-0.861  c-0.308-0.342-0.581-0.706-0.819-1.092c-0.236-0.385-0.412-0.795-0.524-1.23c-0.113-0.435-0.144-0.857-0.088-1.271  c0.118-0.902,0.477-1.523,1.072-1.864c0.597-0.34,1.397-0.444,2.402-0.312l13.532,1.79l0.367-2.783l-14.268-1.887  C60.022,432.927,58.735,433.137,57.863,433.782z M58.356,427.025l18.562,3.215l0.479-2.768l-18.561-3.215L58.356,427.025z   M53.691,426.771c0.514,0.089,0.986-0.021,1.422-0.328c0.437-0.308,0.698-0.717,0.787-1.229c0.088-0.512-0.021-0.986-0.328-1.421  c-0.306-0.436-0.716-0.699-1.229-0.787c-0.512-0.089-0.986,0.021-1.422,0.327s-0.698,0.717-0.787,1.229  c-0.089,0.512,0.021,0.985,0.328,1.422C52.769,426.42,53.179,426.682,53.691,426.771z M60.964,410.709  c-0.229,1.121-0.129,2.222,0.3,3.305s0.996,1.976,1.702,2.677l-2.629-0.577l-0.563,2.751l18.456,3.769l0.563-2.751l-13.526-2.763  c-0.677-0.586-1.234-1.327-1.676-2.223s-0.571-1.786-0.39-2.674c0.187-0.913,0.581-1.578,1.184-1.996s1.516-0.502,2.739-0.252  l13.145,2.686l0.563-2.75l-13.909-2.841C63.585,406.388,61.599,407.601,60.964,410.709z M67.155,390.421  c-1.209,0.883-2.038,2.235-2.489,4.056c-0.288,1.164-0.348,2.324-0.179,3.48c0.171,1.157,0.6,2.289,1.289,3.396l2.23-0.733  c-0.632-0.908-1.026-1.779-1.182-2.61c-0.156-0.831-0.129-1.677,0.085-2.538c0.3-1.215,0.864-2.063,1.693-2.543  s1.874-0.564,3.136-0.252l3.181,0.787c-0.952,0.381-1.721,0.947-2.31,1.699c-0.588,0.752-0.998,1.594-1.229,2.528  c-0.188,0.757-0.232,1.503-0.132,2.236c0.099,0.735,0.346,1.419,0.737,2.051c0.394,0.634,0.927,1.188,1.599,1.661  c0.673,0.476,1.489,0.831,2.448,1.068c0.959,0.238,1.854,0.298,2.687,0.183c0.832-0.115,1.569-0.361,2.211-0.738  c0.644-0.377,1.186-0.864,1.628-1.466c0.443-0.601,0.756-1.267,0.938-1.999c0.23-0.933,0.256-1.871,0.073-2.813  c-0.182-0.942-0.617-1.806-1.307-2.593l1.969,0.487l0.676-2.726l-12.797-3.167C70.016,389.357,68.364,389.539,67.155,390.421z   M80.436,394.829c0.654,0.619,1.092,1.326,1.313,2.121c0.22,0.795,0.229,1.598,0.028,2.41c-0.281,1.141-0.902,1.937-1.861,2.386  s-2.01,0.533-3.15,0.25s-2.024-0.844-2.651-1.687c-0.625-0.841-0.798-1.832-0.515-2.974c0.201-0.811,0.585-1.517,1.15-2.118  c0.564-0.6,1.295-1.018,2.187-1.255L80.436,394.829z M69.932,375.063c-0.321,1.099-0.311,2.205,0.027,3.319  c0.339,1.115,0.831,2.051,1.477,2.808l-2.573-0.791l-0.785,2.696l18.084,5.273l0.785-2.696l-13.254-3.865  c-0.626-0.641-1.121-1.425-1.486-2.354c-0.365-0.928-0.421-1.827-0.168-2.696c0.261-0.894,0.709-1.525,1.344-1.892  c0.635-0.367,1.552-0.376,2.75-0.026l12.879,3.756l0.785-2.694l-13.628-3.975C72.899,370.972,70.82,372.018,69.932,375.063z   M92.981,363.995l-2.269,0.16c0.141,0.239,0.237,0.509,0.288,0.813c0.051,0.305,0.019,0.629-0.095,0.975  c-0.169,0.519-0.475,0.829-0.918,0.931c-0.442,0.102-1.009,0.039-1.698-0.187l-11.458-3.753l0.996-3.039l-2.372-0.777l-0.995,3.039  l-4.894-1.602l-0.874,2.668l4.894,1.603l-0.777,2.372l2.372,0.777l0.777-2.372l11.942,3.911c2.688,0.88,4.424,0.122,5.208-2.275  c0.227-0.691,0.315-1.298,0.269-1.822C93.329,364.895,93.197,364.421,92.981,363.995z");
    }
    if (position === 8) {
      path = paper.path("M130.764,236.193l21.054,15.277l1.649-2.271l-21.054-15.277L130.764,236.193z   M160.32,233.25c0.231,0.935,0.264,1.83,0.096,2.685s-0.507,1.613-1.016,2.271c-0.509,0.659-1.099,1.147-1.771,1.465  c-0.672,0.318-1.38,0.478-2.121,0.481s-1.515-0.143-2.322-0.438c-0.807-0.294-1.59-0.717-2.346-1.269l7.461-9.662l-0.679-0.524  c-1.09-0.842-2.21-1.509-3.358-2c-1.147-0.491-2.268-0.763-3.36-0.817c-1.092-0.053-2.126,0.128-3.104,0.542  c-0.978,0.415-1.848,1.117-2.613,2.107c-0.732,0.949-1.179,1.954-1.342,3.014c-0.162,1.061-0.096,2.125,0.197,3.191  c0.294,1.066,0.811,2.108,1.553,3.125c0.741,1.018,1.648,1.94,2.718,2.766c1.152,0.89,2.319,1.558,3.502,2.005  c1.183,0.447,2.334,0.656,3.458,0.626c1.123-0.029,2.188-0.289,3.189-0.78c1.002-0.49,1.885-1.229,2.647-2.217  c0.779-1.008,1.279-2.092,1.5-3.251c0.224-1.159,0.193-2.323-0.087-3.492L160.32,233.25z M147.665,235.6  c-0.485-0.604-0.861-1.245-1.125-1.924c-0.265-0.679-0.378-1.371-0.341-2.079c0.036-0.708,0.309-1.389,0.814-2.045  c0.522-0.676,1.119-1.131,1.792-1.364c0.672-0.233,1.366-0.302,2.082-0.208c0.716,0.095,1.427,0.301,2.135,0.618  c0.707,0.318,1.35,0.699,1.925,1.144l-5.743,7.439C148.664,236.731,148.151,236.204,147.665,235.6z M152.944,219.069l14.561,11.952  l1.781-2.17l-14.561-11.952L152.944,219.069z M149.011,216.546c0.401,0.331,0.868,0.469,1.398,0.417  c0.53-0.052,0.961-0.279,1.291-0.681c0.329-0.402,0.469-0.868,0.417-1.399c-0.053-0.53-0.279-0.96-0.682-1.291  c-0.401-0.33-0.868-0.469-1.398-0.417c-0.531,0.053-0.961,0.279-1.291,0.681c-0.331,0.402-0.47,0.869-0.417,1.399  C148.382,215.786,148.61,216.215,149.011,216.546z M159.879,199.839l7.462,6.514c-1.179-0.27-2.26-0.247-3.243,0.068  c-0.981,0.315-1.791,0.835-2.423,1.56c-0.702,0.803-1.145,1.676-1.329,2.619c-0.184,0.944-0.141,1.921,0.13,2.935  c0.272,1.013,0.77,2.035,1.493,3.063c0.724,1.029,1.634,2.021,2.731,2.979c1.116,0.975,2.232,1.742,3.349,2.302  s2.189,0.911,3.222,1.053s1.998,0.053,2.898-0.266c0.899-0.319,1.7-0.88,2.4-1.683c0.65-0.744,1.05-1.638,1.2-2.68  c0.15-1.041,0.043-2.085-0.323-3.129l2.027,1.77l1.849-2.114l-19.597-17.107L159.879,199.839z M169.132,207.915l6.521,5.694  c0.388,0.822,0.551,1.723,0.487,2.704c-0.062,0.981-0.393,1.814-0.991,2.5c-0.513,0.587-1.1,0.964-1.76,1.129  c-0.661,0.165-1.366,0.171-2.113,0.019c-0.748-0.152-1.519-0.454-2.313-0.907c-0.796-0.453-1.575-1.013-2.339-1.68  c-0.765-0.667-1.43-1.368-1.995-2.104c-0.566-0.735-0.976-1.463-1.227-2.183c-0.252-0.72-0.341-1.419-0.267-2.097  c0.073-0.677,0.367-1.31,0.88-1.898c0.598-0.685,1.384-1.121,2.357-1.307C167.346,207.599,168.266,207.643,169.132,207.915z   M189.762,199.74c0.135,0.954,0.075,1.847-0.179,2.681s-0.668,1.553-1.241,2.156c-0.573,0.604-1.21,1.029-1.912,1.277  c-0.701,0.249-1.421,0.336-2.159,0.263c-0.737-0.073-1.493-0.297-2.266-0.673c-0.773-0.376-1.508-0.876-2.204-1.502l8.407-8.851  l-0.622-0.591c-0.999-0.949-2.045-1.726-3.137-2.332c-1.093-0.605-2.18-0.99-3.261-1.155c-1.081-0.164-2.129-0.089-3.143,0.223  c-1.014,0.313-1.952,0.923-2.814,1.83c-0.826,0.87-1.372,1.823-1.642,2.862c-0.27,1.039-0.313,2.104-0.129,3.194  c0.183,1.091,0.592,2.181,1.226,3.268c0.634,1.088,1.442,2.097,2.422,3.028c1.056,1.003,2.148,1.787,3.279,2.352  c1.13,0.565,2.256,0.891,3.377,0.975c1.121,0.086,2.205-0.065,3.252-0.451c1.048-0.386,2.002-1.031,2.861-1.936  c0.877-0.923,1.484-1.951,1.823-3.081c0.339-1.13,0.428-2.292,0.269-3.483L189.762,199.74z M176.932,200.788  c-0.422-0.651-0.729-1.327-0.923-2.029c-0.194-0.702-0.236-1.403-0.127-2.103c0.109-0.7,0.449-1.35,1.02-1.951  c0.59-0.619,1.229-1.01,1.923-1.174c0.692-0.163,1.39-0.161,2.092,0.006s1.389,0.444,2.061,0.832  c0.672,0.388,1.271,0.833,1.799,1.334l-6.474,6.814C177.81,202.016,177.354,201.439,176.932,200.788z M189.535,178.677  c-0.822,0.796-1.36,1.762-1.617,2.898c-0.257,1.136-0.292,2.192-0.105,3.17l-1.845-1.959l-2.017,1.954l13.108,13.527l2.017-1.954  l-9.608-9.914c-0.227-0.866-0.27-1.793-0.128-2.781c0.141-0.988,0.537-1.797,1.187-2.427c0.668-0.648,1.37-0.974,2.104-0.979  c0.732-0.005,1.534,0.441,2.403,1.337l9.336,9.634l2.018-1.954l-9.879-10.194C194.138,176.589,191.813,176.47,189.535,178.677z   M214.967,174.828c-0.747-0.832-1.538-1.362-2.373-1.591c-0.834-0.229-1.665-0.287-2.49-0.175c-0.825,0.113-1.646,0.327-2.464,0.642  s-1.592,0.583-2.321,0.801c-0.729,0.219-1.402,0.335-2.021,0.348s-1.152-0.232-1.604-0.735c-0.504-0.561-0.712-1.24-0.623-2.036  s0.52-1.542,1.293-2.237c0.678-0.608,1.428-1.028,2.249-1.26c0.822-0.232,1.617-0.272,2.383-0.121l-0.291-2.308  c-0.989-0.089-1.985,0.019-2.986,0.324c-1.002,0.306-1.967,0.875-2.896,1.709c-0.695,0.625-1.232,1.283-1.61,1.971  c-0.377,0.689-0.604,1.381-0.677,2.077c-0.074,0.696-0.009,1.362,0.196,1.999c0.206,0.637,0.543,1.217,1.013,1.739  c0.729,0.812,1.493,1.313,2.294,1.503c0.8,0.19,1.608,0.225,2.425,0.102c0.816-0.122,1.634-0.341,2.452-0.656  c0.817-0.315,1.591-0.582,2.32-0.801c0.73-0.219,1.422-0.315,2.073-0.29c0.652,0.026,1.222,0.309,1.708,0.851  c0.608,0.678,0.854,1.445,0.733,2.304c-0.119,0.859-0.585,1.654-1.398,2.383c-0.754,0.678-1.603,1.134-2.545,1.369  c-0.942,0.236-1.842,0.284-2.7,0.146l0.285,2.417c2.322,0.291,4.489-0.467,6.501-2.275c0.715-0.643,1.272-1.327,1.67-2.052  c0.398-0.724,0.645-1.443,0.737-2.156c0.093-0.713,0.024-1.411-0.206-2.096C215.864,176.04,215.488,175.408,214.967,174.828z   M225.252,169.912c-0.639,0.534-1.326,0.856-2.065,0.965c-0.737,0.11-1.489,0.043-2.252-0.2c-0.763-0.243-1.517-0.638-2.262-1.184  c-0.745-0.547-1.443-1.209-2.094-1.986c-0.65-0.777-1.176-1.576-1.572-2.396c-0.398-0.819-0.649-1.626-0.754-2.42  c-0.105-0.793-0.038-1.544,0.2-2.252c0.237-0.707,0.676-1.328,1.314-1.862c0.559-0.467,1.158-0.774,1.798-0.92  c0.641-0.146,1.376-0.127,2.209,0.058l-0.06-2.442c-0.925-0.174-1.858-0.175-2.796,0c-0.938,0.176-1.916,0.688-2.934,1.539  c-0.937,0.785-1.611,1.68-2.023,2.686c-0.413,1.007-0.59,2.062-0.531,3.165c0.06,1.103,0.332,2.231,0.82,3.381  c0.487,1.152,1.183,2.265,2.084,3.342c0.899,1.077,1.874,1.958,2.921,2.641c1.047,0.684,2.112,1.156,3.196,1.419  c1.084,0.262,2.157,0.28,3.221,0.051c1.062-0.228,2.062-0.734,3-1.519c1.017-0.851,1.698-1.718,2.047-2.602  c0.346-0.882,0.506-1.805,0.481-2.767l-2.394-0.49C226.887,167.714,226.369,168.978,225.252,169.912z M231.433,144.527  c-1.109-0.178-2.304,0.228-3.583,1.217c-0.908,0.702-1.559,1.608-1.954,2.718c-0.395,1.111-0.555,2.162-0.479,3.155l-6.011-7.826  l-2.222,1.717l15.908,20.582l2.222-1.717l-8.442-10.923c-0.13-0.886-0.068-1.812,0.182-2.778c0.25-0.966,0.733-1.725,1.45-2.279  c0.737-0.57,1.471-0.824,2.203-0.766c0.731,0.059,1.479,0.582,2.243,1.569l8.229,10.646l2.221-1.718l-8.729-11.294  C233.622,145.472,232.542,144.705,231.433,144.527z M245.721,134.459c-1.491-0.12-3.003,0.363-4.533,1.449  c-0.978,0.694-1.779,1.535-2.405,2.521c-0.628,0.987-1.04,2.125-1.24,3.415l2.169,0.899c0.114-1.101,0.383-2.018,0.808-2.749  c0.424-0.732,0.998-1.354,1.721-1.868c1.021-0.724,2.003-0.998,2.943-0.822c0.941,0.176,1.789,0.795,2.541,1.855l1.896,2.671  c-0.97-0.332-1.921-0.405-2.857-0.219c-0.936,0.186-1.797,0.557-2.581,1.114c-0.636,0.451-1.157,0.988-1.56,1.609  c-0.404,0.622-0.664,1.301-0.779,2.036c-0.116,0.736-0.073,1.503,0.127,2.301c0.2,0.799,0.586,1.6,1.158,2.406  c0.572,0.807,1.211,1.436,1.917,1.892c0.706,0.456,1.425,0.751,2.158,0.884c0.731,0.134,1.462,0.118,2.189-0.048  s1.398-0.466,2.013-0.903c0.784-0.556,1.415-1.251,1.893-2.084c0.477-0.833,0.711-1.772,0.702-2.818l1.173,1.654l2.29-1.625  l-7.63-10.749C248.584,135.52,247.213,134.58,245.721,134.459z M252.909,146.465c0.091,0.896-0.038,1.717-0.391,2.463  c-0.352,0.746-0.868,1.361-1.55,1.845c-0.959,0.681-1.948,0.879-2.968,0.594c-1.021-0.285-1.869-0.908-2.55-1.866  c-0.681-0.959-0.984-1.961-0.909-3.007c0.074-1.045,0.591-1.909,1.55-2.59c0.681-0.483,1.433-0.768,2.253-0.854  c0.821-0.086,1.646,0.073,2.477,0.476L252.909,146.465z M258.074,127.994l-1.381-2.08l-2.665,1.768l-1.271-1.917  c-0.503-0.759-0.732-1.457-0.688-2.095c0.045-0.638,0.393-1.172,1.042-1.604c0.585-0.388,1.252-0.486,2.002-0.298l-0.189-2.261  c-0.634-0.11-1.244-0.088-1.828,0.066c-0.585,0.154-1.137,0.403-1.657,0.748c-1.234,0.819-1.94,1.849-2.116,3.089  c-0.176,1.24,0.189,2.542,1.096,3.907l1.271,1.917l-2.08,1.38l1.38,2.08l2.08-1.38l9.036,13.615l2.34-1.551l-9.035-13.615  L258.074,127.994z M273.44,134.943c-0.153,0.267-0.385,0.497-0.692,0.691c-0.462,0.292-0.896,0.335-1.302,0.131  c-0.404-0.204-0.801-0.613-1.188-1.227l-6.435-10.197l2.705-1.707l-1.332-2.111l-2.704,1.707l-2.747-4.354l-2.375,1.499l2.747,4.354  l-2.111,1.332l1.332,2.111l2.11-1.332l6.707,10.629c1.509,2.391,3.329,2.914,5.463,1.568c0.614-0.389,1.07-0.799,1.366-1.232  c0.296-0.432,0.497-0.882,0.603-1.348l-1.851-1.324C273.693,134.407,273.595,134.677,273.44,134.943z M264.889,112.316l13.42,22.284  l2.405-1.448l-13.419-22.284L264.889,112.316z M275.584,114.308l9.423,16.311l2.432-1.405l-9.424-16.311L275.584,114.308z   M273.951,111.445c0.515,0.138,0.996,0.077,1.447-0.183c0.451-0.26,0.745-0.647,0.883-1.164c0.138-0.514,0.076-0.997-0.184-1.448  c-0.261-0.45-0.647-0.744-1.163-0.882c-0.515-0.137-0.998-0.076-1.448,0.184c-0.45,0.26-0.743,0.648-0.882,1.163  c-0.138,0.515-0.077,0.998,0.184,1.448C273.049,111.014,273.436,111.308,273.951,111.445z M296.976,121.601  c-0.731,0.397-1.47,0.576-2.216,0.536c-0.747-0.04-1.468-0.254-2.168-0.644c-0.699-0.39-1.36-0.926-1.981-1.61  c-0.622-0.683-1.175-1.471-1.657-2.362c-0.483-0.891-0.839-1.778-1.065-2.661c-0.227-0.882-0.313-1.723-0.258-2.522  c0.055-0.798,0.269-1.521,0.644-2.167c0.374-0.646,0.927-1.168,1.658-1.564c0.639-0.346,1.288-0.527,1.945-0.544  c0.656-0.016,1.374,0.15,2.153,0.496l0.427-2.405c-0.873-0.354-1.787-0.54-2.741-0.555c-0.955-0.015-2.014,0.293-3.18,0.925  c-1.075,0.583-1.914,1.326-2.519,2.23c-0.604,0.904-0.986,1.903-1.147,2.996s-0.117,2.252,0.133,3.477  c0.249,1.225,0.709,2.454,1.378,3.688s1.448,2.291,2.338,3.168c0.891,0.879,1.841,1.554,2.851,2.026  c1.011,0.473,2.06,0.703,3.146,0.69c1.087-0.013,2.168-0.31,3.243-0.893c1.166-0.632,2.006-1.346,2.521-2.142  c0.515-0.796,0.854-1.668,1.021-2.616l-2.248-0.956C299.015,119.771,298.256,120.907,296.976,121.601z M310.795,100.853  c-0.759-1.54-1.664-2.506-2.717-2.901c-1.051-0.396-2.303-0.235-3.752,0.479c-1.029,0.507-1.849,1.266-2.455,2.275  c-0.608,1.01-0.974,2.009-1.098,2.997l-4.333-8.865l-2.519,1.241l11.497,23.334l2.519-1.241l-6.102-12.385  c0.05-0.894,0.293-1.789,0.73-2.686c0.438-0.896,1.063-1.545,1.875-1.945c0.835-0.412,1.605-0.516,2.312-0.313  c0.706,0.204,1.335,0.864,1.886,1.984l5.947,12.07l2.517-1.24L310.795,100.853z");
    }
    return path;
  };
  this.App.createReflection = function(paper, index) {
    var path;
    if (index === 1) {
      path = paper.path("M499.977,274.129c2.947-3.21,6.447-5.677,10.351-7.418c5.419-7.789,15.79-14.452,35.465-15.935      c22.147-1.667,42.293-21.475,42.93-48.081c0.672-28.288-22.224-51.549-50.519-51.944c-15.191-0.212-28.684,4.834-38.208,15.205      c-9.526-10.371-23.021-15.417-38.21-15.205c-28.294,0.395-51.191,23.656-50.519,51.944c0.638,26.606,20.781,46.414,42.927,48.081      c19.694,1.484,30.067,8.16,35.482,15.958C493.561,268.473,497.042,270.934,499.977,274.129z");
    }
    if (index === 2) {
      path = paper.path("M505.045,347.721c2.863-6.899,9.871-13.599,26.644-14.862c15.333-1.157,29.282-14.87,29.723-33.292      c0.465-19.588-15.387-35.693-34.977-35.967c-5.818-0.082-11.273,0.957-16.106,3.111c-3.904,1.741-7.404,4.208-10.351,7.418      c-2.935-3.195-6.417-5.656-10.3-7.396c-4.846-2.17-10.319-3.215-16.158-3.133c-19.587,0.274-35.442,16.379-34.977,35.967      c0.441,18.422,14.39,32.135,29.721,33.292c16.715,1.259,23.734,7.917,26.616,14.791c1.911,1.019,3.644,2.337,5.144,3.97      C501.49,350.022,503.184,348.73,505.045,347.721z");
    }
    if (index === 3) {
      path = paper.path("M502.099,401.548c0.556-5.341,3.591-12.491,17.567-13.546c9.499-0.714,18.141-9.211,18.414-20.622      c0.289-12.135-9.533-22.112-21.668-22.282c-4.177-0.058-8.046,0.822-11.367,2.624c-1.861,1.009-3.555,2.301-5.022,3.898      c-1.5-1.633-3.233-2.951-5.144-3.97c-3.294-1.756-7.123-2.608-11.247-2.552c-12.135,0.17-21.957,10.147-21.669,22.282      c0.274,11.411,8.914,19.908,18.412,20.622c14.022,1.058,17.033,8.249,17.575,13.595c0.726,0.538,1.416,1.128,2.042,1.809      C500.637,402.705,501.349,402.097,502.099,401.548z");
    }
    if (index === 4) {
      path = paper.path("M659.894,328.676c9.157-2.483,21.386-0.92,37.41,10.593c18.035,12.958,46.201,10.736,63.79-9.233      c18.7-21.239,16.113-53.775-5.307-72.267c-11.498-9.928-25.077-14.735-39.041-12.913c-0.629-14.069-7.722-26.608-19.493-36.211      c-21.927-17.884-54.419-14.787-72.091,7.315c-16.615,20.789-13.916,48.912,1.975,64.425      c14.132,13.797,17.787,25.578,16.923,35.032c1.857,3.829,2.942,7.952,3.136,12.287      C651.517,327.14,655.784,327.499,659.894,328.676z");
    }
    if (index === 5) {
      path = paper.path("M603.779,387.329c6.628-3.439,16.301-4.062,29.953,5.746c12.487,8.973,31.989,7.436,44.169-6.392      c12.947-14.706,11.158-37.233-3.675-50.037c-4.402-3.802-9.247-6.514-14.333-7.97c-4.109-1.177-8.377-1.536-12.698-0.972      c-0.193-4.334-1.278-8.458-3.136-12.287c-2.317-4.777-5.839-9.096-10.362-12.787c-15.184-12.383-37.68-10.238-49.914,5.066      c-11.506,14.394-9.638,33.866,1.365,44.607c11.99,11.707,13.089,21.318,10.881,28.436c0.81,2.009,1.286,4.136,1.386,6.352      C599.569,386.811,601.701,386.904,603.779,387.329z");
    }
    if (index === 6) {
      path = paper.path("M566.909,426.67c3.86-3.734,10.78-7.261,22.165,0.919c7.738,5.557,19.818,4.605,27.363-3.961      c8.021-9.109,6.913-23.066-2.277-30.998c-3.157-2.726-6.683-4.545-10.381-5.302c-2.078-0.425-4.21-0.518-6.364-0.237      c-0.1-2.216-0.576-4.343-1.386-6.352c-1.394-3.461-3.782-6.572-6.977-9.179c-9.403-7.671-23.341-6.343-30.92,3.137      c-7.128,8.917-5.971,20.98,0.845,27.635c10.063,9.824,7.746,17.267,4.725,21.712c0.21,0.877,0.359,1.773,0.401,2.696      C565.047,426.617,565.981,426.609,566.909,426.67z");
    }
    if (index === 7) {
      path = paper.path("M840.404,404.359c-5.299-27.795-32.18-46.31-59.924-40.739c-26.092,5.244-42.102,28.521-39.902,50.618      c1.956,19.654-2.818,31.028-9.559,37.714c-0.258,1.025-0.57,2.03-0.926,3.019c40.563-5.227,76.516-8.82,102.524-11.119      C840.722,432.796,843.184,418.944,840.404,404.359z");
    }
    if (index === 8) {
      path = paper.path("M731.302,435.499c-3.668-19.246-22.28-32.065-41.491-28.208c-18.066,3.629-29.15,19.747-27.626,35.048      c1.096,11.015-0.865,18.269-4.127,23.091c24.84-4.046,49.17-7.511,72.036-10.458c0.355-0.989,0.668-1.994,0.926-3.019      C732.315,446.804,732.395,441.233,731.302,435.499z");
    }
    if (index === 9) {
      path = paper.path("M652.795,459.598c-2.271-11.923-13.802-19.864-25.702-17.473c-11.192,2.248-18.06,12.232-17.115,21.711      c0.422,4.239,0.112,7.579-0.666,10.218c14.652-2.816,29.343-5.421,43.882-7.827C653.358,464.086,653.227,461.863,652.795,459.598z");
    }
    if (index === 10) {
      path = paper.path("M195.417,576.396c-24.564,13.4-33.337,44.303-20.195,68.879c23.473-12.607,54.87-29.081,90.369-46.692      c-2.344-2.565-4.707-5.548-7.078-9.025C246.002,571.207,218.78,563.653,195.417,576.396z");
    }
    if (index === 11) {
      path = paper.path("M292.974,551.648c-15.025,8.199-21.524,25.855-16.561,41.592c19.875-9.757,40.865-19.771,62.342-29.597      c-0.696-0.906-1.394-1.856-2.092-2.881C328,548.058,309.151,542.825,292.974,551.648z");
    }
    if (index === 12) {
      path = paper.path("M363.372,537.977c-7.379,4.024-11.431,11.733-11.266,19.612c12.145-5.457,24.401-10.825,36.66-16.024      C382.897,535.238,372.462,533.021,363.372,537.977z");
    }
    if (index === 13) {
      path = paper.path("M274.484,463.283c-2.647-3.461-4.469-7.336-5.503-11.483c-6.726-6.692-11.483-18.065-9.517-37.701      c2.213-22.096-13.783-45.383-39.873-50.643c-27.739-5.585-54.631,12.911-59.946,40.706c-2.853,14.921-0.234,29.085,8.321,40.27      c-11.871,7.577-19.189,19.986-21.624,34.979c-4.539,27.932,14.382,54.528,42.356,58.79c26.309,4.007,49.321-12.383,54.819-33.898      c4.889-19.136,13.269-28.189,21.891-32.164C267.796,468.617,270.826,465.617,274.484,463.283z");
    }
    if (index === 14) {
      path = paper.path("M350.799,476.729c-1.32-1.726-2.305-3.618-2.975-5.63c-6.291-4.023-11.663-12.09-9.988-28.818      c1.533-15.3-9.544-31.424-27.608-35.065c-19.207-3.869-37.827,8.939-41.507,28.184c-1.093,5.715-1.021,11.267,0.26,16.399      c1.035,4.147,2.856,8.022,5.503,11.483c-3.658,2.334-6.688,5.333-9.077,8.856c-2.98,4.394-4.962,9.602-5.898,15.365      c-3.141,19.337,9.959,37.753,29.329,40.705c18.216,2.775,34.15-8.576,37.955-23.472c4.152-16.24,11.932-21.992,19.201-23.634      C347.33,479.399,348.93,477.922,350.799,476.729z");
    }
    if (index === 15) {
      path = paper.path("M400.326,483.378c-5.164-1.479-11.677-5.71-10.281-19.659c0.95-9.479-5.911-19.467-17.103-21.721      c-11.898-2.397-23.434,5.536-25.711,17.459c-0.784,4.098-0.6,8.062,0.593,11.643c0.67,2.012,1.655,3.904,2.975,5.63      c-1.869,1.193-3.469,2.67-4.805,4.374c-2.303,2.938-3.809,6.559-4.47,10.629c-1.946,11.981,6.169,23.39,18.168,25.218      c11.284,1.717,21.155-5.313,23.514-14.541c3.48-13.623,11.085-15.337,16.447-14.94c0.655-0.621,1.357-1.198,2.135-1.695      C401.21,485.019,400.735,484.212,400.326,483.378z");
    }
    if (index === 16) {
      path = paper.path("M352.011,326.78c0.197-4.353,1.292-8.491,3.166-12.333c-0.851-9.45,2.816-21.221,16.943-34.999      c15.898-15.505,18.613-43.625,2.008-64.425c-17.66-22.109-50.149-25.226-72.087-7.35c-11.776,9.596-18.875,22.13-19.511,36.197      c-13.964-1.826-27.546,2.975-39.049,12.896c-21.431,18.479-24.033,51.016-5.343,72.261c17.578,19.98,45.742,22.218,63.783,9.27      c16.045-11.516,28.283-13.065,37.443-10.568C343.458,326.567,347.708,326.217,352.011,326.78z");
    }
    if (index === 17) {
      path = paper.path("M401.828,386.135c0.098-2.17,0.561-4.253,1.34-6.225c-2.233-7.126-1.163-16.758,10.873-28.496      c11.008-10.734,12.887-30.207,1.39-44.607c-12.226-15.311-34.723-17.467-49.912-5.09c-4.511,3.675-8.024,7.975-10.343,12.73      c-1.874,3.842-2.969,7.98-3.166,12.333c-4.303-0.563-8.552-0.213-12.646,0.95c-5.107,1.45-9.973,4.166-14.394,7.979      c-14.836,12.795-16.639,35.322-3.697,50.033c12.17,13.836,31.673,15.383,44.162,6.418c13.616-9.769,23.271-9.179,29.895-5.766      C397.45,385.946,399.628,385.847,401.828,386.135z");
    }
    if (index === 18) {
      path = paper.path("M435.074,425.84c0.043-0.951,0.198-1.873,0.42-2.776c-3.005-4.453-5.275-11.881,4.762-21.669      c6.82-6.65,7.985-18.711,0.86-27.633c-7.573-9.484-21.51-10.822-30.918-3.152c-3.235,2.636-5.641,5.79-7.029,9.301      c-0.78,1.972-1.242,4.055-1.34,6.225c-2.2-0.288-4.378-0.188-6.498,0.259c-3.651,0.771-7.13,2.581-10.251,5.272      c-9.192,7.928-10.309,21.883-2.292,30.997c7.541,8.568,19.621,9.528,27.359,3.976c11.423-8.199,18.351-4.624,22.203-0.874      C433.25,425.711,434.159,425.72,435.074,425.84z");
    }
    if (index === 19) {
      path = paper.path("M501.478,441.629c0.002-0.066-0.001-0.131,0.003-0.198c0.205-4.03,2.032-10.053,13.164-10.892      c7.084-0.533,13.53-6.87,13.732-15.381c0.215-9.05-7.109-16.491-16.161-16.617c-3.833-0.055-7.316,0.956-10.117,3.006      c-0.75,0.549-1.462,1.157-2.106,1.858c-0.625-0.681-1.316-1.271-2.042-1.809c-2.813-2.083-6.32-3.11-10.182-3.055      c-9.051,0.126-16.377,7.567-16.162,16.617c0.204,8.511,6.649,14.848,13.733,15.381c11.133,0.839,12.959,6.862,13.165,10.892      c0.003,0.066,0,0.129,0.002,0.195c0.531,0.4,1.027,0.854,1.487,1.354C500.453,442.482,500.948,442.029,501.478,441.629z");
    }
    if (index === 20) {
      path = paper.path("M540.671,456.971c0.043-0.048,0.081-0.098,0.126-0.146c2.749-2.955,8.02-6.395,17.087,0.118      c5.767,4.146,14.779,3.435,20.405-2.955c5.984-6.793,5.155-17.201-1.697-23.116c-2.902-2.505-6.221-3.972-9.683-4.202      c-0.928-0.062-1.862-0.053-2.806,0.07c-0.042-0.922-0.191-1.818-0.401-2.696c-0.815-3.404-2.841-6.446-5.835-8.886      c-7.014-5.723-17.409-4.732-23.061,2.337c-5.317,6.652-4.453,15.648,0.631,20.611c7.988,7.8,5.514,13.587,3.08,16.807      c-0.041,0.054-0.084,0.102-0.126,0.154c0.148,0.646,0.236,1.31,0.267,1.985C539.332,456.965,540.006,456.937,540.671,456.971z");
    }
    if (index === 21) {
      path = paper.path("M581.711,459.913c-8.345,1.677-13.47,9.123-12.764,16.192c0.251,2.526,0.142,4.606-0.203,6.352      c10.723-2.394,21.563-4.666,32.445-6.819c-0.046-0.887-0.135-1.784-0.308-2.693C599.187,464.053,590.587,458.131,581.711,459.913z");
    }
    if (index === 22) {
      path = paper.path("M409.608,522.511c-5.253,2.866-8.232,8.236-8.387,13.829c9.177-3.805,18.333-7.499,27.423-11.052      C424.287,520.489,416.438,518.783,409.608,522.511z");
    }
    if (index === 23) {
      path = paper.path("M439.668,490.965c-0.058-0.012-0.116-0.02-0.174-0.033c-3.933-0.906-9.547-3.751-8.436-14.861      c0.709-7.069-4.409-14.519-12.753-16.201c-8.875-1.787-17.478,4.13-19.179,13.022c-0.719,3.765-0.331,7.372,1.2,10.486      c0.41,0.834,0.884,1.641,1.462,2.397c-0.778,0.497-1.48,1.074-2.135,1.695c-2.54,2.406-4.164,5.683-4.782,9.494      c-1.452,8.936,4.602,17.444,13.549,18.807c8.418,1.283,15.778-3.961,17.537-10.845c2.765-10.816,9.013-11.565,13.019-11.065      c0.073,0.009,0.143,0.024,0.214,0.035c0.48-0.444,1.004-0.847,1.566-1.207C440.339,492.143,439.973,491.566,439.668,490.965z");
    }
    if (index === 24) {
      path = paper.path("M461.331,457.054c0.029-0.661,0.116-1.31,0.258-1.942c-0.329-0.334-0.647-0.69-0.945-1.084      c-2.431-3.223-4.902-9.011,3.09-16.807c5.087-4.96,5.956-13.957,0.645-20.609c-5.65-7.072-16.044-8.07-23.063-2.353      c-2.971,2.423-4.992,5.435-5.821,8.805c-0.222,0.903-0.377,1.825-0.42,2.776c-0.916-0.12-1.824-0.129-2.725-0.075      c-3.493,0.21-6.842,1.677-9.766,4.2c-6.856,5.911-7.688,16.32-1.71,23.115c5.624,6.395,14.633,7.107,20.406,2.965      c9.07-6.508,14.338-3.064,17.085-0.107c0.314,0.338,0.59,0.688,0.847,1.044C459.911,456.938,460.62,456.961,461.331,457.054z");
    }
    if (index === 26) {
      path = paper.path("M549.885,477.053c-5.08,1.023-7.855,5.384-7.905,9.743c-0.009,0.712-0.068,1.38-0.168,2.009      c6.335-1.577,12.738-3.108,19.191-4.593C559.683,479.223,555.036,476.018,549.885,477.053z");
    }
    if (index === 27) {
      path = paper.path("M524.691,475.173c1.515-1.805,5.639-2.931,10.441-0.23c3.802,2.135,8.968,1.912,12.393-1.978      c3.644-4.138,2.973-10.134-1.2-13.736c-1.685-1.456-3.634-2.152-5.654-2.258c-0.665-0.035-1.339-0.006-2.013,0.082      c-0.03-0.675-0.118-1.339-0.267-1.985c-0.452-1.974-1.477-3.775-3.206-5.185c-4.271-3.483-10.292-3.103-13.735,1.203      c-3.235,4.05-2.557,9.177,0.204,12.547c3.494,4.263,3.101,8.52,1.587,10.325c-2.957,3.523-8.173,5.257-12.795,0.46      c-6.625,0.706-9.506-3.978-9.506-8.578c0-2.354,2.438-5.868,7.851-6.89c4.282-0.806,8.101-4.297,8.225-9.48      c0.131-5.51-4.238-9.673-9.751-9.751c-2.229-0.03-4.171,0.69-5.787,1.911c-0.529,0.4-1.024,0.853-1.482,1.351      c-0.459-0.5-0.956-0.954-1.487-1.354c-1.615-1.219-3.555-1.938-5.783-1.908c-5.513,0.078-9.883,4.241-9.749,9.751      c0.123,5.184,3.939,8.675,8.22,9.48c5.415,1.021,7.854,4.535,7.854,6.89c0,4.601-2.883,9.284-9.507,8.578      c-4.622,4.798-9.839,3.063-12.794-0.459c-1.514-1.805-1.908-6.062,1.586-10.326c2.761-3.369,3.439-8.498,0.204-12.546      c-3.444-4.306-9.464-4.685-13.738-1.202c-1.74,1.419-2.765,3.236-3.213,5.228c-0.142,0.632-0.229,1.282-0.258,1.942      c-0.71-0.093-1.419-0.117-2.12-0.073c-1.982,0.124-3.891,0.819-5.547,2.249c-4.172,3.602-4.843,9.599-1.199,13.736      c3.425,3.891,8.592,4.112,12.39,1.977c4.804-2.699,8.929-1.575,10.446,0.23c2.954,3.524,3.76,8.963-1.77,12.682      c-0.456,6.646-5.566,8.668-10.096,7.87c-2.321-0.408-5.358-3.416-5.424-8.929c-0.048-4.358-2.826-8.719-7.907-9.742      c-5.405-1.086-10.261,2.493-11.294,7.908c-0.416,2.178-0.05,4.207,0.859,6.002c0.305,0.602,0.67,1.178,1.088,1.724      c-0.563,0.359-1.086,0.763-1.566,1.207c-1.493,1.382-2.548,3.174-2.907,5.387c-0.88,5.439,2.46,10.463,7.911,11.293      c5.124,0.779,9.224-2.374,10.763-6.452c1.946-5.154,5.83-6.942,8.15-6.534c4.527,0.797,8.639,4.449,6.794,10.85      c0.324,0.444,0.588,0.884,0.826,1.32c10.838-3.738,21.465-7.181,31.786-10.26c8.257-2.463,16.714-4.832,25.326-7.11      c-0.748-1.178-1.253-2.668-1.381-4.536C520.93,484.136,521.733,478.697,524.691,475.173z");
    }
    if (index === 28) {
      path = paper.path("M445.014,515.224c-2.299,1.256-3.815,3.241-4.497,5.493c4.768-1.808,9.511-3.573,14.223-5.289      C451.958,513.768,448.382,513.387,445.014,515.224z");
    }
    return path;
  };
  this.App.createInnerElement = function(paper) {
    return paper.path("M519.637,526.542c1.263-2.845,3.136-4.381,5.178-4.99    c1.405-1.878,2.596-3.925,3.551-6.098c-0.507-2.081-0.119-4.485,1.724-7.015c-0.879-3.051-0.396-5.469,0.83-7.259    c-0.135-2.332-0.531-4.593-1.154-6.758c-1.787-1.259-3.087-3.375-3.306-6.569c-2.691-1.81-3.874-4.027-4.046-6.232    c-1.532-1.607-3.229-3.056-5.074-4.306c-2.217,0.23-4.625-0.545-6.893-2.897c-3.272,0.349-5.628-0.621-7.178-2.242    c-1.082-0.114-2.18-0.176-3.292-0.176c-1.098,0-2.181,0.059-3.25,0.17c-1.55,1.625-3.908,2.597-7.184,2.248    c-2.279,2.366-4.702,3.139-6.928,2.896c-1.829,1.238-3.512,2.672-5.034,4.263c-0.16,2.221-1.342,4.456-4.051,6.278    c-0.221,3.222-1.541,5.349-3.353,6.603c-0.612,2.139-1.003,4.37-1.14,6.671c1.252,1.795,1.751,4.23,0.864,7.31    c1.858,2.551,2.237,4.975,1.71,7.068c0.949,2.147,2.127,4.171,3.516,6.029c2.061,0.6,3.954,2.138,5.226,5.005    c3.007,0.744,4.843,2.312,5.801,4.205c2.114,1.056,4.364,1.873,6.718,2.426c1.947-0.824,4.352-0.839,7.123,0.518    c2.764-1.354,5.164-1.342,7.108-0.523c2.364-0.557,4.623-1.382,6.744-2.445C514.811,528.839,516.644,527.283,519.637,526.542z");
  };
  this.App.createLetter = function(paper, index) {
    var path;
    if (index === 0) {
      path = paper.path("M490.328,512.691l6.877-20.357h5.578l6.877,20.357h-5.264l-1.271-4.156h-6.398l-1.271,4.156H490.328z	 M502.004,504.844l-2.078-6.713l-2.078,6.713H502.004z");
    }
    if (index === 1) {
      path = paper.path("M508.778,506.457c0,1.012-0.191,1.9-0.574,2.666s-0.897,1.399-1.545,1.9		c-0.766,0.602-1.606,1.03-2.522,1.285s-2.08,0.383-3.493,0.383h-8.148v-20.357h7.191c1.495,0,2.627,0.057,3.397,0.171		c0.771,0.114,1.492,0.354,2.167,0.718c0.729,0.392,1.273,0.916,1.634,1.572s0.54,1.413,0.54,2.27c0,0.993-0.248,1.878-0.745,2.652		s-1.183,1.345-2.058,1.709v0.109c1.258,0.265,2.265,0.805,3.021,1.62S508.778,505.071,508.778,506.457z M502.229,498.09		c0-0.328-0.084-0.665-0.253-1.012s-0.431-0.597-0.786-0.752c-0.337-0.146-0.736-0.226-1.196-0.239		c-0.46-0.014-1.146-0.021-2.058-0.021h-0.355v4.307h0.643c0.875,0,1.488-0.009,1.839-0.027c0.351-0.019,0.713-0.114,1.087-0.287		c0.41-0.191,0.692-0.456,0.848-0.793S502.229,498.536,502.229,498.09z M503.515,506.361c0-0.629-0.128-1.121-0.383-1.477		s-0.638-0.624-1.148-0.807c-0.31-0.118-0.736-0.185-1.278-0.198c-0.542-0.014-1.27-0.021-2.181-0.021h-0.943v5.1h0.273		c1.331,0,2.251-0.009,2.762-0.027s1.03-0.142,1.559-0.369c0.465-0.2,0.805-0.494,1.019-0.882S503.515,506.854,503.515,506.361z");
    }
    if (index === 2) {
      path = paper.path("M501.532,513.088c-3.054,0-5.478-0.923-7.273-2.769c-1.796-1.846-2.693-4.441-2.693-7.786		c0-3.227,0.9-5.799,2.7-7.718c1.8-1.918,4.227-2.878,7.28-2.878c0.812,0,1.54,0.046,2.188,0.137		c0.647,0.091,1.267,0.219,1.859,0.383c0.465,0.137,0.971,0.324,1.518,0.561c0.547,0.237,0.989,0.442,1.326,0.615v4.854h-0.52		c-0.246-0.219-0.556-0.48-0.93-0.786s-0.798-0.604-1.271-0.896s-0.996-0.54-1.565-0.745s-1.164-0.308-1.784-0.308		c-0.738,0-1.415,0.116-2.03,0.349s-1.201,0.636-1.757,1.21c-0.511,0.52-0.928,1.222-1.251,2.105		c-0.324,0.884-0.485,1.928-0.485,3.131c0,1.267,0.168,2.331,0.506,3.192c0.337,0.861,0.779,1.557,1.326,2.085		c0.528,0.511,1.119,0.88,1.771,1.107c0.651,0.228,1.301,0.342,1.948,0.342c0.675,0,1.317-0.111,1.928-0.335		s1.126-0.472,1.545-0.745c0.456-0.282,0.856-0.569,1.203-0.861s0.647-0.552,0.902-0.779h0.465v4.785		c-0.374,0.173-0.807,0.371-1.299,0.595s-0.998,0.412-1.518,0.567c-0.638,0.191-1.235,0.337-1.791,0.438		S502.508,513.088,501.532,513.088z");
    }
    if (index === 3) {
      path = paper.path("M509.681,502.533c0,1.896-0.415,3.594-1.244,5.093s-1.878,2.65-3.145,3.452		c-1.058,0.684-2.208,1.123-3.452,1.319s-2.568,0.294-3.972,0.294h-6.371v-20.357h6.316c1.431,0,2.771,0.091,4.02,0.273		c1.249,0.183,2.42,0.625,3.514,1.326c1.34,0.857,2.397,2.012,3.172,3.466S509.681,500.564,509.681,502.533z M504.431,502.492		c0-1.34-0.23-2.486-0.69-3.438s-1.169-1.697-2.126-2.235c-0.692-0.383-1.42-0.593-2.181-0.629c-0.761-0.036-1.67-0.055-2.728-0.055		h-0.096v12.742h0.096c1.148,0,2.117-0.021,2.905-0.062c0.788-0.041,1.538-0.285,2.249-0.731c0.839-0.528,1.477-1.258,1.914-2.188		S504.431,503.832,504.431,502.492z");
    }
    return path;
  };
  this.App.doTransform = function(element, width, height, originalWidth, originalHeight, additionalScaleX, additionalScaleY) {
    var offsetX, offsetY;
    if (element) {
      offsetX = (originalWidth - width) / 2;
      offsetY = (originalHeight - height) / 2;
      if (offsetX < 0) {
        offsetX = 0;
      }
      if (offsetY < 0) {
        offsetY = 0;
      }
      if (!additionalScaleX) {
        additionalScaleX = 1.0;
      }
      if (!additionalScaleY) {
        additionalScaleY = 1.0;
      }
      element.scale(width / 1000 * additionalScaleX, height / 1000 * additionalScaleY, 0, 0);
      if (offsetX !== 0 || offsetY !== 0) {
        return element.translate(offsetX, offsetY);
      }
    }
  };
  this.App.doTransformShadow = function(element, width, height, originalWidth, originalHeight) {
    if (element) {
      App.doTransform(element, width, height, originalWidth, originalHeight);
      return element.translate(0, 0);
    }
  };
  this.App.setSelected = function(element, highlight) {
    if (element) {
      if (!highlight) {
        element.attr({
          fill: "#764560"
        });
      } else {
        element.attr({
          fill: "#562540"
        });
      }
      return element.attr({
        stroke: "none"
      });
    }
  };
  this.App.setUnselected = function(element, highlight) {
    if (element) {
      if (!highlight) {
        element.attr({
          fill: "#FCFFE1"
        });
      } else {
        element.attr({
          fill: "#ECEFD1"
        });
      }
      return element.attr({
        stroke: "none"
      });
    }
  };
  this.App.setShadow = function(element) {
    if (element) {
      element.attr({
        fill: "#444444"
      });
      return element.attr({
        stroke: "none"
      });
    }
  };
  this.App.colorizeBorderArrow = function(element) {
    if (element) {
      element.attr({
        fill: "E2D7DC"
      });
      return element.attr({
        stroke: "none"
      });
    }
  };
  this.App.colorizeBorderText = function(element) {
    if (element) {
      element.attr({
        fill: "#76455F"
      });
      return element.attr({
        stroke: "none"
      });
    }
  };
  this.App.colorizeReflection = function(element) {
    if (element) {
      element.attr({
        fill: "#FFFFFF"
      });
      element.attr({
        stroke: "none"
      });
      return element.attr({
        opacity: 0.1
      });
    }
  };
  this.App.colorizeLetter = function(element, highlight) {
    if (element) {
      if (highlight) {
        element.attr({
          fill: "#FFFFFF"
        });
        return element.attr({
          stroke: "none"
        });
      } else {
        element.attr({
          fill: "#ECEFD1"
        });
        return element.attr({
          stroke: "none"
        });
      }
    }
  };
  this.App.getBelongsToOfReflection = function(i) {
    var bto;
    if (i >= 1 && i <= 3) {
      bto = 0;
    }
    if (i >= 4 && i <= 6) {
      bto = 1;
    }
    if (i >= 7 && i <= 9) {
      bto = 2;
    }
    if (i >= 10 && i <= 12) {
      bto = 6;
    }
    if (i >= 13 && i <= 15) {
      bto = 7;
    }
    if (i >= 16 && i <= 18) {
      bto = 8;
    }
    if (i === 19) {
      bto = 0;
    }
    if (i === 20) {
      bto = 1;
    }
    if (i === 21) {
      bto = 2;
    }
    if (i === 22) {
      bto = 6;
    }
    if (i === 23) {
      bto = 7;
    }
    if (i === 24) {
      bto = 8;
    }
    if (i === 26) {
      bto = 2;
    }
    if (i === 28) {
      bto = 6;
    }
    if (i === 27) {
      bto = -2;
    }
    return bto;
  };
  this.App.initFlower = function(container, values, relationshipType, overwriteWidth, overwriteHeight, overlayPath, shadowPath, hoverIndex, disableText) {
    var borderArrow, borderText, borderTextLarge, bto, currentMax, drawBorder, element, fontSize, fontType, handleMouseOver, hearts, height, hideExplanation, hideRaphael, highlightLetter, highlightSelected, highlightUnselected, i, i2, imageOverlay, innerElement, letter, originalHeight, originalWidth, paper, paperDiv, parts, reflection, scaleLargeTextelement, scaleSmallTextelement, shadowBackground, showExplanation, showRaphael, txtElement, unhighlightLetter, unhighlightSelected, unhighlightUnselected, value, width;
    if (!App.flowerCurrentlyActive) {
      App.flowerCurrentlyActive = new Array();
    }
    App.flowerCurrentlyActive[hoverIndex] = -1;
    drawBorder = function(p, x, y, w, h) {
      var border;
      border = p.path("M" + x + " " + y + " L" + (x + w) + " " + y + " " + "L" + (x + w) + " " + (y + h) + " " + "L" + x + " " + (y + h) + " " + "L" + x + " " + y);
      border.attr({
        stroke: "#000"
      });
      border.attr({
        opacity: ".2"
      });
      border.attr({
        fill: "#eee"
      });
      return border;
    };
    handleMouseOver = function(event) {
      var flowerHoverIndex, nowActive;
      event.preventDefault();
      nowActive = event.data.belongsto;
      flowerHoverIndex = event.data.flowerHoverIndex;
      if (nowActive !== App.flowerCurrentlyActive[flowerHoverIndex]) {
        $("[data-selected-" + App.flowerCurrentlyActive[flowerHoverIndex] + "-" + flowerHoverIndex + "]").each(unhighlightSelected);
        $("[data-unselected-" + App.flowerCurrentlyActive[flowerHoverIndex] + "-" + flowerHoverIndex + "]").each(unhighlightUnselected);
        $("[id=flower-popup-explanation-" + App.flowerCurrentlyActive[flowerHoverIndex] + "-" + flowerHoverIndex + "]").each(hideExplanation);
        $("[id=flower-popup-explanation-" + App.flowerCurrentlyActive[flowerHoverIndex] + "]").each(hideExplanation);
        $("[data-textelement-" + App.flowerCurrentlyActive[flowerHoverIndex] + "-" + flowerHoverIndex + "]").each(scaleSmallTextelement);
        $("[data-textelement-large-" + App.flowerCurrentlyActive[flowerHoverIndex] + "-" + flowerHoverIndex + "]").each(hideRaphael);
        $("[data-textelement-small-" + App.flowerCurrentlyActive[flowerHoverIndex] + "-" + flowerHoverIndex + "]").each(showRaphael);
        $("[data-selected-" + nowActive + "-" + flowerHoverIndex + "]").each(highlightSelected);
        $("[data-unselected-" + nowActive + "-" + flowerHoverIndex + "]").each(highlightUnselected);
        $("[id=flower-popup-explanation-" + nowActive + "-" + flowerHoverIndex + "]").each(showExplanation);
        $("[id=flower-popup-explanation-" + nowActive + "]").each(showExplanation);
        $("[data-textelement-large-" + nowActive + "-" + flowerHoverIndex + "]").each(showRaphael);
        $("[data-textelement-small-" + nowActive + "-" + flowerHoverIndex + "]").each(hideRaphael);
        $("[data-borderarrow-" + App.flowerCurrentlyActive[flowerHoverIndex] + "-" + flowerHoverIndex + "]").each(hideRaphael);
        $("[data-borderarrow-" + nowActive + "-" + flowerHoverIndex + "]").each(showRaphael);
        $("[data-letter-" + App.flowerCurrentlyActive[flowerHoverIndex] + "]").each(unhighlightLetter);
        $("[data-letter-" + nowActive + "]").each(highlightLetter);
      }
      return App.flowerCurrentlyActive[flowerHoverIndex] = nowActive;
    };
    highlightSelected = function() {
      return App.setSelected(this.raphael, true);
    };
    unhighlightSelected = function() {
      return App.setSelected(this.raphael, false);
    };
    highlightUnselected = function() {
      return App.setUnselected(this.raphael, true);
    };
    unhighlightUnselected = function() {
      return App.setUnselected(this.raphael, false);
    };
    highlightLetter = function() {
      return App.colorizeLetter(this.raphael, true);
    };
    unhighlightLetter = function() {
      return App.colorizeLetter(this.raphael, false);
    };
    showRaphael = function() {
      return this.raphael.show();
    };
    hideRaphael = function() {
      return this.raphael.hide();
    };
    scaleLargeTextelement = function() {
      return this.raphael.scale(width / 1000 * 1.3, height / 1000 * 1.3);
    };
    scaleSmallTextelement = function() {
      return this.raphael.scale(width / 1000 * 1.0, height / 1000 * 1.0);
    };
    showExplanation = function() {
      return $(this).css("display", "");
    };
    hideExplanation = function() {
      return $(this).css("display", "none");
    };
    paperDiv = container;
    originalWidth = width = paperDiv.width();
    originalHeight = height = paperDiv.height();
    if (overwriteWidth && overwriteWidth > 0) {
      originalWidth = width = overwriteWidth;
    }
    if (overwriteHeight && overwriteHeight > 0) {
      originalHeight = height = overwriteHeight;
    }
    paper = Raphael(paperDiv[0], width, height);
    if (width <= 0) {
      width = 600;
    }
    if (height <= 0) {
      height = width;
    }
    if (width > height) {
      width = height;
    }
    if (height !== width) {
      height = width;
    }
    if (shadowPath) {
      shadowBackground = paper.image(shadowPath, 0, 0, width, height);
      shadowBackground.translate((originalWidth - width) / 2, (originalHeight - height) / 2);
    }
    txtElement = [];
    fontType = "Times, Arial";
    fontSize = 13;
    if (!values) {
      values = [];
    }
    parts = values.length;
    if (parts === 0) {
      parts = 9;
    }
    currentMax = -1;
    if (!disableText) {
      i = 0;
      while (i < parts) {
        if (values[i] > currentMax) {
          currentMax = values[i];
          App.flowerCurrentlyActive[hoverIndex] = i;
        }
        i++;
      }
    }
    i = 0;
    element = new Array(7);
    while (i < parts) {
      element[4] = App.createHeart(paper, i, 0);
      element[3] = App.createHeart(paper, i, 1);
      element[2] = App.createHeart(paper, i, 2);
      element[1] = App.createHeart(paper, i, 3);
      element[0] = App.createHeart(paper, i, 4);
      value = values[i];
      hearts = Math.ceil(value / 2);
      i2 = 0;
      while (i2 < 10) {
        App.doTransform(element[i2], width, height, originalWidth, originalHeight);
        if (element[i2]) {
          if (i2 < hearts) {
            App.setSelected(element[i2], false);
            $(element[i2].node).attr('data-selected-' + i + "-" + hoverIndex, true);
            if (i === App.flowerCurrentlyActive[hoverIndex]) {
              App.setSelected(element[i2], true);
            }
          } else {
            App.setUnselected(element[i2], false);
            $(element[i2].node).attr('data-unselected-' + i + "-" + hoverIndex, true);
            if (i === App.flowerCurrentlyActive[hoverIndex]) {
              App.setUnselected(element[i2], true);
            }
          }
          if (!disableText) {
            $(element[i2].node).bind('mouseover', {
              belongsto: i,
              flowerHoverIndex: hoverIndex
            }, handleMouseOver);
          }
        }
        i2++;
      }
      i++;
    }
    innerElement = App.createInnerElement(paper);
    App.doTransform(innerElement, width, height, originalWidth, originalHeight);
    App.setSelected(innerElement, false);
    if (overlayPath) {
      imageOverlay = paper.image(overlayPath, 0, 0, width, height);
    }
    i = 0;
    while (i < 30) {
      borderArrow = null;
      if (!disableText) {
        borderArrow = App.createBorderArrow(paper, i);
      }
      if (borderArrow) {
        App.setSelected(borderArrow, false);
        if (i === App.flowerCurrentlyActive[hoverIndex]) {
          App.setSelected(borderArrow, true);
        }
        $(borderArrow.node).attr('data-selected-' + i + "-" + hoverIndex, true);
        $(borderArrow.node).attr('data-borderarrow-' + i + "-" + hoverIndex, true);
        App.doTransform(borderArrow, width, height, originalWidth, originalHeight);
        $(borderArrow.node).bind('mouseover', {
          belongsto: i,
          flowerHoverIndex: hoverIndex
        }, handleMouseOver);
        if (i !== App.flowerCurrentlyActive[hoverIndex]) {
          borderArrow.hide();
        }
      }
      borderText = null;
      if (borderText) {
        App.setSelected(borderText, false);
        $(borderText.node).attr('data-selected-' + i + "-" + hoverIndex, true);
        $(borderText.node).attr('data-textelement-small-' + i + "-" + hoverIndex, true);
        App.doTransform(borderText, width, height, originalWidth, originalHeight);
        $(borderText.node).bind('mouseover', {
          belongsto: i,
          flowerHoverIndex: hoverIndex
        }, handleMouseOver);
      }
      borderTextLarge = null;
      if (!disableText) {
        borderTextLarge = App.createBorderText(paper, i);
      }
      if (borderTextLarge) {
        if (i !== App.flowerCurrentlyActive[hoverIndex]) {
          borderTextLarge.hide();
        }
        App.setSelected(borderTextLarge, false);
        if (i === App.flowerCurrentlyActive[hoverIndex]) {
          App.setSelected(borderTextLarge, true);
        }
        $(borderTextLarge.node).attr('data-selected-' + i + "-" + hoverIndex, true);
        $(borderTextLarge.node).attr('data-textelement-large-' + i + "-" + hoverIndex, true);
        App.doTransform(borderTextLarge, width, height, originalWidth, originalHeight);
        borderTextLarge.scale(width / 1000 * 1.3, height / 1000 * 1.3);
        $(borderTextLarge.node).bind('mouseover', {
          belongsto: i,
          flowerHoverIndex: hoverIndex
        }, handleMouseOver);
      }
      reflection = null;
      if (!disableText) {
        reflection = App.createReflection(paper, i);
        App.doTransform(reflection, width, height, originalWidth, originalHeight);
        App.colorizeReflection(reflection);
        if (reflection) {
          bto = App.getBelongsToOfReflection(i);
          if (bto === -2) {
            if (!(relationshipType != null)) {
              bto = -1;
            }
          }
          if (!disableText) {
            $(reflection.node).bind('mouseover', {
              belongsto: bto,
              flowerHoverIndex: hoverIndex
            }, handleMouseOver);
          }
        }
      }
      i++;
    }
    if (!disableText) {
      if (relationshipType != null) {
        letter = App.createLetter(paper, relationshipType);
        $(letter.node).attr('data-letter-' + (-2), true);
        $(letter.node).bind('mouseover', {
          belongsto: -2,
          flowerHoverIndex: hoverIndex
        }, handleMouseOver);
        App.doTransform(letter, width, height, originalWidth, originalHeight);
        if (App.flowerCurrentlyActive[hoverIndex] === -2) {
          App.colorizeLetter(letter, true);
        } else {
          App.colorizeLetter(letter, false);
        }
      }
    }
    i = -2;
    while (i < 10) {
      if (i !== -1) {
        if (i !== App.flowerCurrentlyActive[hoverIndex]) {
          $("[id=flower-popup-explanation-" + i + "-" + hoverIndex + "]").each(hideExplanation);
          $("[id=flower-popup-explanation-" + i + "]").each(hideExplanation);
        } else {
          $("[id=flower-popup-explanation-" + i + "-" + hoverIndex + "]").each(showExplanation);
          $("[id=flower-popup-explanation-" + i + "]").each(showExplanation);
        }
      }
      i++;
    }
    return paper.safari();
  };
}).call(this);
App.FlowerPNG = function(container, attributeValues, relationshipType, size, hoverIndex, branch, stalk) {
  var self = this;
  
  this.container = container;
  this.attributeValues = attributeValues;
	this.relationshipType = relationshipType;
	this.size = size;				
  this.counterIndex = hoverIndex;
  
	// attributeValues expects an array from [0..7] with values from [1..5]
	// relationshipType expects a value from [1..4] for type A, B, C, D or uses value 0 for no relationshipType (default image)
	
	this.numberOfBranches = 8;
	this.flowerValues = new Array(this.numberOfBranches + 1);				
	this.currentHighlight = 0;

	// initialize random values for testing
	// this.flowerValues[0] = this.randomFromTo(1, 4);
	// for(i=1; i <= this.numberOfBranches; i++) {
		// this.flowerValues[i] = this.randomFromTo(1, 5);
	// }

	this.flowerValues[0] = relationshipType;
	this.flowerValues[1] = attributeValues[0];
	this.flowerValues[2] = attributeValues[1];
	this.flowerValues[3] = attributeValues[2];
	this.flowerValues[4] = attributeValues[3];
	this.flowerValues[5] = attributeValues[4];
	this.flowerValues[6] = attributeValues[5];
	this.flowerValues[7] = attributeValues[6];
	this.flowerValues[8] = attributeValues[7];	  

	if(this.flowerValues[0] < 0) {
		this.flowerValues[0] = 0; // 0 is default image, value 1 means relationship type A
	}
	else if(this.flowerValues[0] > 4) {
		this.flowerValues[0] = 4; // 4 is relationship type D
	}

	for(i=1; i <= this.numberOfBranches; i++) {
		if(this.flowerValues[i] < 1) {
			this.flowerValues[i] = 1; // minimum flower value 1
		}
		else if(this.flowerValues[i] > 5) {
			this.flowerValues[i] = 5; // maximum flower value 5
		}
	}

	this.render(this.container, this.size);

	// initialize hover functionality
	this.container.find(".stalkHoverMap").hover(function() { self.doStalkHighlight(); }, function() {	});   			   		   			

	this.container.find(".branchHover1").hover(function() { self.doHighlight(1); }, function() { });
	this.container.find(".branchHover2").hover(function() { self.doHighlight(2); }, function() { });
	this.container.find(".branchHover3").hover(function() { self.doHighlight(3); }, function() { });
	this.container.find(".branchHover4").hover(function() { self.doHighlight(4); }, function() { });
	this.container.find(".branchHover5").hover(function() { self.doHighlight(5); }, function() { });
	this.container.find(".branchHover6").hover(function() { self.doHighlight(6); }, function() { });
	this.container.find(".branchHover7").hover(function() { self.doHighlight(7); }, function() { });
	this.container.find(".branchHover8").hover(function() { self.doHighlight(8); }, function() { });
			
	this.initializeFlowerValues();

	// make it visible
	this.container.find(".flowerVisualizationLarge-"+this.counterIndex).css({display: ""});
	this.container.find(".flowerVisualizationMedium-"+this.counterIndex).css({display: ""});
	this.container.find(".flowerVisualizationSmall-"+this.counterIndex).css({display: ""});
	
	if(branch) {
	  this.doHighlight(branch);
	} else {
	  this.doStalkHighlight();
	}
}

App.FlowerPNG.prototype = {
  randomFromTo: function(from, to) {
       	return Math.floor(Math.random() * (to - from + 1) + from);
  },  
  doShowText: function(index) {		   			
  	this.doShowExplanation(index);

  	for(i=0; i <= this.numberOfBranches; i++) {
  		if(i != index) {
  			// hide all others
  			this.doHideText(i);
  		}
  	}   				

  	if(index == 0) {
  		textelement = this.container.find(".flowerStalkText");
  		textelement.css({display: "inline"});
  	}
  	else {
  		textelement = this.container.find(".flowerText"+index);
  		textelement.css({display: "inline"});
  	}			
  },
  doHideText: function(index) {	   			
  	this.doHideExplanation(index);

  	if(i == 0) {
  		textelement = this.container.find(".flowerStalkText");
  		textelement.css({display: "none"});
  	}
  	else {
  		textelement = this.container.find(".flowerText"+index);
  		textelement.css({display: "none"});
  	}
  },
  doShowExplanation: function(index) {
  	$("#flower-popup-explanation-"+index).css({display: ""});
  	$("#flower-popup-explanation-"+index+"-"+this.counterIndex).css({display: ""});
  },
  doHideExplanation: function(index) {
  	$("#flower-popup-explanation-"+index).css({display: "none"});
  	$("#flower-popup-explanation-"+index+"-"+this.counterIndex).css({display: "none"});
  },
  doStalkHighlight: function() {
		for(i=1; i <= this.numberOfBranches; i++) {   					
			// unhighlight all others
			this.doUnhighlight(i);
		}
	
		for(i=1; i <= this.numberOfBranches; i++) {
			// hide all others
			this.doHideText(i);   				
		}   		
	
		stalk = this.container.find(".flowerStalkL");
		stalk.addClass("isHighlighted");
		stalk.attr({src: "/images/flower/large/stalk"+this.flowerValues[0]+"h.png"});
	
		stalk = this.container.find(".flowerStalkM");
		stalk.addClass("isHighlighted");
		stalk.attr({src: "/images/flower/medium/stalk"+this.flowerValues[0]+"h.png"});
	
		stalk = this.container.find(".flowerStalkS");
		stalk.addClass("isHighlighted");
		stalk.attr({src: "/images/flower/small/stalk"+this.flowerValues[0]+"h.png"});
	
		this.doShowText(0);
	},
  doHighlight: function(index) {
  	this.doShowText(index);

  	for(i=0; i <= this.numberOfBranches; i++) {
  		if(i != index) {
  			// unhighlight all others
  			this.doUnhighlight(i);
  		}
  	}

  	branch = this.container.find(".flowerBranchL"+index);
  	branch.addClass("isHighlighted");
  	branch.attr({src: "/images/flower/large/branch"+index+"_"+this.flowerValues[index]+"h.png"});

  	branch = this.container.find(".flowerBranchM"+index);
  	branch.addClass("isHighlighted");
  	branch.attr({src: "/images/flower/medium/branch"+index+"_"+this.flowerValues[index]+"h.png"});

  	branch = this.container.find(".flowerBranchS"+index);
  	branch.addClass("isHighlighted");
  	branch.attr({src: "/images/flower/small/branch"+index+"_"+this.flowerValues[index]+"h.png"});
  },  			
  doUnhighlight: function(index) {
  	if(index == 0) {
  		stalk = this.container.find(".flowerStalkL"); 
  		stalk.removeClass("isHighlighted");
  		stalk.attr({src: "/images/flower/large/stalk"+this.flowerValues[0]+".png"});
	
  		stalk = this.container.find(".flowerStalkM");
  		stalk.removeClass("isHighlighted");
  		stalk.attr({src: "/images/flower/medium/stalk"+this.flowerValues[0]+".png"});
	
  		stalk = this.container.find(".flowerStalkS");
  		stalk.removeClass("isHighlighted");
  		stalk.attr({src: "/images/flower/small/stalk"+this.flowerValues[0]+".png"});    				    				
  	}
  	else {
  		branch = this.container.find(".flowerBranchL"+index);
  		branch.removeClass("isHighlighted");
  		branch.attr({src: "/images/flower/large/branch"+index+"_"+this.flowerValues[index]+".png"});
	
  		branch = this.container.find(".flowerBranchM"+index);
  		branch.removeClass("isHighlighted");
  		branch.attr({src: "/images/flower/medium/branch"+index+"_"+this.flowerValues[index]+".png"});
	
  		branch = this.container.find(".flowerBranchS"+index);
  		branch.removeClass("isHighlighted");
  		branch.attr({src: "/images/flower/small/branch"+index+"_"+this.flowerValues[index]+".png"});
  	}
  },
  initializeFlowerValues: function() {		
  	if(this.size != 1) {								
  		maxBranch = 1;
  		maxValue  = 0;

  		for(i=1; i <= this.numberOfBranches; i++) {						
  			this.doUnhighlight(i);
	
  			if(this.flowerValues[i] > maxValue) {
  				maxValue = this.flowerValues[i];
  				maxBranch = i;
  			}
  		}
						
  		this.doHighlight(maxBranch);
  		this.currentHighlight = maxBranch;
	
  		for(i=-2; i <= 9; i++) {
  			this.doHideExplanation(i);
  		}
  	}
  },
  render: function(container, size) {
  	if(size == 3) {
  		container.html(
  			'<div class="flowerVisualizationLarge-'+this.counterIndex+'" style="margin-left: -20px; margin-top: -20px; display: none; width:383px; height:402px;">'+
  				'<img border="0" class="flowerCenter" style="display:inline; position: absolute; margin-left:177px; margin-top:178px; z-index: 1;"                 src="/images/flower/large/center.png"/>'+
  				'<img border="0" class="flowerText flowerText1" style="display:none; position: absolute; margin-left:51px; margin-top:267px; z-index: 2;"          src="/images/flower/large/branch1_text.png" />'+
  				'<img border="0" class="flowerText flowerText2" style="display:none; position: absolute; margin-left:8px; margin-top:162px; z-index: 3;"           src="/images/flower/large/branch2_text.png" />'+
  				'<img border="0" class="flowerText flowerText3" style="display:none; position: absolute; margin-left:15px; margin-top:69px; z-index: 4;"           src="/images/flower/large/branch3_text.png" />'+
  				'<img border="0" class="flowerText flowerText4" style="display:none; position: absolute; margin-left:77px; margin-top:14px; z-index: 5;"           src="/images/flower/large/branch4_text.png" />'+
  				'<img border="0" class="flowerText flowerText5" style="display:none; position: absolute; margin-left:187px; margin-top:18px; z-index: 6;"          src="/images/flower/large/branch5_text.png" />'+
  				'<img border="0" class="flowerText flowerText6" style="display:none; position: absolute; margin-left:279px; margin-top:66px; z-index: 7;"          src="/images/flower/large/branch6_text.png" />'+
  				'<img border="0" class="flowerText flowerText7" style="display:none; position: absolute; margin-left:317px; margin-top:160px; z-index: 8;"         src="/images/flower/large/branch7_text.png" />'+
  				'<img border="0" class="flowerText flowerText8" style="display:none; position: absolute; margin-left:237px; margin-top:253px; z-index: 9;"         src="/images/flower/large/branch8_text.png" />'+
  				'<img border="0" class="flowerText flowerStalkText" style="display:none; position: absolute; margin-left:137px; margin-top:343px; z-index: 10;"    src="/images/flower/large/branch9_text.png" />'+
  				'<img border="0" class="flowerBranch flowerBranchL1" data-id="1" style="display:inline; position: absolute; margin-left:83px; margin-top:198px; z-index: 11;"  src="/images/flower/large/branch1_'+this.flowerValues[1]+'.png"/>'+
  				'<img border="0" class="flowerBranch flowerBranchL2" data-id="2" style="display:inline; position: absolute; margin-left:52px; margin-top:176px; z-index: 12;"  src="/images/flower/large/branch2_'+this.flowerValues[2]+'.png"/>'+
  				'<img border="0" class="flowerBranch flowerBranchL3" data-id="3" style="display:inline; position: absolute; margin-left:61px; margin-top:98px; z-index: 13;"   src="/images/flower/large/branch3_'+this.flowerValues[3]+'.png"/>'+
  				'<img border="0" class="flowerBranch flowerBranchL4" data-id="4" style="display:inline; position: absolute; margin-left:115px; margin-top:55px; z-index: 14;"  src="/images/flower/large/branch4_'+this.flowerValues[4]+'.png"/>'+
  				'<img border="0" class="flowerBranch flowerBranchL5" data-id="5" style="display:inline; position: absolute; margin-left:190px; margin-top:55px; z-index: 15;"  src="/images/flower/large/branch5_'+this.flowerValues[5]+'.png"/>'+
  				'<img border="0" class="flowerBranch flowerBranchL6" data-id="6" style="display:inline; position: absolute; margin-left:199px; margin-top:98px; z-index: 16;"  src="/images/flower/large/branch6_'+this.flowerValues[6]+'.png"/>'+
  				'<img border="0" class="flowerBranch flowerBranchL7" data-id="7" style="display:inline; position: absolute; margin-left:200px; margin-top:175px; z-index: 17;" src="/images/flower/large/branch7_'+this.flowerValues[7]+'.png"/>'+
  				'<img border="0" class="flowerBranch flowerBranchL8" data-id="8" style="display:inline; position: absolute; margin-left:197px; margin-top:198px; z-index: 18;" src="/images/flower/large/branch8_'+this.flowerValues[8]+'.png"/>'+
  				'<img border="0" class="flowerStalk flowerStalkL" style="display:inline; position: absolute; margin-left:159px; margin-top:199px; z-index: 19;"                src="/images/flower/large/stalk'+this.flowerValues[0]+'.png"/>'+
  				'<img border="0" class="flowerShadow" style="display:inline; position: absolute; margin-left:0px; margin-top:0px; z-index: 20;"                    src="/images/flower/large/shadow.png" usemap="#totalHoverMapLarge"/>'+
  				'<map name="totalHoverMapLarge" id="totalHoverMapLarge">'+
  					'<area shape="poly" coords="182,199,172,201,84,258,85,282,121,310,147,302,182,209" class="branchHover1"/>'+
  					'<area shape="poly" coords="178,192,169,187,77,176,53,178,53,245,86,245,164,199" class="branchHover2"/>'+
  					'<area shape="poly" coords="180,187,175,172,102,98,77,103,61,130,64,162,170,187" class="branchHover3"/>'+		
  					'<area shape="poly" coords="186,179,173,173,115,88,122,63,170,56,190,75,190,171" class="branchHover4"/>'+						
  					'<area shape="poly" coords="195,179,208,173,266,88,259,63,211,56,191,75,191,171" class="branchHover5"/>'+
  					'<area shape="poly" coords="200,187,205,172,278,98,303,103,319,130,316,162,210,187" class="branchHover6"/>'+		
  					'<area shape="poly" coords="201,191,210,186,302,175,326,177,326,244,293,244,215,198" class="branchHover7"/>'+		
  					'<area shape="poly" coords="199,199,209,201,297,258,296,282,260,310,234,302,199,209" class="branchHover8"/>'+
  					'<area shape="poly" coords="190,201,180,210,174,352,222,343,199,209" class="stalkHoverMap"/>'+
  				'</map>'+
  			'</div>'
  		);
  	}
  	else if(size == 2) {
  		container.html(
  				'<div class="flowerVisualizationMedium-'+this.counterIndex+'" style="margin-left: -9px; margin-top: -19px; display: none; width:283px; height:297px;">'+
  					'<img border="0" class="flowerCenter" style="display:inline; position: absolute; margin-left:130px; margin-top:131px; z-index: 1;"                 src="/images/flower/medium/center.png"/>'+
  					'<img border="0" class="flowerText flowerText1" style="display:none; position: absolute; margin-left:40px; margin-top:197px; z-index: 2;"          src="/images/flower/medium/branch1_text.png" />'+
  					'<img border="0" class="flowerText flowerText2" style="display:none; position: absolute; margin-left:9px; margin-top:120px; z-index: 3;"           src="/images/flower/medium/branch2_text.png" />'+
  					'<img border="0" class="flowerText flowerText3" style="display:none; position: absolute; margin-left:13px; margin-top:53px; z-index: 4;"           src="/images/flower/medium/branch3_text.png" />'+
  					'<img border="0" class="flowerText flowerText4" style="display:none; position: absolute; margin-left:60px; margin-top:14px; z-index: 5;"           src="/images/flower/medium/branch4_text.png" />'+
  					'<img border="0" class="flowerText flowerText5" style="display:none; position: absolute; margin-left:139px; margin-top:16px; z-index: 6;"          src="/images/flower/medium/branch5_text.png" />'+
  					'<img border="0" class="flowerText flowerText6" style="display:none; position: absolute; margin-left:206px; margin-top:51px; z-index: 7;"          src="/images/flower/medium/branch6_text.png" />'+
  					'<img border="0" class="flowerText flowerText7" style="display:none; position: absolute; margin-left:233px; margin-top:120px; z-index: 8;"         src="/images/flower/medium/branch7_text.png" />'+
  					'<img border="0" class="flowerText flowerText8" style="display:none; position: absolute; margin-left:175px; margin-top:187px; z-index: 9;"         src="/images/flower/medium/branch8_text.png" />'+
  					'<img border="0" class="flowerText flowerStalkText" style="display:none; position: absolute; margin-left:101px; margin-top:251px; z-index: 10;"    src="/images/flower/medium/branch9_text.png" />'+
  					'<img border="0" class="flowerBranch flowerBranchM1" data-id="1" style="display:inline; position: absolute; margin-left:61px; margin-top:146px; z-index: 11;"  src="/images/flower/medium/branch1_'+this.flowerValues[1]+'.png"/>'+
  					'<img border="0" class="flowerBranch flowerBranchM2" data-id="2" style="display:inline; position: absolute; margin-left:38px; margin-top:130px; z-index: 12;"  src="/images/flower/medium/branch2_'+this.flowerValues[2]+'.png"/>'+
  					'<img border="0" class="flowerBranch flowerBranchM3" data-id="3" style="display:inline; position: absolute; margin-left:45px; margin-top:72px; z-index: 13;"   src="/images/flower/medium/branch3_'+this.flowerValues[3]+'.png"/>'+
  					'<img border="0" class="flowerBranch flowerBranchM4" data-id="4" style="display:inline; position: absolute; margin-left:85px; margin-top:40px; z-index: 14;"   src="/images/flower/medium/branch4_'+this.flowerValues[4]+'.png"/>'+
  					'<img border="0" class="flowerBranch flowerBranchM5" data-id="5" style="display:inline; position: absolute; margin-left:140px; margin-top:40px; z-index: 15;"  src="/images/flower/medium/branch5_'+this.flowerValues[5]+'.png"/>'+
  					'<img border="0" class="flowerBranch flowerBranchM6" data-id="6" style="display:inline; position: absolute; margin-left:147px; margin-top:72px; z-index: 16;"  src="/images/flower/medium/branch6_'+this.flowerValues[6]+'.png"/>'+
  					'<img border="0" class="flowerBranch flowerBranchM7" data-id="7" style="display:inline; position: absolute; margin-left:148px; margin-top:129px; z-index: 17;" src="/images/flower/medium/branch7_'+this.flowerValues[7]+'.png"/>'+
  					'<img border="0" class="flowerBranch flowerBranchM8" data-id="8" style="display:inline; position: absolute; margin-left:145px; margin-top:146px; z-index: 18;" src="/images/flower/medium/branch8_'+this.flowerValues[8]+'.png"/>'+
  					'<img border="0" class="flowerStalk flowerStalkM" style="display:inline; position: absolute; margin-left:117px; margin-top:147px; z-index: 19;"                src="/images/flower/medium/stalk'+this.flowerValues[0]+'.png"/>'+
  					'<img border="0" class="flowerShadow" style="display:inline; position: absolute; margin-left:0px; margin-top:0px; z-index: 20;"                    src="/images/flower/medium/shadow.png" usemap="#totalHoverMapMedium"/>'+
  					'<map name="totalHoverMapMedium" id="totalHoverMapMedium">'+
  						'<area shape="poly" coords="134,147,127,148,62,190,62,208,89,229,108,223,134,154" class="branchHover1"/>'+
  						'<area shape="poly" coords="131,142,125,138,56,130,39,131,39,181,63,181,121,147" class="branchHover2"/>'+
  						'<area shape="poly" coords="133,138,129,127,75,72,56,76,45,96,47,119,125,138" class="branchHover3"/>'+
  						'<area shape="poly" coords="137,132,128,128,85,65,90,46,125,41,140,55,140,126" class="branchHover4"/>'+
  						'<area shape="poly" coords="144,132,153,128,196,65,191,46,156,41,141,55,141,126" class="branchHover5"/>'+
  						'<area shape="poly" coords="148,138,151,127,205,72,224,76,236,96,233,119,155,138" class="branchHover6"/>'+
  						'<area shape="poly" coords="148,141,155,137,223,129,241,130,241,180,216,180,159,146" class="branchHover7"/>'+
  						'<area shape="poly" coords="147,147,154,148,219,190,219,208,192,229,173,223,147,154" class="branchHover8"/>'+
  						'<area shape="poly" coords="140,148,133,155,128,260,164,253,147,154" class="stalkHoverMap"/>'+
  					'</map>'+
  			'</div>'
  		);
  	}
  	else if(size == 1) {
  		container.html(
  			'<div class="flowerVisualizationSmall-'+this.counterIndex+'" style="margin-left: -15px; margin-top: -21px; display: none; width:153px; height:161px;">'+
  				'<img border="0" class="flowerCenter" style="display:inline; position: absolute; margin-left:70px; margin-top:71px; z-index: 1;"                 src="/images/flower/small/center.png"/>'+
  				'<img border="0" class="flowerBranch flowerBranchS1" data-id="1" style="display:inline; position: absolute; margin-left:33px; margin-top:79px; z-index: 11;" src="/images/flower/small/branch1_'+this.flowerValues[1]+'.png"/>'+
  				'<img border="0" class="flowerBranch flowerBranchS2" data-id="2" style="display:inline; position: absolute; margin-left:20px; margin-top:70px; z-index: 12;" src="/images/flower/small/branch2_'+this.flowerValues[2]+'.png"/>'+
  				'<img border="0" class="flowerBranch flowerBranchS3" data-id="3" style="display:inline; position: absolute; margin-left:24px; margin-top:39px; z-index: 13;" src="/images/flower/small/branch3_'+this.flowerValues[3]+'.png"/>'+
  				'<img border="0" class="flowerBranch flowerBranchS4" data-id="4" style="display:inline; position: absolute; margin-left:46px; margin-top:22px; z-index: 14;" src="/images/flower/small/branch4_'+this.flowerValues[4]+'.png"/>'+
  				'<img border="0" class="flowerBranch flowerBranchS5" data-id="5" style="display:inline; position: absolute; margin-left:76px; margin-top:22px; z-index: 15;" src="/images/flower/small/branch5_'+this.flowerValues[5]+'.png"/>'+
  				'<img border="0" class="flowerBranch flowerBranchS6" data-id="6" style="display:inline; position: absolute; margin-left:79px; margin-top:39px; z-index: 16;" src="/images/flower/small/branch6_'+this.flowerValues[6]+'.png"/>'+
  	      '<img border="0" class="flowerBranch flowerBranchS7" data-id="7" style="display:inline; position: absolute; margin-left:80px; margin-top:70px; z-index: 17;" src="/images/flower/small/branch7_'+this.flowerValues[7]+'.png"/>'+
  	      '<img border="0" class="flowerBranch flowerBranchS8" data-id="8" style="display:inline; position: absolute; margin-left:78px; margin-top:79px; z-index: 18;" src="/images/flower/small/branch8_'+this.flowerValues[8]+'.png"/>'+
  	      '<img border="0" class="flowerStalk flowerStalkS" style="display:inline; position: absolute; margin-left:63px; margin-top:79px; z-index: 19;"                src="/images/flower/small/stalk'+this.flowerValues[0]+'.png"/>'+
  	      '<img border="0" class="flowerShadow" style="display:inline; position: absolute; margin-left:0px; margin-top:0px; z-index: 20;"                  src="/images/flower/small/shadow.png"/>'+
  	      '</div>'
  		);
  	}
  }
};
(function() {
  this.jQuery.fn.setError = function(message) {
    var $el, $errorMessage;
    $el = $(this);
    $el.removeError();
    $errorMessage = $('<span class="error-message">' + message + '</span>');
    return $el.addClass('error').parent().append($errorMessage);
  };
  this.jQuery.fn.removeError = function() {
    $(this).removeClass('error').parent().find('.error-message').remove();
    $(this).parent().find('.success-message').remove();
    $(this).parents('.field_with_errors').removeClass('field_with_errors');
    return $(this).parents('.field_with_error_binding').find('.error').removeClass('error').parent().find('.error-message').remove();
  };
  this.jQuery.fn.setSuccess = function(message) {
    var $el, $successMessage;
    $el = $(this);
    $el.removeError();
    $successMessage = $('<span class="success-message">' + message + '</span>');
    return $el.parent().append($successMessage);
  };
  this.App.Form = {};
  this.App.Form.initFieldAppend = function() {
    return $('.append_fields').live('click', function(e) {
      var container, content, content_id, last_count;
      e.preventDefault();
      content_id = $(this).attr('data-append');
      if (content_id) {
        content = $('#' + content_id + '_template');
        container = $('#' + content_id);
        if (container) {
          last_count = container.find('li:last-child').attr('data-counter');
          return content.tmpl({
            count: parseInt(last_count) + 1
          }).appendTo(container);
        }
      }
    });
  };
  this.App.Form.initFormElements = function() {};
  this.App.Form.initFormFunctions = function() {
    $('[data-action-reset-form]').live('click', function(e) {
      var $el;
      e.preventDefault();
      $el = $(e.currentTarget);
      return $el.closest('form')[0].reset();
    });
    $('[data-action-send-form]').live('click', function(e) {
      var $el;
      e.preventDefault();
      $el = $(e.currentTarget);
      return $el.closest('form').submit();
    });
    $('[data-action-reset-and-send-form]').live('click', function(e) {
      var $el, form;
      e.preventDefault();
      $el = $(e.currentTarget);
      form = $el.closest('form');
      form[0].reset();
      return form.submit();
    });
    $('[data-action-clear-and-send-form]').live('click', function(e) {
      var $el, form;
      e.preventDefault();
      $el = $(e.currentTarget);
      form = $el.closest('form');
      form[0].reset();
      form.find('input[type=text]').val('');
      return form.submit();
    });
    return $('form[data-send-mode=block] input[type=submit]').live('click', function(e) {
      var $el, $form;
      $el = $(e.currentTarget);
      $form = $el.closest('form[data-send-mode=block]');
      $form.bind('ajax:before', function(e) {
        $el.unbind('ajax:before', arguments.callee);
        return $el.attr('disabled', 'disabled');
      });
      $form.bind('ajax:success', function(e) {
        $el.unbind('ajax:success', arguments.callee);
        return $el.removeAttr('disabled');
      });
      return $form.bind('ajax:error', function(e) {
        $el.unbind('ajax:error', arguments.callee);
        return $el.removeAttr('disabled');
      });
    });
  };
  this.App.Form.initPlaceholder = function() {
    return $('input[placeholder]').placeholder();
  };
  this.App.Form.initValidations = function() {
    var $city, $postal_code, currentEmail, currentUserName, validation_messages;
    validation_messages = {
      already_taken: 'ist bereits vergeben',
      max_size_6: 'bitte mindestens 6 Zeichen',
      passwords_not_matching: 'Passwörter stimmen nicht überein',
      plz_not_found: 'PLZ nicht gefunden',
      has_to_be_filled_in: 'muss ausgefüllt werden'
    };
    currentUserName = $('#current_user_name, #user_name').val();
    $('#current_user_name, #user_name').blur(function(e) {
      var $el, name;
      $el = $(this);
      name = $el.val();
      if (name === currentUserName) {
        return $el.removeClass('error');
      } else {
        return $.ajax({
          url: '/api/v1/users/param_availability.json',
          data: {
            'name': 'name',
            'content': name
          },
          success: function(data) {
            if (data.status === 'not_available') {
              return $el.setError(validation_messages.already_taken);
            } else {
              return $el.removeError();
            }
          }
        });
      }
    });
    currentEmail = $('#user_email').val();
    $('#user_email').blur(function(e) {
      var $el, email;
      $el = $(this);
      email = $el.val();
      if (email === currentEmail) {
        return $el.removeClass('error');
      } else {
        return $.ajax({
          url: '/api/v1/users/param_availability.json',
          data: {
            'name': 'email',
            'content': email
          },
          success: function(data) {
            if (data.status === 'not_available') {
              return $el.setError(validation_messages.already_taken);
            } else {
              return $el.removeError();
            }
          }
        });
      }
    });
    $('#current_user_profile_country, #profile_country').change(function() {
      var $el, country;
      $el = $(this);
      country = $el.val().toLowerCase();
      if (country === 'de') {
        return $('#current_user_profile_zip_code, #profile_zip_code').attr('maxlength', '5');
      } else {
        return $('#current_user_profile_zip_code, #profile_zip_code').attr('maxlength', '4');
      }
    });
    $city = $('#current_user_profile_city');
    $postal_code = $('#current_user_profile_zip_code, #profile_zip_code');
    $postal_code.focus(function(e) {
      return $city.val('…');
    });
    $postal_code.blur(function(e) {
      var $el, country, postalCode;
      $el = $(this) || $('#current_user_profile_country, #profile_country');
      country = $('#current_user_profile_country, #profile_country').val().toLowerCase();
      postalCode = $el.val();
      $('#city').remove();
      return $.ajax({
        url: "/cities/" + country + "/" + postalCode + ".json",
        success: function(data) {
          if (data && data.city && data.city.name) {
            $city.val(data.city.name);
            return $el.setSuccess(data.city.name);
          } else {
            return $el.setError(validation_messages.plz_not_found);
          }
        },
        error: function() {
          return $el.setError(validation_messages.plz_not_found);
        }
      });
    });
    $('.letters').keypress(function(e) {
      if (!(String.fromCharCode(e.keyCode).match(/[0-9a-záàäæåçéèëóòöœßúùüÿ -]/i) || e.keyCode < 30)) {
        return e.preventDefault();
      }
    });
    $('.letters-strict').keypress(function(e) {
      if (!(String.fromCharCode(e.keyCode).match(/[0-9a-z_-]/i) || e.keyCode < 30)) {
        return e.preventDefault();
      }
    });
    $('[type=email]').keypress(function(e) {
      if (!(String.fromCharCode(e.keyCode).match(/[0-9a-z@._-]/i) || e.keyCode < 30)) {
        return e.preventDefault();
      }
    });
    $('.numbers').keypress(function(e) {
      if (!(String.fromCharCode(e.keyCode).match(/[0-9]/) || e.keyCode < 30)) {
        return e.preventDefault();
      }
    });
    $('#user_password').blur(function() {
      if ($(this).val().length < 6) {
        return $(this).setError(validation_messages.max_size_6);
      } else if (($(this).val() !== $('#user_password_confirmation').val()) && ($('#user_password_confirmation').val().length > 0)) {
        return $(this).setError(validation_messages.passwords_not_matching);
      } else {
        return $(this).removeError();
      }
    });
    $('#user_profile_attributes_gender, #user_profile_attributes_gender_preference').change(function() {
      if ($(this).val() === "") {
        return $(this).setError(validation_messages.has_to_be_filled_in);
      } else {
        return $(this).removeError();
      }
    });
    $('#user_profile_attributes_steady_relationship').change(function() {
      if (!$(this).val()) {
        return $(this).setError(validation_messages.has_to_be_filled_in);
      } else {
        return $(this).removeError();
      }
    });
    $('#user_password_confirmation').blur(function() {
      if ($(this).val() !== $('#user_password').val()) {
        return $('#user_password').setError(validation_messages.passwords_not_matching);
      } else if ($(this).val().length < 6) {
        return $('#user_password').setError(validation_messages.max_size_6);
      } else {
        return $('#user_password').removeError();
      }
    });
    return $('#current_user_password_confirmation').blur(function() {
      if ($(this).val().length < 6) {
        return $(this).setError(validation_messages.max_size_6);
      } else if ($(this).val() !== $('#current_user_password, #user_password').val()) {
        return $(this).setError(validation_messages.passwords_not_matching);
      } else {
        return $(this).removeError();
      }
    });
  };
  this.App.initForm = function() {
    App.Form.initFieldAppend();
    App.Form.initFormElements();
    App.Form.initFormFunctions();
    App.Form.initPlaceholder();
    return App.Form.initValidations();
  };
}).call(this);
(function() {
  this.App.initGallery = function() {
    var $actions, $actionsOld, $avatarImg, $containment, $currentImage, $gallery, $galleryUploadForm, $jqXHR, $removePrivacy, $setPrivacy, $spinnerOverlay, $ul, MAX_AVATAR_H, MAX_AVATAR_W, applyCropping, applyFileUpload, closePositioner, createUploadForm, initActions, lastUploadedFile, maxImages, navigate, newPictureAdded, pictureReplaced;
    maxImages = 7;
    $gallery = $('#gallery');
    if ($gallery.length) {
      $currentImage = $('#gallery .current-image img');
      $avatarImg = $('#user-avatar img');
      $ul = $gallery.find('ul');
      $galleryUploadForm = $('#gallery-upload form');
      $setPrivacy = $('.set-privacy');
      $removePrivacy = $('.remove-privacy');
      lastUploadedFile = '';
      $spinnerOverlay = null;
      $jqXHR = null;
      if ($gallery.find('.gallery-thumb:first-child').attr('data-is-private') === 'true') {
        $setPrivacy.hide();
      } else {
        $removePrivacy.hide();
      }
      $('[href=#gallery]').fancybox({
        margin: 18,
        padding: 5,
        onStart: function(selectedArray, selectedIndex, selectedOpts) {
          var data_id;
          $gallery.find('[data-is-avatar=true] .show-image').click();
          data_id = $(selectedArray[selectedIndex]).attr('data-id');
          if (data_id) {
            return $gallery.find('[data-id=' + data_id + '] .show-image').click();
          }
        },
        onComplete: function() {
          $('.set-privacy').css({
            minWidth: $('.remove-privacy').outerWidth() + 'px'
          });
          return $('.remove-privacy').css({
            minWidth: $('.set-privacy').outerWidth() + 'px'
          });
        }
      });
      newPictureAdded = function(event, data) {
        var $li, $nextLi, picture;
        picture = data.result.picture;
        $li = $('.gallery-thumb.empty').eq(0);
        $nextLi = $('.gallery-thumb.empty').eq(1);
        if ($nextLi) {
          createUploadForm($nextLi);
        }
        $li.attr({
          'data-id': picture.id,
          'data-is-private': picture.is_private,
          'data-is-avatar': picture.is_avatar
        });
        $li.html("<a class=\"show-image\" href=\"" + picture.image.gallery.url + "\" data-original-url=\"" + picture.image.url + "\">\n  <img src=\"" + picture.image.big.url + "\">\n  <span class=\"is-avatar\">Profilbild</span>\n  <span class=\"is-private\">Gesperrt</span>\n</a>");
        $li.removeClass('empty');
        $li.find('.show-image').click();
        if ($gallery.find('.gallery-thumb.empty').length === 0) {
          $gallery.find('.gallery-add-picture').hide();
          return $gallery.find('.picture-notice').show();
        }
      };
      pictureReplaced = function(event, data) {
        var $li, picture;
        picture = data.result.picture;
        $li = $('.gallery-thumb[data-id=' + picture.id + ']');
        if (picture.is_avatar) {
          $avatarImg.attr('src', picture.image.profile.url);
        }
        $li.attr({
          'data-is-private': picture.is_private,
          'data-is-avatar': picture.is_avatar
        });
        $li.html("<a class=\"show-image\" href=\"" + picture.image.gallery.url + "\" data-original-url=\"" + picture.image.url + "\">\n  <img src=\"" + picture.image.big.url + "\">\n  <span class=\"is-avatar\">Profilbild</span>\n  <span class=\"is-private\">Gesperrt</span>\n</a>");
        $li.css({
          display: 'inline-block'
        }).animate({
          width: '100px'
        }, 'slow');
        return $li.find('.show-image').click();
      };
      createUploadForm = function($element) {
        $element.html("<form class=\"picture-upload\" action=\"/api/v1/pictures.json\" method=\"post\" enctype=\"multipart/form-data\">\n  <input type=\"file\" name=\"picture[image]\" accept=\"image/*\" />\n  <div class=\"fake-input\"></div>\n</form>");
        return applyFileUpload($element.find('.picture-upload'));
      };
      applyFileUpload = function($form) {
        return $form.fileupload({
          url: '/api/v1/pictures',
          type: 'POST',
          dataType: 'json',
          dropZone: null,
          maxFileSize: 10000000,
          acceptFileTypes: /(\.|\/)(jpe?g|png)$/i,
          previewFileTypes: /^image\/(jpe?g|png)$/i,
          fail: function(event, data) {
            var json;
            log("fail", event, data);
            if (data.jqXHR && data.jqXHR.responseText) {
              json = JSON.parse(data.jqXHR.responseText);
              if ($('#gallery-upload .error-message').length === 0) {
                $('<span class="error-message"></span>').insertBefore($('#gallery .actions'));
              }
              return $('#gallery .error-message').text(json['errors']['image'].join(', '));
            }
          },
          done: function(event, data) {
            log("done", event, data);
            if ($(this).hasClass('replace')) {
              return pictureReplaced(event, data);
            } else {
              return newPictureAdded(event, data);
            }
          },
          start: function(event) {
            log("start", event);
            if (!$(this).hasClass('replace')) {
              $ul.find('li.empty').eq(0).addClass('loading');
            }
            $spinnerOverlay = App.spinner().init({
              el: $gallery,
              text: 'Bild wird hochgeladen...<span id="upload-progress"></span><button class="button cancel-picture-upload tooltip_2" title="Aktuellen Upload-Vorgang abbrechen">Abbrechen</button>'
            });
            return App.initTooltip();
          },
          add: function(event, data) {
            log("add", event, data);
            if ($('#gallery .error-message').length > 0) {
              $('#gallery .error-message').remove();
            }
            if ($(this).hasClass('replace')) {
              data.url = '/api/v1/pictures/' + $('#gallery .current').attr('data-id');
              data.type = 'PUT';
            } else {
              data.url = '/api/v1/pictures';
              data.type = 'POST';
            }
            return $jqXHR = data.submit();
          },
          progress: function(event, data) {
            log("progress", event, data);
            return $('#upload-progress').text(parseInt(data.loaded / data.total * 100, 10) + '%');
          },
          always: function(event) {
            log("always", event);
            $ul.find('li').removeClass('loading');
            $('#upload-progress').empty();
            return $spinnerOverlay.remove();
          }
        });
      };
      applyCropping = function(image, cropData) {
        image.css('left', cropData.x).css('top', cropData.y);
        if (cropData.width > 0) {
          return image.css({
            'width': cropData.width,
            'height': 'auto'
          });
        }
      };
      $('form.picture-upload').each(function() {
        return applyFileUpload($(this));
      });
      $('button.cancel-picture-upload').live('click', function(event) {
        if ($jqXHR) {
          return $jqXHR.abort();
        }
      });
      initActions = function($li) {
        var isAvatar, isPrivate;
        isAvatar = $li.attr('data-is-avatar') === 'true';
        isPrivate = $li.attr('data-is-private') === 'true';
        $li.addClass('current').siblings().removeClass('current');
        $gallery.find('.set-avatar').attr('disabled', isAvatar);
        $gallery.find('.set-avatar-position').attr('disabled', !isAvatar);
        $gallery.find('.set-privacy').attr('disabled', isAvatar);
        $gallery.find('.remove-privacy').attr('disabled', isAvatar);
        $gallery.find('.button.delete').attr('disabled', isAvatar);
        $setPrivacy[isPrivate ? 'hide' : 'show']();
        return $removePrivacy[isPrivate ? 'show' : 'hide']();
      };
      $gallery.delegate('ul .show-image', 'click', function(e) {
        var $li;
        e.preventDefault();
        if ($gallery.hasClass('cropping')) {
          return;
        }
        $currentImage.attr('src', this.href);
        $currentImage.data({
          'gallery-url': this.href,
          'original-url': $(this).data('original-url')
        });
        $li = $(this).parent();
        return initActions($li);
      });
      navigate = function(e, direction, fallback) {
        var $prevThumb, currentSrc;
        e.preventDefault();
        currentSrc = $currentImage.attr('src').replace(/http:\/\/.+?\//, '/');
        $prevThumb = $gallery.find('.current')[direction]().find('.show-image');
        if (!$prevThumb.length) {
          $prevThumb = $gallery.find('ul .show-image')[fallback]();
        }
        return $prevThumb.click();
      };
      $gallery.delegate('.prev', 'click', function(e) {
        return navigate(e, 'prev', 'last');
      });
      $gallery.delegate('.next', 'click', function(e) {
        return navigate(e, 'next', 'first');
      });
      $gallery.delegate('.delete', 'click', function(e) {
        var $li, id;
        e.preventDefault();
        if (confirm('Möchten Sie dieses Bild wirklich löschen?')) {
          $li = $('#gallery .current');
          id = $li.attr('data-id');
          $li.siblings().first().find('.show-image').click();
          $li.empty().addClass('empty').appendTo($ul);
          if ($ul.find('li.empty').length === 1) {
            createUploadForm($ul.find('li.empty'));
          }
          if ($gallery.find('.gallery-thumb.empty').length !== 0) {
            $gallery.find('.picture-notice').hide();
            $gallery.find('.gallery-add-picture').show();
          }
          return $.ajax({
            url: "/api/v1/pictures/" + id,
            type: "delete"
          });
        }
      });
      $gallery.delegate('.set-privacy, .remove-privacy', 'click', function(e) {
        var $li, id, isPrivate;
        e.preventDefault();
        $li = $('#gallery .current');
        id = $li.attr('data-id');
        isPrivate = $(this).hasClass('set-privacy');
        $setPrivacy[isPrivate ? 'hide' : 'show']();
        $removePrivacy[isPrivate ? 'show' : 'hide']();
        $li.attr('data-is-private', isPrivate);
        $li.find('.show-image').click();
        return $.ajax({
          url: "/api/v1/pictures/" + id,
          type: "put",
          data: {
            picture: {
              is_private: isPrivate
            }
          }
        });
      });
      $gallery.delegate('.set-avatar', 'click', function(e) {
        var $li, id;
        e.preventDefault();
        $li = $('#gallery .current');
        id = $li.attr('data-id');
        $li.attr({
          'data-is-avatar': true,
          'data-is-private': false
        });
        $li.siblings().attr('data-is-avatar', false);
        $li.find('.show-image').click();
        $avatarImg.css({
          width: 'auto',
          left: 'auto',
          top: 'auto'
        });
        $li.parent('ul').prepend($li.detach());
        return $.ajax({
          url: "/api/v1/pictures/" + id + "/set_as_avatar",
          type: "put",
          success: function(data) {
            return $avatarImg.attr('src', data.picture.image.profile.url);
          }
        });
      });
      MAX_AVATAR_W = 522;
      MAX_AVATAR_H = 370;
      $actions = $gallery.find('.actions');
      $actionsOld = $actions.html();
      $containment = function($width, $height) {
        if ($width < MAX_AVATAR_W && $height >= MAX_AVATAR_H) {
          $currentImage.width(MAX_AVATAR_W);
          $width = MAX_AVATAR_W;
          $height = $currentImage.height();
          $gallery.find('.zoom-out').attr('disabled', true);
        } else if ($height < MAX_AVATAR_H && $width >= MAX_AVATAR_W) {
          $currentImage.height(MAX_AVATAR_H);
          $height = MAX_AVATAR_H;
          $width = $currentImage.width();
          $gallery.find('.zoom-out').attr('disabled', true);
        } else if ($height <= MAX_AVATAR_H && $width <= MAX_AVATAR_W) {
          $currentImage.width('auto');
          $currentImage.height(MAX_AVATAR_H);
          if ($currentImage.width() < MAX_AVATAR_W) {
            $currentImage.height('auto');
            $currentImage.width(MAX_AVATAR_W);
            $width = MAX_AVATAR_W;
            $height = $currentImage.height();
          } else {
            $height = MAX_AVATAR_H;
            $width = $currentImage.width();
          }
          $gallery.find('.zoom-out').attr('disabled', true);
        } else {
          $gallery.find('.zoom-out').removeAttr('disabled');
        }
        return [$gallery.offset().left + ($width - MAX_AVATAR_W) * -1, $gallery.offset().top + ($height - MAX_AVATAR_H) * -1, $gallery.offset().left, $gallery.offset().top];
      };
      $gallery.delegate('.set-avatar-position', 'click', function(e) {
        var $li, boxHeight, boxWidth, canDrag, dragBox, dragItem, dragItemLeft, dragItemTop, imageCroppingData, maxX, maxY, mouseX, mouseY;
        e.preventDefault();
        $gallery.addClass('cropping');
        if ($('#gallery-crop-overlay').length === 0) {
          $('#gallery .current-image').append($('<div id="gallery-crop-overlay"></div>'));
        }
        if ($('#thumbnail-overlay').length === 0) {
          $('#gallery .current-image').append($('<div id="thumbnail-overlay"></div>'));
        }
        App.initTooltip();
        if ($('#gallery-dragbox').length === 0) {
          $('#gallery .current-image').append($('<div id="gallery-dragbox"></div>'));
        }
        $li = $gallery.find('li[data-is-avatar=true]');
        imageCroppingData = {
          'x': parseInt($li.attr('data-avatar-position-x')),
          'y': parseInt($li.attr('data-avatar-position-y')),
          'width': parseInt($li.attr('data-avatar-width'))
        };
        $currentImage.parent().css({
          'text-align': 'left',
          'padding-left': 0
        });
        $currentImage.attr('src', $currentImage.data('original-url'));
        $currentImage.css({
          'vertical-align': 'top',
          'max-width': 'none',
          'max-height': 'none',
          'position': 'relative'
        });
        $currentImage.draggable({
          containment: $containment($currentImage.width(), $currentImage.height())
        });
        applyCropping($currentImage, imageCroppingData);
        dragBox = $('#gallery .current-image');
        dragItem = $currentImage;
        boxWidth = $('#gallery-dragbox').width();
        boxHeight = $('#gallery-dragbox').height();
        canDrag = false;
        mouseX = mouseY = dragItemLeft = dragItemTop = null;
        maxX = maxY = 0;
        dragBox.mousedown(function(event) {
          canDrag = true;
          dragBox.addClass('canDrag');
          mouseX = event.pageX;
          mouseY = event.pageY;
          dragItemLeft = parseInt(dragItem.css('left'));
          dragItemTop = parseInt(dragItem.css('top'));
          return false;
        });
        $(document).mouseup(function() {
          canDrag = false;
          return dragBox.removeClass('canDrag');
        });
        $(document).mousemove(function(event) {
          var leftX, minX, minY, mousemoveX, mousemoveY, topY;
          if (canDrag) {
            minX = boxWidth - dragItem.width();
            minY = boxHeight - dragItem.height();
            mousemoveX = event.pageX - mouseX;
            mousemoveY = event.pageY - mouseY;
            leftX = dragItemLeft + mousemoveX;
            topY = dragItemTop + mousemoveY;
            if (minX <= leftX && leftX <= maxX) {
              dragItem.css('left', leftX + 'px');
            }
            if (minY <= topY && topY <= maxY) {
              dragItem.css('top', topY + 'px');
            }
          }
          return false;
        });
        $gallery.find("a.prev, a.next").hide();
        $actions.html('<div id="gallery-position-zoom"><button class="button zoom-in tooltip_2" title="Bild vergrößern">Zoom größer</button><button class="button zoom-out tooltip_2" title= "Bild verkleinern">Zoom kleiner</button><p>Positionieren Sie das Bild durch Ziehen mit der Maus</p></div><button class="button avatar-position-save tooltip_2" title="Speichern und zurück zur Übersicht">Bildausschnitt speichern</button><button class="button avatar-position-cancel tooltip_2" title="Vorgang abbrechen">Abbrechen</button>');
        return App.initTooltip();
      });
      $gallery.delegate('.avatar-position-save', 'click', function(e) {
        var cropData, id, newPositionLeft, newPositionTop, newWidth;
        e.preventDefault();
        id = $('#gallery .current').attr('data-id');
        App.initTooltip();
        newPositionLeft = $currentImage.position().left;
        newPositionTop = $currentImage.position().top;
        newWidth = $currentImage.width();
        $avatarImg.attr('src', $currentImage.src);
        cropData = {
          x: newPositionLeft,
          y: newPositionTop,
          width: newWidth
        };
        $gallery.find('li.current').attr({
          'data-avatar-position-x': cropData.x,
          'data-avatar-position-y': cropData.y,
          'data-avatar-width': cropData.width
        });
        closePositioner();
        return $.ajax({
          url: "/api/v1/pictures/" + id,
          type: "put",
          data: {
            picture: {
              avatar_position_x: newPositionLeft,
              avatar_position_y: newPositionTop,
              avatar_width: newWidth
            }
          },
          success: function(data) {
            var match, newSrc;
            match = $avatarImg.attr('src').match(/(.+)(?:\?\d+$)?/);
            newSrc = "" + match[1] + "?" + (new Date().getTime());
            return $avatarImg.attr('src', newSrc);
          }
        });
      });
      $gallery.delegate('.avatar-position-cancel', 'click', function(e) {
        e.preventDefault();
        closePositioner();
        return App.initTooltip();
      });
      closePositioner = function() {
        $gallery.removeClass('cropping');
        $gallery.find("a.prev, a.next").show();
        $('#gallery-crop-overlay').remove();
        $('#thumbnail-overlay').remove();
        $('#gallery-dragbox').remove();
        $actions.html($actionsOld);
        initActions($gallery.find('ul li.current'));
        $currentImage.attr('src', $currentImage.data('gallery-url'));
        $currentImage.css({
          width: 'auto',
          height: 'auto',
          position: 'static',
          left: 'auto',
          top: 'auto',
          'vertical-align': 'middle'
        });
        return $currentImage.parent().css({
          'text-align': 'center',
          'padding-left': '50px'
        });
      };
      $gallery.delegate('.zoom-in', 'click', function(e) {
        e.preventDefault();
        return $currentImage.height('auto').width($currentImage.width() * 1.1).draggable("option", "containment", $containment($currentImage.width(), $currentImage.height())).css({
          left: 0,
          top: 0
        });
      });
      return $gallery.delegate('.zoom-out', 'click', function(e) {
        e.preventDefault();
        return $currentImage.height('auto').width($currentImage.width() * 0.9).draggable("option", "containment", $containment($currentImage.width(), $currentImage.height())).css({
          left: 0,
          top: 0
        });
      });
    }
  };
}).call(this);
(function() {
  this.App.GetFunctions = {};
  this.App.GetFunctions.init = function() {};
  this.App.GetFunctions.initInvitations = function() {
    var trigger;
    trigger = $(document).getUrlParam('open_membership_invitations_popup');
    if (trigger && trigger === 'true') {
      $('[data-action=open-membership-invitations-popup]').first().trigger("click");
    }
    trigger = $(document).getUrlParam('open_game_popup');
    if (trigger && trigger === 'true') {
      $('[data-action=open-game-popup]').first().trigger("click");
    }
    trigger = $(document).getUrlParam('open_invitations_popup');
    if (trigger && trigger === 'true') {
      return $('[data-action=open-invitations-popup]').first().trigger("click");
    }
  };
}).call(this);
(function() {
  this.App.initHelpOverlays = function(pictures, videos, helpId) {
    if (videos && (videos.length > 0) && (($('html').hasClass("video") === true) || swfobject.hasFlashPlayerVersion("10.0.0"))) {
      $('#help-overlay-pictures-' + helpId).css('display', 'none');
      $('#help-overlay-videos-' + helpId).show();
      $('#help-overlay-videos-' + helpId).empty();
      $.each(videos, function(idx, vid) {
        return $('#help-overlay-videos-' + helpId).append('<iframe src="http://player.vimeo.com/video/' + vid.id + '?title=0&amp;byline=0&amp;portrait=0&amp;color=7F70BA" width="400" height="235" frameborder="0" webkitAllowFullScreen allowFullScreen autoplay></iframe>');
      });
      $('#help-overlay-text-' + helpId).css('overflow', 'auto');
      return $('#help-error-' + helpId).css('display', 'none');
    } else if ((!videos) && (($('html').hasClass("video") === true) || swfobject.hasFlashPlayerVersion("10.0.0"))) {
      $('#help-overlay-pictures-').show();
      return $.each(pictures, function(idx, pic) {
        $('#help-overlay-pictures-' + helpId).append("<img src=" + pic.src + "  style='max-width: 420px;'></img><br />");
        $('#help-overlay-content-' + helpId).css('overflow', 'auto');
        $('#help-notice-' + helpId).css('display', '');
        return $('#help-error-' + helpId).css('display', 'none');
      });
    } else {
      $('#help-overlay-pictures-').show();
      return $.each(pictures, function(idx, pic) {
        $('#help-overlay-pictures-' + helpId).append("<img src=" + pic.src + "  style='max-width: 400px;'></img><br />");
        $('#help-overlay-content-' + helpId).css('overflow', 'auto');
        $('#help-notice-' + helpId).css('display', 'none');
        return $('#help-error-' + helpId).css('display', '');
      });
    }
  };
  this.App.initHelpMouseHandlers = function() {
    $('[data-hover-show]').live('mouseenter', function(e) {
      var $el, selector;
      $el = $(e.currentTarget);
      selector = $el.attr('data-hover-show');
      return $(selector).css('display', 'inline-block');
    });
    return $('[data-hover-show]').live('mouseleave', function(e) {
      var $el, selector;
      $el = $(e.currentTarget);
      selector = $el.attr('data-hover-show');
      return $(selector).hide();
    });
  };
}).call(this);
(function() {
  this.App.initIdFocus = function() {
    var els;
    els = $('[data-id-focus]');
    return els.each(function(idx, el) {
      var $el, id;
      $el = $(el);
      id = $el.attr('data-id-focus');
      $el.bind('click', function(e) {
        e.preventDefault();
        return $(id).focus();
      });
      return $el.bind('focus', function(e) {
        e.preventDefault();
        return $(id).focus();
      });
    });
  };
}).call(this);
(function() {
  this.App.initIdScroller = function() {
    return $('[data-id-scroll]').live('click', function(e) {
      var $el, id, new_url;
      e.preventDefault();
      $el = $(e.currentTarget);
      id = $el.attr('href');
      new_url = /\#/.test(location.href) ? location.href.replace(/\#.+/, id) : location.href + id;
      window.history.pushState({}, "page-" + id, new_url);
      return $('html,body').animate({
        scrollTop: $(id).offset().top
      });
    });
  };
}).call(this);
(function() {
  this.App.initTabSwitch = function() {
    var els;
    els = $('[data-id-tab-switch]');
    return els.each(function(idx, el) {
      var $el, id;
      $el = $(el);
      id = $el.attr('data-id-tab-switch');
      return $el.bind('click', function(e) {
        e.preventDefault();
        $(id).trigger('click');
        return $el.trigger('focus');
      });
    });
  };
}).call(this);
App.image = (function() {

    var el,
    fill = true,

    init = function(options) {
      el = options.el;        
      if (options.hasOwnProperty("fill")) {            
        fill = options.fill;
      }

      el.hide();
      el.load(function() {
        render();
      })

      var imageNode;
      el.each(function(index, element) {
        imageNode = $(element);
        if (imageNode.width() !== null && imageNode.height() !== null) {
          renderImage(imageNode);
        }
      });
    },

    render = function() {    
      if (el.size() > 0) {
        el.each(function(index, element) {
          renderImage($(element));
        });
      } else {
        renderImage(el);
      }      
    },

    renderImage = function(image) {     
      image.css({"width": "auto", "height": "auto"});
      
      var fitRect = getFitRect(
        {x: 0, y: 0, width: image.width(), height: image.height()},
        {x: 0, y: 0, width: image.parent().width(), height: image.parent().height()},
        fill
      );

      image.width(fitRect.width);
      image.height(fitRect.height);
      image.css({"margin-left": fitRect.x, "margin-top": fitRect.y});
      image.show();        
    },

    getFitRect = function(source, target, fill) {
      var sourceRatio = source.width / source.height,
      targetRatio = target.width / target.height,
      fitRect = {};

      if (sourceRatio > targetRatio) {
        if (fill) {
          fitRect.height = target.height;
          fitRect.width = fitRect.height * sourceRatio;
        } else {
          fitRect.width = target.width;
          fitRect.height = fitRect.width / sourceRatio;
        }
      } else if (targetRatio > sourceRatio) {
        if (fill) {
          fitRect.width = target.width;
          fitRect.height = fitRect.width / sourceRatio;
        } else {
          fitRect.height = target.height;
          fitRect.width = fitRect.height * sourceRatio;
        }
      } else {
        fitRect.width = target.width;
        fitRect.height = target.height;
      }

      fitRect.x = target.x + target.width  * 0.5 - fitRect.width  * 0.5;
      fitRect.y = target.y + target.height * 0.5 - fitRect.height * 0.5;

      return fitRect;
    },

    load = function(src) {
      el.hide();
      el.attr("src", src);
    };

    return {
      init: init,
      load: load
    }

});
(function() {
  this.App.initJQueryUI = function() {
    $('.buttonset').buttonset();
    return $('.datepicker').datepicker();
  };
}).call(this);
(function() {
  this.App.LandingPage = {};
  this.App.LandingPage.init = function(coupon, couponFull) {
    var $clearCoupon, $couponContainer, $couponInputWrapper, $couponRegButtons, $currentCouponLink, $defaultContainer, $defaultRegButtons, $openCoupon, couponFormOpen, couponFormSubmit, errorHandler, loginButton, loginPopup, submitPending, timer;
    coupon = coupon;
    couponFull = couponFull;
    loginPopup = $('#home-header-login-popup');
    loginButton = $('[data-action=open-login-popup]');
    loginPopup.bind('click', function(e) {
      return e.stopPropagation();
    });
    loginButton.bind('click', function(e) {
      e.preventDefault();
      e.stopPropagation();
      $('#login-password-forgotten').hide();
      $('#login-sign-in').show();
      $('html').bind('click', function(e) {
        $('html').unbind('click', arguments.callee);
        loginButton.css('opacity', 1);
        return loginPopup.css('display', 'none');
      });
      loginButton.css('opacity', 0);
      return loginPopup.css('display', 'block');
    });
    if ($.cookie('login')) {
      $('#open-login-popup').trigger('click');
    }
    $couponInputWrapper = $('#home-header-reg-coupon').find('.coupon-input-wrapper');
    $couponContainer = $('#reg-header-coupon');
    $defaultContainer = $('.reg-header');
    couponFormOpen = false;
    $openCoupon = $('[data-action=open-coupon-form]');
    $clearCoupon = $('[data-action=clear-coupon]');
    $currentCouponLink = coupon ? $clearCoupon : $openCoupon;
    $couponRegButtons = $('.coupon-reg-button');
    $defaultRegButtons = $('.default-reg-button');
    submitPending = false;
    errorHandler = function(e, xhr, status) {
      var response;
      submitPending = false;
      $currentCouponLink = $openCoupon;
      $couponContainer.hide();
      $defaultContainer.show();
      $couponRegButtons.hide();
      $defaultRegButtons.show();
      if (!couponFormOpen) {
        $clearCoupon.hide();
        $openCoupon.show();
      }
      $currentCouponLink = $openCoupon;
      $couponInputWrapper.removeClass('valid');
      response = JSON.parse(xhr.responseText);
      if (response.coupon.length >= 10) {
        return $couponInputWrapper.addClass('invalid');
      } else {
        return $couponInputWrapper.remove('invalid');
      }
    };
    $('.simple_form.coupon').live('ajax:success', function(e, data, status, xhr) {
      var hint, tempCoupon, term, type;
      submitPending = false;
      if (data && data.coupon) {
        tempCoupon = data.coupon;
        term = ["" + tempCoupon.term_name + " Premium-Mitgliedschaft"];
        hint = [];
        if (tempCoupon._type) {
          type = tempCoupon._type;
          coupon = tempCoupon.code;
          couponFull = false;
          if (type === 'Coupon::FullTest') {
            hint.push('Kostenlos, läuft automatisch aus');
            couponFull = true;
          }
          if (type === 'Coupon::Discount') {
            hint.push(" für nur " + tempCoupon.format_discount_price + " statt <strike>" + tempCoupon.format_old_price + "</strike>");
            if (tempCoupon.payment_type_info) {
              hint.push(" bei Zahlung mit " + tempCoupon.payment_type_info);
            }
          }
        }
        $couponContainer.find('.term-name').html(term.join(''));
        $couponContainer.find('.term-membership').html(hint.join(''));
        if (!couponFormOpen) {
          $openCoupon.hide();
          $clearCoupon.show();
        }
        $currentCouponLink = $clearCoupon;
        $defaultRegButtons.hide();
        $couponRegButtons.show();
        $defaultContainer.hide();
        $couponContainer.show();
      } else {
        errorHandler(e, xhr, status);
        return;
      }
      $couponInputWrapper.removeClass('invalid');
      return $couponInputWrapper.addClass('valid');
    });
    $('.simple_form.coupon').live('ajax:error', function(e, xhr, status, error) {
      return errorHandler(e, xhr, status);
    });
    couponFormSubmit = function() {
      if (!submitPending) {
        submitPending = true;
        return $('.simple_form.coupon').submit();
      }
    };
    timer = null;
    $('#coupon_temp_code').live('keyup', function(e) {
      var submitFunc;
      window.clearTimeout(timer);
      submitFunc = function() {
        return couponFormSubmit();
      };
      return timer = window.setTimeout(submitFunc, 250);
    });
    $("#coupon_temp_code").keypress(function(e) {
      if (e.which === 13 && ($('.coupon-input-wrapper').hasClass('valid') || $('.coupon-input-wrapper').hasClass('invalid'))) {
        return $('[data-action=close-coupon-form]').click();
      }
    });
    $('#coupon_temp_code').live('blur', function(e) {
      return couponFormSubmit();
    });
    $('[data-action=clear-coupon]').click(function(e) {
      e.preventDefault();
      $('#coupon_temp_code').val('');
      return $('.simple_form.coupon').submit();
    });
    $('[data-action=open-coupon-form]').click(function(e) {
      var $couponForm;
      e.preventDefault();
      couponFormOpen = true;
      $couponForm = $('#home-header-reg-coupon .coupon-form');
      $clearCoupon.hide();
      $openCoupon.hide();
      return $couponForm.show();
    });
    return $('[data-action=close-coupon-form]').click(function(e) {
      var $couponForm;
      e.preventDefault();
      couponFormOpen = false;
      $couponForm = $('#home-header-reg-coupon .coupon-form');
      $couponForm.hide();
      return $currentCouponLink.show();
    });
  };
}).call(this);
(function() {
  this.App.initLogin = function() {
    var $checkbox, $error, $form, $userLogin;
    $form = $('#signin-form');
    $userLogin = $form.find('[name="user[login]"]');
    $error = $form.find('.login-error');
    $checkbox = $form.find('[name="user[user_settings][privacy_settings_attributes][remember_me]"]:checkbox');
    $checkbox.attr('checked', 'checked');
    $userLogin.val($.cookie('login'));
    return $form.submit(function(e) {
      e.preventDefault();
      if ($checkbox.length > 0) {
        if ($checkbox[0].checked) {
          $.cookie('login', $userLogin.val(), {
            expires: 365,
            path: '/'
          });
        } else {
          $.cookie('login', null);
        }
      }
      return $form.ajaxSubmit({
        success: function(data) {
          $error.hide();
          if (data && data.url) {
            return window.location.href = data.url;
          } else {
            return location.reload();
          }
        },
        error: function() {
          return $error.show();
        },
        dataType: 'json'
      });
    });
  };
}).call(this);
(function() {
  this.App.messages = {};
  this.App.messages.afterCreate = function($tab, $el) {
    var $picShareCont, pageUp, pageUpParent, pageUpParentChildren, tempLink;
    this.removeError($tab);
    if ($el.find('.message-photo-sharing').length !== 0) {
      $tab.find('.picture-sharing-content .gallery-thumb.current').each(function(idx, el) {
        var dataId;
        $el = $(el);
        dataId = $el.attr('data-id');
        return $('[data-id=' + dataId + ']').remove();
      });
      $picShareCont = $tab.find('.picture-sharing-container');
      if ($tab.find('.picture-sharing-content .gallery-thumb').length === 0) {
        $picShareCont.find('a.picture-sharing-option').addClass('disabled-picture-sharing-option');
        $picShareCont.find('span.picture-sharing-option').removeClass('disabled-picture-sharing-option');
      } else {
        $picShareCont.find('a.picture-sharing-option').removeClass('disabled-picture-sharing-option');
        $picShareCont.find('span.picture-sharing-option').addClass('disabled-picture-sharing-option');
      }
    }
    tempLink = $('<a href="#body_content" style="display: none;" data-id-scroll><a>');
    $('body').append(tempLink);
    tempLink.click();
    tempLink.remove();
    pageUp = $('.button.page-up');
    pageUpParent = pageUp.parent();
    pageUpParentChildren = pageUpParent.children();
    if (pageUpParentChildren.length === 1) {
      return pageUpParent.remove();
    } else {
      return pageUp.remove();
    }
  };
  this.App.messages.afterError = function($tab, text) {
    return this.setError($tab, text);
  };
  this.App.messages.setError = function($tab, text) {
    var errorField;
    errorField = $tab.find('.actions .notice, .actions .error');
    errorField.removeClass('notice');
    errorField.addClass('error');
    return errorField.text(text);
  };
  this.App.messages.removeError = function($tab) {
    var errorField;
    errorField = $tab.find('.actions .notice, .actions .error');
    errorField.removeClass('error');
    errorField.addClass('notice');
    return errorField.html('&nbsp;');
  };
}).call(this);
(function() {
  this.App.initOverlays = function() {
    var closeControls, openControls;
    openControls = function(e, self) {
      var selector;
      e.preventDefault();
      selector = $(self).attr('href');
      return $(selector).css('display', 'block');
    };
    closeControls = function(e, self) {
      var selector;
      e.preventDefault();
      selector = $(self).attr('href');
      return $(selector).css('display', '');
    };
    $('a[data-action=open-controls]').live('click', function(e) {
      return openControls(e, this);
    });
    $('[data-action=close-controls]').live('click', function(e) {
      return closeControls(e, this);
    });
    $('[data-action=close-help-controls]').live('click', function(e) {
      closeControls(e, this);
      return $('.help-overlay').find('iframe').remove();
    });
    $('[data-action=open-usp-controls]').live('click', function(e) {
      var selector;
      selector = $(this).attr('href');
      $(selector).find('iframe').attr('src', $(this).attr('data-iframe-src'));
      return openControls(e, this);
    });
    return $('[data-action=close-usp-controls]').live('click', function(e) {
      var selector;
      selector = $(this).attr('href');
      $(selector).find('iframe').attr('src', '');
      return closeControls(e, this);
    });
  };
}).call(this);
(function() {
  this.App.Pagination = {};
  this.App.initPagination = function() {
    return $('body:not(.admin) .pagination').pagination();
  };
  this.App.Pagination.initAjaxPagination = function(page, url, numPages, $paginationEl) {
    var ajaxPaginate, hasLoadedPage, offset, paginationObject, turnThePage;
    $(".pagination-container").height(366);
    hasLoadedPage = {};
    $(".pagination-arrow").each(function() {
      var self;
      self = $(this);
      self.data("onclick", this.onclick);
      return this.onclick = function(e) {
        if (self.hasClass("loading")) {
          e.stopImmediatePropagation();
          return e.preventDefault();
        }
      };
    });
    turnThePage = function(pagination, offset, direction) {
      var identifier, queryString;
      if (!$paginationEl) {
        queryString = location.search;
        if (queryString.length === 0) {
          queryString = "?page=" + offset;
        } else {
          queryString = (queryString.search(/page=\d+/) === -1 ? queryString + "&page=" + offset : queryString.replace(/page=\d+/, "page=" + offset));
        }
        if (typeof window.history.pushState === "function") {
          window.history.replaceState(null, null, queryString);
        }
      }
      if (direction === "next") {
        pagination.next();
      } else {
        pagination.previous();
      }
      identifier = $paginationEl.attr('data-pageable');
      return $(".pagination-numbers[data-pagination-numbers=" + identifier + "] .current").html(offset);
    };
    ajaxPaginate = function(pagination, offset, direction) {
      var currentTrigger;
      if (hasLoadedPage[offset]) {
        return turnThePage(pagination, offset, direction);
      } else {
        currentTrigger = (direction === "next" ? pagination.nextTrigger : pagination.previousTrigger);
        $(".spinner", currentTrigger).show();
        currentTrigger.addClass("loading");
        return $.ajax({
          url: url,
          data: {
            page: offset
          },
          dataType: "html",
          success: function(data) {
            var $data;
            $data = $(data);
            $("img", $data).each(function() {
              $(this).data("src", $(this).attr("src"));
              return $(this).removeAttr("src");
            });
            hasLoadedPage[offset] = true;
            if ($paginationEl) {
              $paginationEl.find(".page-" + offset).replaceWith($data);
            } else {
              $(".page-" + offset).replaceWith($data);
            }
            turnThePage(pagination, offset, direction);
            $(pagination.element).queue(function() {
              $("img", $data).each(function() {
                return $(this).attr("src", $(this).data("src"));
              });
              return $(this).dequeue();
            });
            $(".spinner-small", currentTrigger).hide();
            return currentTrigger.removeClass("loading");
          }
        });
      }
    };
    offset = page;
    $.ajax({
      url: url,
      data: {
        page: offset
      },
      dataType: "html",
      success: function(data) {
        if ($paginationEl) {
          $paginationEl.find(".page-" + offset).replaceWith($(data));
        } else {
          $(".page-" + offset).replaceWith($(data));
        }
        return hasLoadedPage[offset] = true;
      }
    });
    paginationObject = {
      offset: page,
      onNext: function(pagination) {
        return ajaxPaginate(pagination, pagination.offset + 1, 'next');
      },
      onPrevious: function(pagination) {
        return ajaxPaginate(pagination, pagination.offset - 1, 'previous');
      },
      maxOffset: function() {
        return numPages;
      }
    };
    if ($paginationEl) {
      return $paginationEl.pagination(paginationObject);
    } else {
      return $('.sites-pagination').pagination(paginationObject);
    }
  };
}).call(this);
(function() {
  this.App.Payment = {};
  this.App.Payment.initPaymentModeSwitch = function() {
    var closeFields, showField;
    closeFields = function() {
      return $('#credit_card_fields, #direct_debit_fields, #paypal_fields').hide();
    };
    showField = function(paymentType) {
      closeFields();
      $('#' + paymentType + '_fields').show();
      if (paymentType === 'paypal') {
        return $('#payment-change-submit').hide();
      } else {
        return $('#payment-change-submit').show();
      }
    };
    showField($('#payment_form input[name=payment_type][checked=checked]').data('type'));
    return $('#payment_form input[name=payment_type]').click(function() {
      return showField($(this).data('type'));
    });
  };
  this.App.Payment.initPaymentChangePage = function() {
    return App.Payment.initPaymentModeSwitch();
  };
}).call(this);
App.Popups = {}

App.Popups.shared = (function(app, $) {

  var spinner = null,

  addAjaxHandlers = function(el) {
    el
      .live("ajax:beforeSend", onAjaxBeforeSend)
      .live("ajax:complete", onAjaxComplete);
  },

  onAjaxBeforeSend = function(ev) {
    spinner = app.spinner().init({
      el: $(ev.currentTarget),
      text: 'Diese Aktion kann länger dauern...'
    });
  },

  onAjaxComplete = function(ev) {
    spinner.remove();
  }

  return {
    addAjaxHandlers: addAjaxHandlers
  }

}(App, jQuery));

App.Popups.game = (function(app, $) {
  
  var self = null, 
  options = null,
  
  init = function(opts) {
    self = App.Popups.game;
    options = opts;
    
    friendSelector = app.facebook.friendSelector;
    friendSelector.init({
      friends: opts.friends, 
      disabledFriends: opts.invitations,
      counter: opts.counter,
      multipleSelect: true
    });
    
    inviteButton = $("#fb-invite");
    inviteButton.click(onInviteButtonClick);

    $(friendSelector).bind("selectionChanged", onFriendSelectionChanged);
   
    app.Popups.shared.addAjaxHandlers($(opts.container));
    
    setSelectedFriends([]);
  },
  
  onInviteButtonClick = function(ev) {
    if (inviteButton.hasClass("disabled")) {
      ev.preventDefault();
    }
  },

  onFriendSelectionChanged = function(ev, data) {
    setSelectedFriends(data.selectedFriends);
  },

  setSelectedFriends = function(selectedFriends) {
    setForm(selectedFriends);
    setFriendCount(selectedFriends.length);
  },
  
  setForm = function(selectedFriends) {
    $("#fb_user_ids").val(selectedFriends.join(","));
    if (selectedFriends.length > 0) {      
      inviteButton.removeClass("disabled");
    } else {
      inviteButton.addClass("disabled");
    }
  },
  
  setFriendCount = function(x) {
    if ($(".goal-area").length > 0) {
      var goals = options.goals;
      var max = goals[goals.length - 1].coins[0];

      var y = x + options.counter;

      if(y >= max) {
        $('.goal-bar-container h6').html('Maximum ausgewählt');
      } else {
        $('.goal-bar-container h6').html('<span>'+ x +'</span> ausgewählt');
        //$(".goal-bar-container h6 span").text(x);
      }

      var previous_min = 0;
      $.each(goals, function(idx, goal){
        var coins = goal.coins
        fillBar(idx + 1, y - previous_min, coins[0] - previous_min);
        fillIcon(idx + 1, y, coins[0], coins[1]);
        previous_min = coins[0];
      });
    }  
  },

  fillBar = function(idx, x, n){
    $element = $('#goal-bar-item-' + idx);

    if (x <= 0) {
      $element.find("i").width(0);
      $element.find("em").remove();
      return false;
    }
    var barWidth = $element.width();
    if (x >= n) {
      x = n;
      $element.find("i").addClass("full");
      $element.find("em").remove();
    } else {
      $element.find("i.full").removeClass("full")
      if ($element.find("em").length < 1) {
        $element.append("<em>noch " + (n - x).toString() + "</em>");
      } else {
        $element.find("em").html("noch " + (n - x).toString());
      }
    }
    $element.find("i").width(x / n * barWidth);
  },

  fillIcon = function(idx, x, min, max) {
    $element = $('#goal-icon-wrapper-' + idx);

    if (x >= min && (!max || x < max)) {
      $element.addClass("enabled");
      $element.find('.goal-symbol-disabled').hide();
      $element.find('.goal-symbol-enabled').show();
    } else {
      $element.removeClass("enabled");
      $element.find('.goal-symbol-enabled').hide();
      $element.find('.goal-symbol-disabled').show();
    }
  };

  return {
    init: init
  }
}(App, jQuery));

App.invitations = (function(app, $) {

  var options = null,
  dialogNode = null,
  friendSelector = null,
  recipientItem = null,

  init = function(initOptions) {
    var firstRecipientItem;
    options = initOptions;

    friendSelector = app.facebook.friendSelector;
    friendSelector.init({
      friends: options.friends, 
      disabledFriends: options.invitations,
      counter: options.counter,
      multipleSelect: false});

    app.tabs($(".special-tabs"));
    app.Popups.shared.addAjaxHandlers($("#invite-popup"));

    // $("#send-invitation-next").click(showSendDialog);
    $("#send-invitation-next").click(function(event) {
      $.post('/confirmation_accesses', { value: "fb-" + friendSelector.getSelectedFriends()[0] }, function(data) {
        showSendDialog(data.code);
      });
    });
    $(".add-recipient-button").click(onAddMailRecipient);

    firstRecipientItem = $(".recipient-item").first();
    setRecipientItemAttributes(firstRecipientItem, 0);
    recipientItem = firstRecipientItem.clone();
  },

  showSendDialog = function(code) {
    $.fancybox.close();

    var link = options.facebookLink.replace('CODE_REPLACE', code);
    FB.ui({
      method: "send", 
      to: friendSelector.getSelectedFriends()[0],
      display: "dialog",
      name: "Bitte verifiziere mich bei MeAndYou",
      link: link,
      description: "Wir bringen das Ich zum Du",
      picture: options.pictureUrl
    },
    onSendDialogResponse);
  },

  onSendDialogResponse = function(response) {
    if (response) {
      //console.log(response);
    } else {
      $("#invitations-popup").trigger("click");
    }
  },

  onAddMailRecipient = function(ev) {
    ev.preventDefault();
    var numRecipients = $(".recipient-item").size(),
    newRecipient = recipientItem.clone();
    if (numRecipients == 100) {
      return;
    }
    $(".recipient-items").prepend(newRecipient);
    setRecipientItemAttributes(newRecipient, numRecipients);
  },

  setRecipientItemAttributes = function(item, index) {
    var nameLabel = item.find(".name-label"),
    nameInput = item.find(".name-input"),
    mailLabel = item.find(".mail-label"),
    mailInput = item.find(".mail-input"),
    fieldName = "recipients";

    nameLabel.attr("for", fieldName + "_[" + index + "][name]");
    nameInput.attr({
      "id":   fieldName + "_[" + index + "][name]",
      "name": fieldName + "[[" + index + "][name]]"
    });
    
    mailLabel.attr("for", fieldName +"_[" + index + "][email]");
    mailInput.attr({
      "id":   fieldName +"_[" + index + "][email]",
      "name": fieldName + "[[" + index + "][email]]"
    });
  };

  return {
    init: init,
    showSendDialog: showSendDialog
  }
  
}(App, jQuery));
(function() {
  this.App.initPopups = function() {
    $('.open-popup-edit-profile').fancybox({
      padding: '5',
      onComplete: function(event, ui) {
        return App.Profile.initEditProfileAnimationTabs();
      }
    });
    $('.open-popup').fancybox({
      padding: '5',
      onStart: function(e) {
        return $(e).trigger('fancybox-start');
      },
      onCancel: function(e) {
        return $(e).trigger('fancybox-cancel');
      },
      onComplete: function(e) {
        return $(e).trigger('fancybox-complete');
      },
      onCleanup: function(e) {
        return $(e).trigger('fancybox-cleanup');
      },
      onClosed: function(e) {
        return $(e).trigger('fancybox-closed');
      }
    });
    $('.close-popup').live('click', function(e) {
      e.preventDefault();
      return $.fancybox.close();
    });
    $('[data-action=open-flower-popup]').live('click', function(e) {
      var $el, branch, branchEl, href, selector, stalk, stalkEl, target;
      e.preventDefault();
      $el = $(e.currentTarget);
      selector = $el.attr('data-target');
      stalk = false;
      branch = false;
      stalkEl = $(selector).find('.flowerStalk.isHighlighted');
      branchEl = $(selector).find('.flowerBranch.isHighlighted');
      if (stalkEl.length > 0) {
        stalk = true;
      }
      if (branchEl.length > 0) {
        branch = branchEl.attr('data-id');
      }
      href = "" + ($el.attr('href')) + "?branch=" + branch + "&stalk=" + stalk;
      target = $("<a href='" + href + "'></a>");
      $('body').append(target);
      target.fancybox({
        padding: 5
      });
      target.trigger('click');
      return target.remove();
    });
    $('[data-action=open-chat]').live('click', function(e) {
      var roster, user;
      e.preventDefault();
      if (!(window.chatWindow != null) || window.chatWindow.closed) {
        window.chatWindow = window.open(e.currentTarget.href, 'MeAndYouChat', 'dependent=yes,width=895,height=550,resizable=no');
      } else {
        roster = window.chatWindow.MeAndYou.chatRouter.roster;
        user = roster.get($(this).data('user_id'));
        if (user) {
          roster.setActiveUser(user);
        }
      }
      return window.chatWindow.focus();
    });
    return $('[data-action=open-videochat]').live('click', function(e) {
      e.preventDefault();
      if (!(window.videoChatWindow != null) || window.videoChatWindow.closed) {
        window.videoChatWindow = window.open(this.href, 'MeAndYouVideochat', 'width=620,height=410,resizable=no');
      }
      return window.videoChatWindow.focus();
    });
  };
}).call(this);
App.Profile = {
  initProfileDescriptionLink: function() {
    $('a#user-short-description-link').bind('click', function(e) {
      e.preventDefault();
      $('#user-profile-data.pagination').data('pagination').paginate(6).show();
    });
  },

  initEditProfileElements: function() {
    $('select[multiple]').vzselect({
      maxElementsSelected: null,
      maxHeight: 100,
      addButtonText: 'und',
      addButtonTextNullSelect: 'Bitte wählen',
      buttonType: 'span'
    });
  },

  initEditProfileAnimationTabs: function() {
    $('.animationTabSwich').animationTab({
      tabBorder:$(".animationTabs .animationTabSwich .tabs .tabBorder"),
      animateTime: 0
    });
  }
};
(function() {
  this.App.ProfileEdit = {
    initialProfileData: {}
  };
  this.App.initProfileEdit = function(extendedAggregation) {
    var $spinnerOverlay, changeFunction1, changeFunction2, change_truth, slider1, slider2;
    $spinnerOverlay = null;
    $('.simple_form.profile').bind('ajax:before', function(e) {
      log('before', arguments);
      return $spinnerOverlay = App.spinner().init({
        el: $('#edit-profile-dialog'),
        text: 'Daten werden aktualisiert...<span id="upload-progress"></span><button class="button cancel-profile-update tooltip_2" title="Aktuellen Vorgang abbrechen">Abbrechen</button>'
      });
    });
    $('.simple_form.profile').bind('ajax:complete', function(e, jqXHR, textStatus) {
      log('complete', arguments);
      if ($spinnerOverlay) {
        $spinnerOverlay.remove();
      }
      return $.fancybox.close();
    });
    $('button.cancel-profile-update').live('click', function(event) {
      if ($jqXHR) {
        return $jqXHR.abort();
      }
    });
    $('#edit-profile-container form.profile :input').each(function() {
      var input;
      input = $(this);
      return App.ProfileEdit.initialProfileData[input.attr('data-field-name')] = input.val();
    });
    slider1 = $($('#edit-profile-container form.profile .slider')[0]);
    changeFunction1 = function(e, ui) {
      return change_truth(slider1);
    };
    slider1.selectToUISlider({
      labels: 0,
      sliderOptions: {
        range: false,
        change: changeFunction1
      }
    });
    $(slider1).next('.ui-slider').attr('id', "" + ($(slider1).attr('data-field-name')) + "-slider").addClass('edit-profile-slider');
    slider2 = $($('#edit-profile-container form.profile .slider')[1]);
    changeFunction2 = function(e, ui) {
      return change_truth(slider2);
    };
    slider2.selectToUISlider({
      labels: 0,
      sliderOptions: {
        range: false,
        change: changeFunction2
      }
    });
    $(slider2).next('.ui-slider').attr('id', "" + ($(slider2).attr('data-field-name')) + "-slider").addClass('edit-profile-slider');
    $('#edit-profile-container form.profile select:not(.multiple-select)').bind('change', function(e) {
      return change_truth($(e.currentTarget));
    });
    $('#edit-profile-container #profile_birthday_2i').unbind('change');
    $('#edit-profile-container #profile_birthday_3i').unbind('change');
    $('#edit-profile-container form.profile select.multiple-select').bind('change', function(e) {
      var $el, $tr, current, initialWert;
      $el = $(e.currentTarget);
      $tr = $el.closest('tr');
      initialWert = App.ProfileEdit.initialProfileData[$el.attr('data-field-name')];
      current = $el.val();
      if ((_.difference(initialWert, current).length === 0) && (_.difference(current, initialWert).length === 0)) {
        return $tr.find('.rating-available').show();
      } else {
        $tr.find('.rating-available').hide();
        return $tr.find('.rating-not-available').show();
      }
    });
    return change_truth = function(ct) {
      var $ct, $tr, confirmationResult, confirmationResultIcon, confirmationValues1, confirmationValues2, fieldName, negativeRating, showChanges, value, values;
      showChanges = function(values, value) {
        if (values[value][true] > values[value][false]) {
          confirmationResult.addClass('confirmation-profile-true-medium-bg');
          confirmationResultIcon.addClass('confirmation-profile-true-medium');
        } else if (values[value][true] < values[value][false]) {
          confirmationResult.addClass('confirmation-profile-false-medium-bg');
          confirmationResultIcon.addClass('confirmation-profile-false-medium');
        } else {
          confirmationResult.addClass('confirmation-profile-average-medium-bg');
          confirmationResultIcon.addClass('confirmation-profile-average-medium');
        }
        confirmationValues1.find('span').html(values[value][true]);
        return confirmationValues2.find('span').html(values[value][false]);
      };
      $ct = $(ct);
      $tr = $ct.closest('tr');
      fieldName = $tr.attr('data-field-name');
      value = $ct.val();
      confirmationResult = $tr.find('.confirmation-result');
      confirmationResult.removeClass('confirmation-profile-true-medium-bg confirmation-profile-false-medium-bg confirmation-profile-average-medium-bg');
      confirmationResultIcon = $tr.find('.confirmation-result-icon');
      confirmationResultIcon.removeClass('confirmation-profile-true-medium confirmation-profile-false-medium confirmation-profile-average-medium');
      confirmationValues1 = $tr.find('.confirmation-values:first');
      confirmationValues2 = $tr.find('.confirmation-values:last');
      if (extendedAggregation && extendedAggregation[fieldName] && fieldName !== 'height' && fieldName !== 'birthday' && fieldName !== 'number_of_children') {
        values = extendedAggregation[fieldName];
        if (values[value]) {
          if (values[value][true] !== 0 || values[value][false] !== 0) {
            return showChanges(values, value);
          }
        }
      } else if (fieldName === 'birthday' || fieldName === 'height' || fieldName === 'number_of_children') {
        negativeRating = 0;
        if (fieldName === 'number_of_children' || fieldName === 'height') {
          $tr.find('.rating-available').show();
          $tr.find('.rating-not-available').hide();
        }
        if (fieldName === 'birthday') {
          values = extendedAggregation['year_of_birth'];
        } else {
          values = extendedAggregation[fieldName];
        }
        if (values[value] && (values[value][true] !== 0 || values[value][false] !== 0)) {
          if (values[value][true] !== 0) {
            if (values[value][true] > values[value][false]) {
              return showChanges(values, value);
            }
          } else if (values[value][false] !== 0 && values[value][true] === 0) {
            negativeRating = 0;
            negativeRating += values[value][false];
            _.each(values, function(v, k, hash) {
              if (value !== k) {
                return negativeRating += values[k][true];
              }
            });
            confirmationResult.addClass('confirmation-profile-false-medium-bg');
            confirmationResultIcon.addClass('confirmation-profile-false-medium');
            confirmationValues1.find('span').html(values[value][true]);
            return confirmationValues2.find('span').html(negativeRating);
          }
        } else if (values[value] && fieldName === 'number_of_children' && values[value][false] === 0 && values[value][true] === 0) {
          $tr.find('.rating-available').hide();
          return $tr.find('.rating-not-available').show();
        } else if (fieldName === 'number_of_children' && !values[value]) {
          $tr.find('.rating-available').hide();
          return $tr.find('.rating-not-available').show();
        } else {
          negativeRating = 0;
          confirmationResult.addClass('confirmation-profile-false-medium-bg');
          confirmationResultIcon.addClass('confirmation-profile-false-medium');
          confirmationValues1.find('span').html("0");
          _.each(values, function(v, k, hash) {
            if (value !== k) {
              return negativeRating += values[k][true];
            }
          });
          if (values[value]) {
            return confirmationValues2.find('span').html(negativeRating + values[value][false]);
          } else {
            return confirmationValues2.find('span').html(negativeRating);
          }
        }
      }
    };
  };
}).call(this);
(function() {
  this.App.initPromotionContainer = function(){
    $('.panel').hover(function(){
        $(this).addClass('flip');
    }, function(){
        $(this).removeClass('flip');
    });
  }
}).call(this);
(function() {
  this.App.ResuggestDateRequestWidget = {};
  this.App.ResuggestDateRequestWidget.init = function(defaultDate, calendarOptions) {
    var $dateField, $dpWidget, $selectedDate, $selectedTime, $timeField, addDatePickerEvent;
    $dpWidget = $('.resuggest-datepicker-widget');
    $dateField = $('#resuggest_meeting_time_date');
    $timeField = $('#resuggest_meeting_time_time');
    $selectedDate = $('#resuggest-datepicker-widget-selected-date');
    $selectedTime = $('#resuggest-datepicker-widget-time-select');
    $('[data-action-reset-form]').click(function(e) {
      var $el;
      e.preventDefault();
      $el = $(e.currentTarget);
      $el.closest('form')[0].reset();
      return $('.date_request-selection.pagination').data('pagination').paginate(1);
    });
    $dateField.live('focus', function(e) {
      var date;
      e.preventDefault();
      addDatePickerEvent();
      date = $(this).val();
      return App.DateRequestWidget.fetchDates(date, false, App.ResuggestDateRequestWidget.insertDates);
    });
    $timeField.live('focus', function(e) {
      var date;
      e.preventDefault();
      addDatePickerEvent();
      date = $dateField.val();
      return App.DateRequestWidget.fetchDates(date, false, App.ResuggestDateRequestWidget.insertDates);
    });
    $('.resuggest-datepicker-widget-done-button').live('click', function() {
      $('#resuggest-date_request-form #date_request_meeting_time').val($selectedDate.html() + ' ' + $selectedTime.val());
      $dateField.val($selectedDate.html());
      $timeField.val($selectedTime.val());
      $dateField.removeAttr('disabled');
      $timeField.removeAttr('disabled');
      $dpWidget.hide();
      return false;
    });
    $('.resuggest-datepicker-widget-cancel-button').live('click', function() {
      $('.resuggest-datepicker-widget').hide();
      $dateField.removeAttr('disabled');
      $timeField.removeAttr('disabled');
      return false;
    });
    return addDatePickerEvent = function() {
      var height, pos, width;
      $dateField.attr('disabled', true);
      $timeField.attr('disabled', true);
      $("#fancybox-content, #fancybox-content > div").css("overflow", "visible");
      pos = $dateField.position();
      width = $dateField.width();
      height = $dateField.height();
      return $dpWidget.css({
        "left": pos.left + "px",
        "top": (pos.top + height + 8) + "px"
      }).show();
    };
  };
  this.App.ResuggestDateRequestWidget.insertDates = function(data) {
    return $('.resuggest-datepicker-widget .dates ul').html(data.responseText);
  };
}).call(this);
App.Search = {
  init: function(options){    
    App.Search.settings = $.extend({ 
      maxSearchParams: 2, 
      searchParamsCounter: 0, 
      submitFormSelector: "#edit_search_profile", 
      form_prefix: "search_profile"
    },options||{});
    
    App.Search.initSliders();
    //App.Search.initMultiSelectButtons();
    App.Search.initAttributeDelete();
    App.Search.disableHiddenOptions();
    App.Search.setSearchParamsHint();
    
    $('[data-action=reset]').unbind('click');
    $('[data-action=reset]').bind('click', function(e) {
      e.preventDefault();
      App.Search.resetSearchParams(e);
    });
    App.Search.initSort();
    App.Search.submitFormSelector = $('#attribute-form form');
    App.Search.initCodeInjects();
    //App.Search.initSubmit();
  },
  initSort: function() {
    $("#sort_form select").change(function() {
      App.Search.updateHiddenSortField();
      $('#edit_search_profile').submit();
    });
  },
  initCodeInjects: function() {
    //$('.dynamic-container li.visible .exclamation_blink').hide();
    $('.dynamic-container li.hidden .form-element-wrapper label').after($('<div class="exclamation_blink"></div'));
    $('select').change(function(e) {
        $(this).unbind('change', arguments.callee);
        $(this).parent().find('.exclamation_blink').hide();
    });
  },
  resetSearchParams: function(e){
    $('#selectors input:checked').each(function(index) {
      $(this).next('a').trigger('click');
    });
    App.Search.submitForm();
    return true;
  },
  
  setSearchParamsHint: function(){
    if(App.Search.checkSearchParamsLimit()) {
      $("#max-search-params-hint").text('Fügen Sie Sucheigenschaften hinzu').removeClass('error');
      $('#selectors input').removeAttr('disabled');
    }
    else {
      $("#max-search-params-hint").text('Es dürfen maximal nur ' + App.Search.settings.maxSearchParams + ' Elemente selektiert werden').addClass('error');
      $('#selectors input:not(:checked)').attr('disabled', 'disabled');      
      $('#control1').hide();
    }
   return true;
  },
  
  checkSearchParamsLimit: function(){
    //if($('#selectors input:checked').size() < App.Search.settings.maxSearchParams) {
    if($('.dynamic-container li.visible').size() < App.Search.settings.maxSearchParams) {
      return true;
    }
    else {
      return false;
    }
  },

  deleteAttribute: function($li, selectorName) {
     $('#control1').show();
     var $select = $li.find('select, input');
     var $selector = $("#selectors li[data-name="+selectorName+"]");
     $select.children().remove();
     $selector.find('input:first').attr('checked', false);
     $li.addClass('hidden');
     $li.removeClass('visible');
     App.Search.settings.searchParamsCounter -= 1;
     if(App.Search.settings.searchParamsCounter <= 0){
       App.Search.settings.searchParamsCounter = 0;
     }
     // $select.attr('disabled','disabled');
     App.Search.setSearchParamsHint();
     App.Search.refreshBackground();
  },

  
  initAttributeDelete: function(){
     // Delete Button
     $('#attribute-form button[data-action=delete]').unbind('click');
     $('#attribute-form button[data-action=delete]').bind('click', function(e) {
       var $li = $(this).closest('li');
       var selectorName = $(this).attr('data-name');
       App.Search.deleteAttribute($li, selectorName);
     });
  },
  
  initSliders: function(){
    // Sliders
    // $(".age_range").selectToUISlider({labels: /*$("#"+App.Search.settings.form_prefix+"_age_min")[0].length/5*/ 0, sliderOptions: {range: true}});
    // $(".credibility_range").selectToUISlider({labels: /*$("#"+App.Search.settings.form_prefix+"_credibility_min")[0].length/5*/ 0, sliderOptions: {range: true}});
    // $(".number_of_children_range").selectToUISlider({labels: /*$("#"+App.Search.settings.form_prefix+"_number_of_children_min")[0].length*/ 0, sliderOptions: {range: true}});
    // $(".height_range").selectToUISlider({labels: /*$("#"+App.Search.settings.form_prefix+"_height_min")[0].length/10*/ 0, sliderOptions: {range: true}});
    $(".age_range").selectToUISlider({labels: 0, sliderOptions: {range: true}});
    //$(".credibility_range").selectToUISlider({labels: 0, sliderOptions: {range: true}});
    $(".number_of_children_range").selectToUISlider({labels: 0, sliderOptions: {range: true}});
    $(".height_range").selectToUISlider({labels: 0, sliderOptions: {range: true}});
    $('.ui-slider').each(function(idx, el) {
       var $el = $(el);
       var parent = $el.parent();
       $el.detach();
       var $div = $('<div class="ui-slider-container"></div>');
       $div.insertBefore(parent);
       $div.append($el);
     });
  },
  
  initMultiSelectButtons: function(){
    $('select[multiple]').vzselect({
      //maxElementsSelected: 3,
      maxHeight: 100,
      addButtonText: 'oder',
      addButtonTextNullSelect: 'Bitte auswählen',
      buttonType: 'span'
    });
  },
  
  refreshBackground: function() {
    $('.dynamic-container li.visible:even').css('background', App.colors.f10);
    $('.dynamic-container li.visible:odd').css('background', 'transparent');
  },
  
  disableHiddenOptions: function(){
    $('.dynamic-container li.hidden').find('input, select').attr('disabled', 'disabled');
  },
  
  initSubmit: function(){
    $('button[data-action=submit][type=submit]').unbind('click');
    $('button[data-action=submit][type=submit]').bind('click', function(e) {
      App.Search.submitForm();
      e.preventDefault();
	  return false;	
    });
  },
  
  submitForm: function(){
    //e.preventDefault();
    //var form = $(e.target).parents('form');
    
    var form = $(App.Search.settings.submitFormSelector);
    //form.submit(); //not needed if we use ajax call below
    
    form.ajaxSubmit({   	
	    //Doc: http://jquery.malsup.com/form/#options-object:
   	  url: form.attr('action')+'.js',  // override for form's 'action' attribute 
	    dataType: 'script',
      success: function(e) {
        //render den kram
        //alert('ok');
      },
      error: function(e) {
        // render error
        //alert("Error");
      },
	    beforeSerialize: function($form, options) { 
  	  	//Remove existing dropdown hidden input fields from previous submit:
  	  	$('.dropdown_hidden').remove(); 
		
  	  	//Set hidden input fields for current submit:
  	  	$('option[disabled]').each(function() {	
  	  		//$(this).attr('selected','selected');
  	  		var selected_value = $(this).val();
  	  		var search_name = $(this).closest('select').attr('name');
  	  		var closest_li = $(this).closest('select').closest('li');
  	  		closest_li.append('<input class="dropdown_hidden" type="hidden" name="search_profile['+search_name+'][]" value="'+selected_value+'">');	
  	  	});

        // Set hidden input field for sort
        App.Search.updateHiddenSortField();

        // var disabledSelects = form.find('*:disabled');
        // disabledSelects.each(function(index, el) {
        //   var $el = $(el);
        //   if($el.is('select')) {
        //     //console.log($el.attr('name'));
        //   }
        // });
      }
    });
    return false;
  },

  updateHiddenSortField: function() {
    $('#search_profile_sort').val($('#sort_form select').val());
  },

  searchOptionsControl: {

    init: function(){

      $('.inline-controls [data-action=open-controls]').unbind('click');
      $('.inline-controls [data-action=open-controls]').bind('click', function(e) {
        e.preventDefault();
        var selector = $(this).attr('href');
        $(selector).css('display', 'block');

        $('#selectors [data-action=close-controls]').unbind('click');
        $('#selectors [data-action=close-controls]').bind('click', function(e) {
          e.preventDefault();
          var selector = $(this).attr('href');
          $(selector).css('display', '');
          return false;
        });
        return false;
      });
      
      $('.dynamic-container li.visible').each(function(idx, el){
        $('#selectors li[data-name='+ $(el).attr('data-name') + '] input[type=checkbox]').attr('checked', true);
      });

      // Select with Link
      $('#selectors a').unbind('click');
      $('#selectors a').bind('click', function(e){
        e.preventDefault();
        App.Search.searchOptionsControl.attributeClick($(this))
      });
      $('#selectors input[type=checkbox]').unbind('click');
      $('#selectors input[type=checkbox]').bind('click', function(e){
        if($(this).attr('data-action') === 'close-controls'){
          return;
        }
        App.Search.searchOptionsControl.attributeClick($(this))
        return true;
      });
    },
    
    attributeClick: function($selected){
      var inputName 
      var $inputFlag
      var checked = false;
      
      if($selected.get(0).tagName.toLowerCase()=="a") {
        inputName = $selected.attr('href').replace("selector_", "");
        $inputFlag = $selected.parent().find('input');
        if($inputFlag.is(":checked")) {
          checked = true;
        }
      }
      else {
        inputName = $selected.next('a').attr('href').replace("selector_", "");
        $inputFlag = $selected
        if(!$inputFlag.is(":checked")) {
          checked = true;
        }
      }
      $input = $("#"+inputName);
      $li = $input.closest('li');
      $select = $li.find('select, input');

      if($inputFlag.is(":disabled")) {
        return;
      }
      
      var check = function(){
        $inputFlag.attr('checked', true);
        $li.removeClass('hidden');
        $li.addClass('visible');
        $select.removeAttr('disabled');
        App.Search.settings.searchParamsCounter += 1;
      };

      var uncheck = function(){
        $inputFlag.attr('checked', false);
        $li.addClass('hidden');
        $li.removeClass('visible');
        var selectorName = $(this).attr('data-name');
        App.Search.deleteAttribute($li, selectorName);
         
      };
      
      if(checked == true) {
          uncheck();
      } else {
        if(App.Search.checkSearchParamsLimit()){
          check();
        }
      }
      
      $('div#selectors').css('display', 'none');
      
      searchParams = $('.search-params');
      searchParams.scrollTop(searchParams[0].scrollHeight - searchParams.height())
      
      App.Search.setSearchParamsHint();
      App.Search.refreshBackground();
    }
  }
};
(function() {
  this.App.initAccountSettings = function() {
    var $rememberMe, cancel, closeHighlight;
    closeHighlight = function(e) {
      var $form, $highlight;
      if (e) {
        e.preventDefault();
      }
      $form = $('.settings-fields.highlight');
      $highlight = $('#highlight');
      $form.find('input, select').attr('disabled', true);
      $form.addClass('disabled');
      $form.removeClass('highlight');
      return $highlight.fadeOut(function() {
        return $highlight.remove();
      });
    };
    cancel = function(e) {
      var $form;
      $form = $('.settings-fields.highlight');
      closeHighlight(e);
      return $form.find('input, select').each(function() {
        var $input;
        $input = $(this);
        $input.removeClass('error');
        $input.next('.error-message').remove();
        return $input.val($input.data('old-value'));
      });
    };
    $('.settings-fields .cancel').click(cancel);
    $('.settings-fields .edit').click(function(e) {
      var $el, $form, $highlight;
      e.preventDefault();
      $el = $(this);
      $form = $el.parents('.settings-fields');
      $highlight = $('<div id="highlight" style="display: none"></div>');
      $form.addClass('highlight').removeClass('disabled').find('input, select').attr('disabled', false);
      $form.find('input, select').each(function() {
        var $input;
        $input = $(this);
        return $input.attr('data-old-value', $input.val());
      });
      $('body').append($highlight);
      $highlight.fadeIn();
      $highlight.click(cancel);
      return $form.find('input:first').focus();
    });
    $('.settings-fields .save').click(function(e) {
      var $el, $form;
      e.preventDefault();
      $el = $(this);
      $form = $el.parents('.settings-fields');
      if ($form.find('.error').length) {
        return;
      }
      return $.ajax({
        url: $form.attr('action'),
        data: $form.serialize(),
        type: $form.find('[name=_method]').val(),
        success: function(data) {
          App.currentUser = data.user;
          return closeHighlight(e);
        },
        error: function(xhr) {
          var data, text;
          data = JSON.parse(xhr.responseText);
          text = "" + data.error + "<br>";
          return $.each(data.errors, function(field, messages) {
            return text += ("<br><strong>" + (field.toUpperCase()) + ":</strong> ") + messages.join(', ');
          });
        }
      });
    });
    $('.get-adobe-flash').click(function(e) {
      e.preventDefault();
      return window.open(e.currentTarget.href);
    });
    $rememberMe = $('#privacy-settings #current_user_privacy_settings_attributes_remember_me');
    return $rememberMe.change(function(e) {
      if (this.checked) {
        return $.cookie('login', $('#current_user_name').val(), {
          expires: 365,
          path: '/'
        });
      } else {
        return $.cookie('login', null, {
          path: '/'
        });
      }
    });
  };
  this.App.initPrivacySettings = function() {
    var $container;
    $container = $('#privacy-settings');
    return $container.find('input, select').change(function(e) {
      var $el, $form;
      e.preventDefault();
      $el = $(this);
      $form = $el.parents('form');
      return $.ajax({
        url: $form.attr('action'),
        data: $form.serialize(),
        type: $form.find('[name=_method]').val(),
        success: function(data) {
          return App.currentUser = data.user;
        }
      });
    });
  };
  this.App.initSettings = function() {
    App.initAccountSettings();
    return App.initPrivacySettings();
  };
}).call(this);
App.spinner = (function() {

    var el,
    modalWrapper = null,
    spinner = null,

    init = function(options) {
      var elWidth, 
      elHeight;
      el = options.el;
      spinnerText = options.text;

      elWidth = el.outerWidth();
      elHeight = el.outerHeight();

      modalWrapper = $('<div class="spinner-modal-wrapper"></div>');
      spinner = $('<div class="spinner"></div>');
      spinnerText = $('<p class="spinner-text"></p>').html(spinnerText);
      modalWrapper.append(spinner);
      modalWrapper.append(spinnerText);

      modalWrapper.width(elWidth);
      modalWrapper.height(elHeight);
      
      el.append(modalWrapper);

      spinner.css({
        "left": Math.round(elWidth * 0.5 - spinner.width() * 0.5),
        "top": Math.round(elHeight * 0.5 - spinner.height() * 0.5)
      });
      spinnerText.css({
        "top": Math.round(elHeight * 0.5 + spinner.height() * 0.5)
      });

      return this;
    },

    remove = function() {
      // el.remove(modalWrapper);
      modalWrapper.remove();
    };

    return {
      init: init,
      remove: remove
    }
});
(function() {
  this.App.initTabs = function() {
    App.tabs('nav.tabs');
    return App.tabs('nav.special-tabs');
  };
  this.App.tabs = function(element) {
    var tabClicked, tabContentId, tabContents, tabContentsSelector, tabs;
    element = $(element).not('[data-tabs-disabled]');
    tabs = $(_.reject(_.map(element.find('a'), function(tab) {
      var id, link;
      id = $(tab).attr('href');
      link = $(tab).attr('data-tab-link');
      if ((id != null) && id.charAt(0) === '#' && id.length > 1 && !(link != null)) {
        return tab;
      } else {
        return null;
      }
    }), _.isNull));
    if (tabs.length > 0) {
      tabContentId = function(tab) {
        return $(tab).attr('href');
      };
      tabContentsSelector = _(tabs).map(tabContentId).join(',');
      tabContents = $(tabContentsSelector);
      tabs.click(function(e) {
        var tab;
        tab = $(this || e.currentTarget);
        if (tab.attr('data-tab-link')) {
          return;
        }
        e.preventDefault();
        tabContents.hide();
        $(tabContentId(tab)).show();
        tabs.removeClass('active');
        return tab.addClass('active');
      });
      tabClicked = false;
      tabs.each(function(idx, el) {
        var $el;
        $el = $(el);
        if ($el.hasClass('active')) {
          $el.click();
          tabClicked = true;
          return false;
        }
      });
      if (!tabClicked) {
        return tabs.first().click();
      }
    }
  };
  this.App.liveTabs = {};
  this.App.liveTabs.closeAll = function(element) {
    $(element).find('a').removeClass('active');
    return $(element).find('a').each(function() {
      var tabContentId;
      tabContentId = $(this).attr('href');
      if (tabContentId) {
        return $(tabContentId).hide();
      }
    });
  };
  this.App.liveTabs.init = function(element) {
    return $(element).find('a').live('click', function(event) {
      var tabContentId;
      App.liveTabs.closeAll(element);
      tabContentId = $(this).attr('href');
      if (tabContentId) {
        $(this).addClass('active');
        return $(tabContentId).show();
      }
    });
  };
}).call(this);
(function() {
  this.App.Text = {};
  this.App.Text.init = function() {};
}).call(this);
(function() {
  this.App.initTooltip = function() {
    var pagerTooltips, tooltipSrcElements;
    pagerTooltips = $('#profile-pager[data-pager=profiles] a');
    pagerTooltips.each(function(idx, el) {
      var title;
      title = '';
      switch (idx) {
        case 0:
          title = 'Charakterblume';
          break;
        case 1:
          title = 'Basiseigenschaften';
          break;
        case 2:
          title = 'Erscheinungsbild';
          break;
        case 3:
          title = 'Lebenssituation';
          break;
        case 4:
          title = 'Private Eigenschaften';
          break;
        case 5:
          title = 'Weitere Eigenschaften';
          break;
        case 6:
          title = 'Über mich';
      }
      $(el).attr('title', title);
      return $(el).addClass('tooltip_2');
    });
    tooltipSrcElements = $("[data-tooltip-parent]");
    tooltipSrcElements.each(function(idx, el) {
      var $el, $selector, offset, offsetStr, position, positionStr, relative, relativeStr, selector;
      $el = $(el);
      selector = $el.attr('data-tooltip-src');
      $selector = $(selector);
      positionStr = $el.attr('data-tooltip-position');
      position = ['top', 'center'];
      if ((positionStr != null) && positionStr.length > 0) {
        position = positionStr.split(',');
      }
      offsetStr = $el.attr('data-tooltip-offset');
      offset = [0, 0];
      if ((offsetStr != null) && offsetStr.length > 0) {
        offset = offsetStr.split(',');
        _(offset).each(function(val, idx, arr) {
          return arr[idx] = parseInt(val);
        });
      }
      relativeStr = $el.attr('data-tooltip-relative');
      relative = false;
      if ((relativeStr != null) && relativeStr === "true") {
        relative = true;
      }
      if ($.inArray('top', position) !== -1) {
        $selector.addClass('top');
        offset[0] += -16;
      } else if ($.inArray('bottom', position) !== -1) {
        $selector.addClass('bottom');
        offset[0] += 16;
      }
      return $el.tooltip({
        tip: selector,
        effect: 'slide',
        position: position,
        offset: offset,
        relative: relative
      });
    });
    if (!App.UserAgents.mobile) {
      $('.tooltip_2[title]').tooltip_2({
        track: true,
        delay: 0,
        showURL: false,
        fade: false
      });
    }
    return $(".tooltip-target").each(function(idx, el) {
      var $el, fieldName;
      $el = $(el);
      fieldName = $el.attr('data-field-name');
      return $el.ezpz_tooltip({
        contentId: "tooltip-content-" + fieldName
      });
    });
  };
}).call(this);
(function() {
  this.App.UserAgents = {
    mobile: false
  };
  this.App.initUserAgentSwitches = function() {
    var device;
    device = {
      detect: function(key) {
        if (this['_' + key] === void 0) {
          this['_' + key] = navigator.userAgent.match(new RegExp(key, 'i'));
        }
        return this['_' + key];
      },
      iDevice: function() {
        return this.detect('iPhone') || this.detect('iPod') || this.detect('iPad');
      },
      android: function() {
        return this.detect('Android');
      },
      webOS: function() {
        return this.detect('webOS');
      },
      mobile: function() {
        return this.iDevice() || this.android() || this.webOS();
      }
    };
    return App.UserAgents.mobile = device.mobile();
  };
}).call(this);
(function() {
  var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
  this.App.initUserNotifications = function() {
    var currentUserId, fayeClient;
    currentUserId = $('meta[name=current_user_id]').attr('content');
    if (currentUserId) {
      fayeClient = new Faye.Client(AppConfig.faye_uri);
      fayeClient.addExtension(FayeLogger);
      fayeClient.subscribe("/users/" + currentUserId + "/online_state_change", __bind(function(data) {
        if (data.user_id === currentUserId) {
          return App.setUserOnlineState(data.online_state);
        }
      }, this));
      return fayeClient.subscribe("/users/" + currentUserId + "/notifications", function(data) {
        var message, notifyOfChatUpdate;
        log("notification received", data);
        notifyOfChatUpdate = function() {
          var timeoutFunc;
          $('.chat-status').addClass('new-message');
          timeoutFunc = function() {
            return $('.chat-status').removeClass('new-message');
          };
          return window.setTimeout(timeoutFunc, 10000);
        };
        if (data.event === "chat_request") {
          log("growling chat request", data);
          notifyOfChatUpdate();
          message = ("" + data.text + "<br /><a href='/chat/open?user_id=" + data.sender_id + "' data-action='open-chat' data-user_id='" + data.sender_id + "' target='chat'>") + ("" + (I18n.t('chat.chat_request.notification.link')) + "</a>");
          data['text'] = message;
          return $.jGrowl(data, {
            life: 180000
          });
        } else if (data.event === "new_chat_message") {
          log("growling chat message notification", data);
          notifyOfChatUpdate();
          message = ("" + data.text + "<br /><a href='/chat/open?user_id=" + data.sender_id + "' data-action='open-chat' data-user_id='" + data.sender_id + "' target='chat'>") + ("" + (I18n.t('chat.chat_message.notification.link')) + "</a>");
          if (!(window.chatWindow != null) || !window.chatWindow.hasFocus) {
            data['text'] = message;
            return $.jGrowl(data, {
              life: 10000
            });
          }
        } else if (data) {
          return $.jGrowl(data);
        }
      });
    }
  };
}).call(this);
(function() {
  this.App.VideoLibrary = {};
  this.App.VideoLibrary.init = function(lib) {
    return lib.find('.video-library-link').click(function(e) {
      var $el, href;
      e.preventDefault();
      $el = $(e.currentTarget);
      lib.find('.video-library-button').removeClass('enabled');
      $el.find('.video-library-button').addClass('enabled');
      href = $el.attr('href');
      return $('#video-library-iframe').attr('src', href);
    });
  };
}).call(this);
(function() {
  this.App.wizard = {};
  this.App.wizard.stepBasicAttributes = {};
  this.App.wizard.stepExtendedAttributes = {};
  this.App.wizard.init = function() {
    var $avatar, $avatarErrors, $avatarPreview, $body, $containment, $currentImage, $currentImageBox, $positioner, $spinnerOverlay, $wizard, MAX_AVATAR_H, MAX_AVATAR_W, applyCropping, applyFileUpload, closePositioner, lastUploadedFile, showHtmlInPopup, showPositioner;
    showHtmlInPopup = function(html) {
      return $('#fancybox-content > div').html(html);
    };
    $body = $('body');
    $body.delegate('form', 'submit', function(e) {
      var $this;
      $this = $(this);
      if ($this.hasClass('wizard')) {
        e.preventDefault();
        return $this.ajaxSubmit({
          success: showHtmlInPopup
        });
      }
    });
    $body.delegate('.wizard [data-action=close]', 'click', function(e) {
      e.preventDefault();
      return $.fancybox.close();
    });
    $body.delegate('.popup a[href="/registration"]', 'click', function(e) {
      var $this;
      e.preventDefault();
      $this = $(this);
      return $.ajax({
        url: this.href,
        type: 'GET',
        success: showHtmlInPopup
      });
    });
    lastUploadedFile = null;
    $avatar = $('#wizard-form-1-avatar');
    $avatarPreview = $('#wizard-avatar-preview');
    $avatarErrors = $avatar.find('.errors');
    $body.delegate('#wizard-avatar-preview, #wizard-upload-button', 'click', function(e) {
      if ($.browser.msie) {
        return;
      }
      e.preventDefault();
      return $('#user_picture_image').trigger('click');
    });
    applyFileUpload = function($form) {
      if ($.browser.msie || $.browser.mozilla && $.browser.version.slice(0, 5) === '1.9.2') {
        $('#wizard-form-1-avatar').addClass('ie');
        $('#user_picture_image[type=file]').change(function(e) {
          return $('#wizard-form-1-avatar > .info').html("(jpg, jpeg, png - min. 251 x 185 Pixel)<p class=\"picture-choosen-info\">Du hast ein Bild ausgewählt! Klicke auf \"Weiter\" um eine Vorschau zu sehen.</p><b>Bitte beachten Sie:</b><br/>eine Positionierung des Bildes und eine Vorschau ist aus technischen Gründen derzeit mit Ihrem Browser (" + ($.browser.msie ? 'Microsoft Internet Explorer' : 'Firefox 3.6') + ") nicht möglich.<br />Wir bitten Sie um Verständnis und werden diese Funktion so bald wie möglich auch für Ihren Browser anbieten.");
        });
        SI.Files.stylizeById('user_picture_image');
        return;
      }
      return $form.fileupload({
        url: '/registration_avatar_preview',
        type: 'PUT',
        dataType: 'json',
        dropZone: null,
        maxFileSize: 10000000,
        acceptFileTypes: /(\.|\/)(jpe?g|png)$/i,
        previewFileTypes: /^image\/(jpe?g|png)$/i,
        fail: function(event, data) {
          var error, response, _i, _len, _ref, _ref2, _results;
          if ((_ref = data.jqXHR) != null ? _ref.responseText : void 0) {
            response = JSON.parse(data.jqXHR.responseText);
            if (response.errors.length && !$('#image-errors').length) {
              $('<span id="image-errors"></span>').insertAfter($('#wizard-form-1-avatar .info'));
            } else {
              $('#image-errors').empty();
            }
            _ref2 = response.errors;
            _results = [];
            for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
              error = _ref2[_i];
              if (!error.match(/Bitte lade ein Bild hoch/)) {
                $('#image-errors').append('<span class="error-message">' + error + '</span>');
                break;
              }
            }
            return _results;
          }
        },
        done: function(event, data) {
          var avatarCache, imageUrl;
          if ($('#wizard-avatar-preview img').length === 0) {
            $('#wizard-avatar-preview').append('<img />');
          }
          imageUrl = data.result.image_url;
          avatarCache = data.result.avatar_cache;
          $('#wizard-avatar-preview img').attr('src', imageUrl).data('avatar-cache', avatarCache);
          $('#user_picture_image_cache').val(avatarCache);
          $('#wizard-form-1-avatar').removeClass('error');
          $('#wizard-form-1-avatar .error-message').remove();
          return $('#wizard-upload-button').text('Bild ändern');
        },
        start: function(event, data) {
          $form.find('input.button').val('Bildupload läuft...').attr('disabled', true);
          return $avatarPreview.addClass('spinner');
        },
        add: function(event, data) {
          $('#image-errors').empty();
          return data.submit();
        },
        progress: function(event, data) {
          return $('#upload-progress').text(parseInt(data.loaded / data.total * 100, 10) + '%');
        },
        always: function(event) {
          $form.find('input.button').val('Weiter').removeAttr('disabled');
          $('#upload-progress').empty();
          return $avatarPreview.removeClass('spinner');
        }
      });
    };
    $('#wizard-form-1 form').each(function(idx, el) {
      return applyFileUpload($(this));
    });
    $wizard = $('#wizard');
    $positioner = $('#positioner');
    if ($.browser.msie) {
      $('#wizard-position-button').hide();
    }
    $('#wizard-position-button').fancybox({
      onStart: function() {
        return showPositioner();
      },
      onClosed: function() {
        return $positioner.hide();
      }
    });
    $spinnerOverlay = null;
    MAX_AVATAR_W = 522;
    MAX_AVATAR_H = 370;
    $currentImageBox = $('.current-image');
    $currentImage = $currentImageBox.find('img');
    $containment = function($width, $height) {
      if ($width < MAX_AVATAR_W && $height >= MAX_AVATAR_H) {
        $currentImage.width(MAX_AVATAR_W);
        $width = MAX_AVATAR_W;
        $height = $currentImage.height();
        $positioner.find('.zoom-out').attr('disabled', true);
      } else if ($height < MAX_AVATAR_H && $width >= MAX_AVATAR_W) {
        $currentImage.height(MAX_AVATAR_H);
        $height = MAX_AVATAR_H;
        $width = $currentImage.width();
        $positioner.find('.zoom-out').attr('disabled', true);
      } else if ($height <= MAX_AVATAR_H && $width <= MAX_AVATAR_W) {
        $currentImage.width('auto');
        $currentImage.height(MAX_AVATAR_H);
        if ($currentImage.width() < MAX_AVATAR_W) {
          $currentImage.height('auto');
          $currentImage.width(MAX_AVATAR_W);
          $width = MAX_AVATAR_W;
          $height = $currentImage.height();
        } else {
          $height = MAX_AVATAR_H;
          $width = $currentImage.width();
        }
        $positioner.find('.zoom-out').attr('disabled', true);
      } else {
        $positioner.find('.zoom-out').removeAttr('disabled');
      }
      return [$positioner.offset().left + ($width - MAX_AVATAR_W) * -1, $positioner.offset().top + ($height - MAX_AVATAR_H) * -1, $positioner.offset().left, $positioner.offset().top];
    };
    showPositioner = function() {
      var $actions, boxHeight, boxWidth, canDrag, dragBox, dragItem, dragItemLeft, dragItemTop, imageCroppingData, maxX, maxY, mouseX, mouseY;
      $actions = $positioner.find('.actions');
      if ($('#gallery-crop-overlay').length === 0) {
        $currentImageBox.append($('<div id="gallery-crop-overlay"></div>'));
      }
      if ($('#thumbnail-overlay').length === 0) {
        $currentImageBox.append($('<div id="thumbnail-overlay"></div>'));
      }
      if ($('#gallery-dragbox').length === 0) {
        $currentImageBox.append($('<div id="gallery-dragbox"></div>'));
      }
      imageCroppingData = {
        'x': parseInt($currentImageBox.find('input#avatar_position_x').val()),
        'y': parseInt($currentImageBox.find('input#avatar_position_y').val()),
        'width': parseInt($currentImageBox.find('input#avatar_width').val())
      };
      applyCropping($currentImage, imageCroppingData);
      dragBox = $currentImageBox;
      dragItem = $currentImage;
      boxWidth = $('#gallery-dragbox').width();
      boxHeight = $('#gallery-dragbox').height();
      canDrag = false;
      mouseX = mouseY = dragItemLeft = dragItemTop = null;
      maxX = maxY = 0;
      dragBox.mousedown(function(event) {
        canDrag = true;
        dragBox.addClass('canDrag');
        mouseX = event.pageX;
        mouseY = event.pageY;
        dragItemLeft = parseInt(dragItem.css('left'));
        dragItemTop = parseInt(dragItem.css('top'));
        return false;
      });
      $(document).mouseup(function() {
        canDrag = false;
        return dragBox.removeClass('canDrag');
      });
      $(document).mousemove(function(event) {
        var leftX, minX, minY, mousemoveX, mousemoveY, topY;
        if (canDrag) {
          minX = boxWidth - dragItem.width();
          minY = boxHeight - dragItem.height();
          mousemoveX = event.pageX - mouseX;
          mousemoveY = event.pageY - mouseY;
          leftX = dragItemLeft + mousemoveX;
          topY = dragItemTop + mousemoveY;
          if (minX <= leftX && leftX <= maxX) {
            dragItem.css('left', leftX + 'px');
          }
          if (minY <= topY && topY <= maxY) {
            dragItem.css('top', topY + 'px');
          }
        }
        return false;
      });
      $actions.html('<div id="gallery-position-zoom"><button class="button zoom-in tooltip_2" title="Bild vergrößern">Zoom größer</button><button class="button zoom-out tooltip_2" title="Bild verkleinern">Zoom kleiner</button><p>Positionieren Sie das Bild durch Ziehen mit der Maus</p></div><button class="button avatar-position-save tooltip-2" title="Speichern und weiter">Bildausschnitt speichern</button><button class="button avatar-position-cancel tooltip_2" title="Abbrechen">Abbrechen</button>');
      return $positioner.show();
    };
    $positioner.delegate('.zoom-in', 'click', function(e) {
      e.preventDefault();
      $currentImage = $('.current-image img');
      return $currentImage.height('auto').width($currentImage.width() * 1.1).draggable("option", "containment", $containment($currentImage.width(), $currentImage.height())).css({
        left: 0,
        top: 0
      });
    });
    $positioner.delegate('.zoom-out', 'click', function(e) {
      e.preventDefault();
      $currentImage = $('.current-image img');
      return $currentImage.height('auto').width($currentImage.width() * 0.9).draggable("option", "containment", $containment($currentImage.width(), $currentImage.height())).css({
        left: 0,
        top: 0
      });
    });
    $positioner.delegate('.avatar-position-save', 'click', function(e) {
      var id, img, newPositionLeft, newPositionTop, newWidth;
      e.preventDefault();
      $currentImage = $('.current-image img');
      newPositionLeft = $currentImage.position().left;
      newPositionTop = $currentImage.position().top;
      newWidth = $currentImage.width();
      $('#avatar_position_x').val(newPositionLeft);
      $('#avatar_position_y').val(newPositionTop);
      $('#avatar_width').val(newWidth);
      closePositioner();
      img = $avatarPreview.find('img');
      id = img.data('id');
      return $.ajax({
        url: "/api/v1/pictures/" + id,
        type: "put",
        data: {
          picture: {
            avatar_position_x: newPositionLeft,
            avatar_position_y: newPositionTop,
            avatar_width: newWidth
          }
        },
        beforeSend: function(jqXHR, settings) {
          return $spinnerOverlay = App.spinner().init({
            el: $avatarPreview,
            text: ''
          });
        },
        complete: function(jqXHR, textStatus) {
          return $spinnerOverlay.remove();
        },
        success: function(data) {
          var match, newSrc;
          match = img.attr('src').match(/(.+)(?:\?\d+$)?/);
          newSrc = "" + match[1] + "?" + (new Date().getTime());
          return img.attr('src', newSrc);
        }
      });
    });
    $positioner.delegate('.avatar-position-cancel', 'click', function(e) {
      e.preventDefault();
      return closePositioner();
    });
    closePositioner = function() {
      return $.fancybox.close();
    };
    return applyCropping = function(image, cropData) {
      image.css('left', cropData.x).css('top', cropData.y);
      if (cropData.width > 0) {
        return image.css('width', cropData.width);
      }
    };
  };
  this.App.wizard.stepBasicAttributes.init = function() {
    var $wizardForm1;
    $wizardForm1 = $('#wizard-form-1');
    if ($wizardForm1.length) {
      return App.wizard.stepBasicAttributes.initGenderSwitch($wizardForm1);
    }
  };
  this.App.wizard.stepBasicAttributes.initGenderSwitch = function($wizardForm1) {
    var $genderPreference, $genderSelect, changeFunction;
    if ($wizardForm1.length) {
      $genderSelect = $wizardForm1.find('#user_profile_attributes_gender');
      $genderPreference = $wizardForm1.find('#user_profile_attributes_gender_preference');
      changeFunction = function(e) {
        var $targetSelect, switchFunction, targetSelect;
        targetSelect = e.currentTarget;
        $targetSelect = $(targetSelect);
        switchFunction = function(source, target) {
          if (source.selectedIndex === 1) {
            return target.selectedIndex = 2;
          } else if (source.selectedIndex === 2) {
            return target.selectedIndex = 1;
          }
        };
        if ($targetSelect.is('#user_profile_attributes_gender')) {
          return switchFunction(targetSelect, $genderPreference[0]);
        } else if ($targetSelect.is('#user_profile_attributes_gender_preference')) {
          return switchFunction(targetSelect, $genderSelect[0]);
        }
      };
      $genderSelect.change(changeFunction);
      return $genderPreference.change(changeFunction);
    }
  };
  this.App.wizard.stepExtendedAttributes.init = function() {
    var $wizardForm3;
    $wizardForm3 = $('#wizard-form-3');
    if ($wizardForm3.length) {
      return App.wizard.stepExtendedAttributes.initSlider($wizardForm3);
    }
  };
  this.App.wizard.stepExtendedAttributes.initSlider = function($wizardForm3) {
    var $profileHeightEl;
    if ($wizardForm3.length) {
      $profileHeightEl = $wizardForm3.find("#profile_height");
      $profileHeightEl.selectToUISlider({
        labels: 0,
        sliderOptions: {
          create: function(e, ui) {
            return $(e.target).attr('id', 'profile-height-ui-slider');
          }
        }
      });
      return $profileHeightEl.hide();
    }
  };
}).call(this);
 /*
 * jQuery UI selectmenu
 *
 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI
 * https://github.com/fnagel/jquery-ui/wiki/Selectmenu
 */


(function($) {

$.widget("ui.selectmenu", {
	getter: "value",
	version: "1.8",
	eventPrefix: "selectmenu",
	options: {
		transferClasses: true,
		typeAhead: "sequential",
		style: 'dropdown',
		positionOptions: {
			my: "left top",
			at: "left bottom",
			offset: null
		},
		width: null, 
		menuWidth: null, 
		handleWidth: 26,
		maxHeight: null,
		icons: null, 
		format: null,
		bgImage: function() {},
		wrapperElement: ""
	},

	_create: function() {
		var self = this, o = this.options;
 
		// set a default id value, generate a new random one if not set by developer
		var selectmenuId = this.element.attr('id') || 'ui-selectmenu-' + Math.random().toString(16).slice(2, 10);
        				
		// quick array of button and menu id's
		this.ids = [ selectmenuId + '-button', selectmenuId + '-menu' ];

		// define safe mouseup for future toggling
		this._safemouseup = true;
		
		// create menu button wrapper
		this.newelement = $('<a class="' + this.widgetBaseClass + ' ui-widget ui-state-default ui-corner-all" id="' + this.ids[0] + '" role="button" href="#" tabindex="0" aria-haspopup="true" aria-owns="' + this.ids[1] + '"></a>')
			.insertAfter(this.element);
		this.newelement.wrap(o.wrapperElement);

		// transfer tabindex
		var tabindex = this.element.attr('tabindex');
		if (tabindex) {
			this.newelement.attr('tabindex', tabindex);
		}

		// save reference to select in data for ease in calling methods
		this.newelement.data('selectelement', this.element);
		
		// menu icon
		this.selectmenuIcon = $('<span class="' + this.widgetBaseClass + '-icon ui-icon"></span>')
			.prependTo(this.newelement);
			
		// append status span to button
		this.newelement.prepend('<span class="' + self.widgetBaseClass + '-status" />');
			
		// make associated form label trigger focus
		$('label[for="' + this.element.attr('id') + '"]')
			.attr('for', this.ids[0])
			.bind('click.selectmenu', function() {
				self.newelement[0].focus();
				return false;
			});	
			
		// click toggle for menu visibility
		this.newelement
			.bind('mousedown.selectmenu', function(event) {
				self._toggle(event, true);
				// make sure a click won't open/close instantly
				if (o.style == "popup") {
					self._safemouseup = false;
					setTimeout(function() { self._safemouseup = true; }, 300);
				}
				return false;
			})
			.bind('click.selectmenu', function() {
				return false;
			})
			.bind("keydown.selectmenu", function(event) {
				var ret = false;
				switch (event.keyCode) {
					case $.ui.keyCode.ENTER:
						ret = true;
						break;
					case $.ui.keyCode.SPACE:
						self._toggle(event);	
						break;
					case $.ui.keyCode.UP:
						if (event.altKey) {
							self.open(event);
						} else {
							self._moveSelection(-1);
						}
						break;
					case $.ui.keyCode.DOWN:
						if (event.altKey) {
							self.open(event);
						} else {
							self._moveSelection(1);
						}
						break;
					case $.ui.keyCode.LEFT:
						self._moveSelection(-1);
						break;
					case $.ui.keyCode.RIGHT:
						self._moveSelection(1);
						break;
					case $.ui.keyCode.TAB:
						ret = true;
						break;
					default:
						ret = true;
				}
				return ret;
			})
			.bind('keypress.selectmenu', function(event) {
				self._typeAhead(event.which, 'mouseup');
				return true;
			})
			.bind('mouseover.selectmenu focus.selectmenu', function() { 
				if (!o.disabled) {
					$(this).addClass(self.widgetBaseClass + '-focus ui-state-hover');
				}
			})
			.bind('mouseout.selectmenu blur.selectmenu', function() {
				if (!o.disabled) {
					$(this).removeClass(self.widgetBaseClass + '-focus ui-state-hover');
				}
			});

		// document click closes menu
		$(document).bind("mousedown.selectmenu", function(event) {
			self.close(event);
		});

		// change event on original selectmenu
		this.element
			.bind("click.selectmenu", function() {
				self._refreshValue();
			})
			// FIXME: newelement can be null under unclear circumstances in IE8 
			// TODO not sure if this is still a problem (fnagel 20.03.11)
			.bind("focus.selectmenu", function() {
				if (self.newelement) {
					self.newelement[0].focus();
				}
			});

		// set width when not set via options
		if (!o.width) {
			o.width = this.element.outerWidth();
		}		
		// set menu button width
		this.newelement.width(o.width);

		// hide original selectmenu element
		this.element.hide();		

		// create menu portion, append to body
		this.list = $('<ul class="' + self.widgetBaseClass + '-menu ui-widget ui-widget-content" aria-hidden="true" role="listbox" aria-labelledby="' + this.ids[0] + '" id="' + this.ids[1] + '"></ul>').appendTo('body');
		this.list.wrap(o.wrapperElement);				

		// transfer menu click to menu button
		this.list
			.bind("keydown.selectmenu", function(event) {
				var ret = false;
				switch (event.keyCode) {
					case $.ui.keyCode.UP:
						if (event.altKey) {
							self.close(event, true);
						} else {
							self._moveFocus(-1);
						}
						break;
					case $.ui.keyCode.DOWN:
						if (event.altKey) {
							self.close(event, true);
						} else {
							self._moveFocus(1);
						}
						break;	
					case $.ui.keyCode.LEFT:
						self._moveFocus(-1);
						break;
					case $.ui.keyCode.RIGHT:
						self._moveFocus(1);
						break;	
					case $.ui.keyCode.HOME:
						self._moveFocus(':first');
						break;		
					case $.ui.keyCode.PAGE_UP:
						self._scrollPage('up');
						break;	
					case $.ui.keyCode.PAGE_DOWN:
						self._scrollPage('down');
						break;
					case $.ui.keyCode.END:
						self._moveFocus(':last');
						break;		
					case $.ui.keyCode.ENTER:
					case $.ui.keyCode.SPACE:
						self.close(event, true);
						$(event.target).parents('li:eq(0)').trigger('mouseup');
						break;		
					case $.ui.keyCode.TAB:
						ret = true;
						self.close(event, true);
						$(event.target).parents('li:eq(0)').trigger('mouseup');
						break;	
					case $.ui.keyCode.ESCAPE:
						self.close(event, true);
						break;
					default:
						ret = true;	
				}
				return ret;
			})
			.bind('keypress.selectmenu', function(event) {
				self._typeAhead(event.which, 'focus');
				return true;
			});			
		
		// needed when window is resized
		$(window).bind( "resize.selectmenu", $.proxy( self._refreshPosition, this ) );
	},

	_init: function() {
		var self = this, o = this.options;
		
		// serialize selectmenu element options	
		var selectOptionData = [];
		this.element
			.find('option')
			.each(function() {
				selectOptionData.push({
					value: $(this).attr('value'),
					text: self._formatText($(this).text()),
					selected: $(this).attr('selected'),
					disabled: $(this).attr('disabled'),
					classes: $(this).attr('class'),
					typeahead: $(this).attr('typeahead'),
					parentOptGroup: $(this).parent('optgroup'),
					bgImage: o.bgImage.call($(this))
				});
			});		
				
		// active state class is only used in popup style
		var activeClass = (self.options.style == "popup") ? " ui-state-active" : "";

		// empty list so we can refresh the selectmenu via selectmenu()
		this.list.html("");

		// write li's
		for (var i = 0; i < selectOptionData.length; i++) {
				var thisLi = $('<li role="presentation"' + (selectOptionData[i].disabled ? ' class="' + this.namespace + '-state-disabled' + '"' : '' ) + '><a href="#" tabindex="-1" role="option"' + (selectOptionData[i].disabled ? ' aria-disabled="true"' : '' ) + ' aria-selected="false"' + (selectOptionData[i].typeahead ? ' typeahead="' + selectOptionData[i].typeahead + '"' : '' ) + '>'+ selectOptionData[i].text +'</a></li>')
				.data('index', i)
				.addClass(selectOptionData[i].classes)
				.data('optionClasses', selectOptionData[i].classes || '')
				.bind("mouseup.selectmenu", function(event) {
					if (self._safemouseup && !self._disabled(event.currentTarget) && !self._disabled($( event.currentTarget ).parents( "ul>li." + self.widgetBaseClass + "-group " )) ) {
						var changed = $(this).data('index') != self._selectedIndex();
						self.index($(this).data('index'));
						self.select(event);
						if (changed) {
							self.change(event);
						}
						self.close(event, true);
					}
					return false;
				})
				.bind("click.selectmenu", function() {
					return false;
				})
				.bind('mouseover.selectmenu focus.selectmenu', function(e) {
					// no hover if diabled
					if (!$(e.currentTarget).hasClass(self.namespace + '-state-disabled')) {
						self._selectedOptionLi().addClass(activeClass); 
						self._focusedOptionLi().removeClass(self.widgetBaseClass + '-item-focus ui-state-hover'); 
						$(this).removeClass('ui-state-active').addClass(self.widgetBaseClass + '-item-focus ui-state-hover'); 
					}
				})
				.bind('mouseout.selectmenu blur.selectmenu', function() { 
					if ($(this).is(self._selectedOptionLi().selector)) {
						$(this).addClass(activeClass);
					}
					$(this).removeClass(self.widgetBaseClass + '-item-focus ui-state-hover');
				});

			// optgroup or not...
			if ( selectOptionData[i].parentOptGroup.length ) {
				var optGroupName = self.widgetBaseClass + '-group-' + this.element.find( 'optgroup' ).index( selectOptionData[i].parentOptGroup );
				if (this.list.find( 'li.' + optGroupName ).length ) {
					this.list.find( 'li.' + optGroupName + ':last ul' ).append( thisLi );
				} else {
					$(' <li role="presentation" class="' + self.widgetBaseClass + '-group ' + optGroupName + (selectOptionData[i].parentOptGroup.attr("disabled") ? ' ' + this.namespace + '-state-disabled" aria-disabled="true"' : '"' ) + '><span class="' + self.widgetBaseClass + '-group-label">' + selectOptionData[i].parentOptGroup.attr('label') + '</span><ul></ul></li> ')
						.appendTo( this.list )
						.find( 'ul' )
						.append( thisLi );
				}
			} else {
				thisLi.appendTo(this.list);
			}
			
			// this allows for using the scrollbar in an overflowed list
			this.list.bind('mousedown.selectmenu mouseup.selectmenu', function() { return false; });
			
			// append icon if option is specified
			if (o.icons) {
				for (var j in o.icons) {
					if (thisLi.is(o.icons[j].find)) {
						thisLi
							.data('optionClasses', selectOptionData[i].classes + ' ' + self.widgetBaseClass + '-hasIcon')
							.addClass(self.widgetBaseClass + '-hasIcon');
						var iconClass = o.icons[j].icon || "";						
						thisLi
							.find('a:eq(0)')
							.prepend('<span class="' + self.widgetBaseClass + '-item-icon ui-icon ' + iconClass + '"></span>');
						if (selectOptionData[i].bgImage) {
							thisLi.find('span').css('background-image', selectOptionData[i].bgImage);
						}
					}
				}
			}
		}	
				
		// we need to set and unset the CSS classes for dropdown and popup style
		var isDropDown = (o.style == 'dropdown');
		this.newelement
			.toggleClass(self.widgetBaseClass + "-dropdown", isDropDown)
			.toggleClass(self.widgetBaseClass + "-popup", !isDropDown);
		this.list
			.toggleClass(self.widgetBaseClass + "-menu-dropdown ui-corner-bottom", isDropDown)
			.toggleClass(self.widgetBaseClass + "-menu-popup ui-corner-all", !isDropDown)
			// add corners to top and bottom menu items
			.find('li:first')
			.toggleClass("ui-corner-top", !isDropDown)
			.end().find('li:last')
			.addClass("ui-corner-bottom");
		this.selectmenuIcon
			.toggleClass('ui-icon-triangle-1-s', isDropDown)
			.toggleClass('ui-icon-triangle-2-n-s', !isDropDown);

		// transfer classes to selectmenu and list
		if (o.transferClasses) {
			var transferClasses = this.element.attr('class') || '';
			this.newelement.add(this.list).addClass(transferClasses);
		}

		// set menu width to either menuWidth option value, width option value, or select width 
		if (o.style == 'dropdown') { 
			this.list.width(o.menuWidth ? o.menuWidth : o.width); 
		} else { 
			this.list.width(o.menuWidth ? o.menuWidth : o.width - o.handleWidth); 
		}

		// calculate default max height
		if (o.maxHeight) {
			// set max height from option 
			if (o.maxHeight < this.list.height()) {
				this.list.height(o.maxHeight);
			}
		} else {
			if (!o.format && ($(window).height() / 3) < this.list.height()) {
				o.maxHeight = $(window).height() / 3;
				this.list.height(o.maxHeight);
			}
		}

		// save reference to actionable li's (not group label li's)
		this._optionLis = this.list.find('li:not(.' + self.widgetBaseClass + '-group)');
						
		// transfer disabled state
		if (this.element.attr('disabled') === true) {
			this.disable();
		}

		// update value
		this.index(this._selectedIndex());		

		// needed when selectmenu is placed at the very bottom / top of the page
		window.setTimeout(function() {
			self._refreshPosition();
		}, 200);
	},

	destroy: function() {
		this.element.removeData( this.widgetName )
			.removeClass( this.widgetBaseClass + '-disabled' + ' ' + this.namespace + '-state-disabled' )
			.removeAttr( 'aria-disabled' )
			.unbind( ".selectmenu" );
			
		$( window ).unbind( ".selectmenu" );
		$( document ).unbind( ".selectmenu" );
	
		// unbind click on label, reset its for attr
		$( 'label[for=' + this.newelement.attr('id') + ']' )
			.attr( 'for', this.element.attr( 'id' ) )
			.unbind( '.selectmenu' );
		
		if ( this.options.wrapperElement ) {
			this.newelement.find( this.options.wrapperElement ).remove();
			this.list.find( this.options.wrapperElement ).remove();
		} else {
			this.newelement.remove();
			this.list.remove();
		}
		this.element.show();	

		// call widget destroy function
		$.Widget.prototype.destroy.apply(this, arguments);
	},

	_typeAhead: function(code, eventType){
		var self = this, focusFound = false, C = String.fromCharCode(code).toUpperCase();
		c = C.toLowerCase();

		if (self.options.typeAhead == 'sequential') {
			// clear the timeout so we can use _prevChar
			window.clearTimeout('ui.selectmenu-' + self.selectmenuId);

			// define our find var
			var find = typeof(self._prevChar) == 'undefined' ? '' : self._prevChar.join('');
			
			function focusOptSeq(elem, ind, c){
				focusFound = true;
				$(elem).trigger(eventType);
				typeof(self._prevChar) == 'undefined' ? self._prevChar = [c] : self._prevChar[self._prevChar.length] = c;
			}
			this.list.find('li a').each(function(i) {	
				if (!focusFound) {
					// allow the typeahead attribute on the option tag for a more specific lookup
					var thisText = $(this).attr('typeahead') || $(this).text();
					if (thisText.indexOf(find+C) == 0) {
						focusOptSeq(this,i,C)
					} else if (thisText.indexOf(find+c) == 0) {
						focusOptSeq(this,i,c)
					}
				}
			});
			// set a 1 second timeout for sequenctial typeahead
			//  	keep this set even if we have no matches so it doesnt typeahead somewhere else
			window.setTimeout(function(el) {
				self._prevChar = undefined;
			}, 1000, self);

		} else {
			//define self._prevChar if needed
			if (!self._prevChar){ self._prevChar = ['',0]; }

			var focusFound = false;
			function focusOpt(elem, ind){
				focusFound = true;
				$(elem).trigger(eventType);
				self._prevChar[1] = ind;
			}
			this.list.find('li a').each(function(i){	
				if(!focusFound){
					var thisText = $(this).text();
					if( thisText.indexOf(C) == 0 || thisText.indexOf(c) == 0){
							if(self._prevChar[0] == C){
								if(self._prevChar[1] < i){ focusOpt(this,i); }	
							}
							else{ focusOpt(this,i); }	
					}
				}
			});
			this._prevChar[0] = C;
		}
	},
	
	// returns some usefull information, called by callbacks only
	_uiHash: function() {
		var index = this.index();
		return {
			index: index,
			option: $("option", this.element).get(index),
			value: this.element[0].value
		};
	},

	open: function(event) {
		var self = this;
		if ( this.newelement.attr("aria-disabled") != 'true' ) {
			this._closeOthers(event);
			this.newelement
				.addClass('ui-state-active');
			if (self.options.wrapperElement) {
				this.list.parent().appendTo('body');
			} else {
				this.list.appendTo('body');
			}
			
			this.list.addClass(self.widgetBaseClass + '-open').attr('aria-hidden', false);
			// FIX IE: Refreshing position before focusing the element, prevents IE from scrolling to the focused element before it is in position.
			this._refreshPosition();
			     if(this._selectedIndex() > 0) {
			       this.list.find('li:not(.' + self.widgetBaseClass + '-group):eq(' + this._selectedIndex() + ') a')[0].focus();
			 }
			 
			if ( this.options.style == "dropdown" ) {
				this.newelement.removeClass('ui-corner-all').addClass('ui-corner-top');
			}
			this._trigger("open", event, this._uiHash());
		}
	},

	close: function(event, retainFocus) {
		if ( this.newelement.is('.ui-state-active') ) {
			this.newelement
				.removeClass('ui-state-active');
			this.list
				.attr('aria-hidden', true)
				.removeClass(this.widgetBaseClass + '-open');
			if ( this.options.style == "dropdown" ) {
				this.newelement.removeClass('ui-corner-top').addClass('ui-corner-all');
			}
			if ( retainFocus ) {
				this.newelement.focus();
			}
			this._trigger("close", event, this._uiHash());
		}
	},

	change: function(event) {
		this.element.trigger("change");
		this._trigger("change", event, this._uiHash());
	},

	select: function(event) {
                if (this._disabled(event.currentTarget)) { return false; }
		this._trigger("select", event, this._uiHash());
	},

	_closeOthers: function(event) {
		$('.' + this.widgetBaseClass + '.ui-state-active').not(this.newelement).each(function() {
			$(this).data('selectelement').selectmenu('close', event);
		});
		$('.' + this.widgetBaseClass + '.ui-state-hover').trigger('mouseout');
	},

	_toggle: function(event, retainFocus) {
		if ( this.list.is('.' + this.widgetBaseClass + '-open') ) {
			this.close(event, retainFocus);
		} else {
			this.open(event);
		}
	},

	_formatText: function(text) {
		return (this.options.format ? this.options.format(text) : text);
	},

	_selectedIndex: function() {
		return this.element[0].selectedIndex;
	},

	_selectedOptionLi: function() {
		return this._optionLis.eq(this._selectedIndex());
	},

	_focusedOptionLi: function() {
		return this.list.find('.' + this.widgetBaseClass + '-item-focus');
	},

	_moveSelection: function(amt, recIndex) {
		var currIndex = parseInt(this._selectedOptionLi().data('index') || 0, 10);
		var newIndex = currIndex + amt;
		// do not loop when using up key
        
        if (newIndex < 0) {
			newIndex = 0;
		}
		if (newIndex > this._optionLis.size() - 1) {
			newIndex = this._optionLis.size() - 1;
		}
        //Occurs when a full loop has been made
        if (newIndex === recIndex) { return false; }
        
        if (this._optionLis.eq(newIndex).hasClass( this.namespace + '-state-disabled' )) {
			// if option at newIndex is disabled, call _moveFocus, incrementing amt by one
			(amt > 0) ? ++amt : --amt;
			this._moveSelection(amt, newIndex);
		} else {
            return this._optionLis.eq(newIndex).trigger('mouseup');
		}
	},

	_moveFocus: function(amt, recIndex) {
		if (!isNaN(amt)) {
			var currIndex = parseInt(this._focusedOptionLi().data('index') || 0, 10);
			var newIndex = currIndex + amt;
		}
		else {
			var newIndex = parseInt(this._optionLis.filter(amt).data('index'), 10);
		}

		if (newIndex < 0) {
			newIndex = 0;
		}
		if (newIndex > this._optionLis.size() - 1) {
			newIndex = this._optionLis.size() - 1;
		}
        
        //Occurs when a full loop has been made
        if (newIndex === recIndex) { return false; }
		
		var activeID = this.widgetBaseClass + '-item-' + Math.round(Math.random() * 1000);

		this._focusedOptionLi().find('a:eq(0)').attr('id', '');
		
		if (this._optionLis.eq(newIndex).hasClass( this.namespace + '-state-disabled' )) {
			// if option at newIndex is disabled, call _moveFocus, incrementing amt by one
			(amt > 0) ? ++amt : --amt;
			this._moveFocus(amt, newIndex);
		} else {
			this._optionLis.eq(newIndex).find('a:eq(0)').attr('id',activeID).focus();
		}
		
		this.list.attr('aria-activedescendant', activeID);
	},

	_scrollPage: function(direction) {
		var numPerPage = Math.floor(this.list.outerHeight() / this.list.find('li:first').outerHeight());
		numPerPage = (direction == 'up' ? -numPerPage : numPerPage);
		this._moveFocus(numPerPage);
	},

	_setOption: function(key, value) {
		this.options[key] = value;
		// set 
		if (key == 'disabled') {
			this.close();
			this.element
				.add(this.newelement)
				.add(this.list)[value ? 'addClass' : 'removeClass'](
					this.widgetBaseClass + '-disabled' + ' ' +
					this.namespace + '-state-disabled')
				.attr("aria-disabled", value);
		}
	},

	disable: function(index, type){
			// if options is not provided, call the parents disable function
			if ( typeof( index ) == 'undefined' ) {
				this._setOption( 'disabled', true );
			} else {
				if ( type == "optgroup" ) {
					this._disableOptgroup(index);
				} else {
					this._disableOption(index);
				}
			}
	},

	enable: function(index, type) {
			// if options is not provided, call the parents enable function
			if ( typeof( index ) == 'undefined' ) {
				this._setOption('disabled', false);
			} else {
				if ( type == "optgroup" ) {
					this._enableOptgroup(index);
				} else {
					this._enableOption(index);
				}
			}
	},

	_disabled: function(elem) {
			return $(elem).hasClass( this.namespace + '-state-disabled' );
	},
	

	_disableOption: function(index) {
			var optionElem = this._optionLis.eq(index);
			if (optionElem) {
				optionElem.addClass(this.namespace + '-state-disabled')
					.find("a").attr("aria-disabled", true);
				this.element.find("option").eq(index).attr("disabled", "disabled");
			}
	},

	_enableOption: function(index) {
			var optionElem = this._optionLis.eq(index);
			if (optionElem) {
				optionElem.removeClass( this.namespace + '-state-disabled' )
					.find("a").attr("aria-disabled", false);
				this.element.find("option").eq(index).removeAttr("disabled");
			}
	},

	_disableOptgroup: function(index) {		
			var optGroupElem = this.list.find( 'li.' + this.widgetBaseClass + '-group-' + index );
			if (optGroupElem) {
				optGroupElem.addClass(this.namespace + '-state-disabled')
					.attr("aria-disabled", true);
				this.element.find("optgroup").eq(index).attr("disabled", "disabled");
			}
	},

	_enableOptgroup: function(index) {		
			var optGroupElem = this.list.find( 'li.' + this.widgetBaseClass + '-group-' + index );
			if (optGroupElem) {
				optGroupElem.removeClass(this.namespace + '-state-disabled')
					.attr("aria-disabled", false);
				this.element.find("optgroup").eq(index).removeAttr("disabled");
			}
	},
	
	index: function(newValue) {
		if (arguments.length) {
			if (!this._disabled($(this._optionLis[newValue]))) {
				this.element[0].selectedIndex = newValue;
				this._refreshValue();
			} else {
				return false;
			}
		} else {
			return this._selectedIndex();
		}
	},

	value: function(newValue) {
		if (arguments.length) {
			this.element[0].value = newValue;
			this._refreshValue();
		} else {
			return this.element[0].value;
		}
	},

	_refreshValue: function() {
		var activeClass = (this.options.style == "popup") ? " ui-state-active" : "";
		var activeID = this.widgetBaseClass + '-item-' + Math.round(Math.random() * 1000);
		// deselect previous
		this.list
			.find('.' + this.widgetBaseClass + '-item-selected')
			.removeClass(this.widgetBaseClass + "-item-selected" + activeClass)
			.find('a')
			.attr('aria-selected', 'false')
			.attr('id', '');
		// select new
		this._selectedOptionLi()
			.addClass(this.widgetBaseClass + "-item-selected" + activeClass)
			.find('a')
			.attr('aria-selected', 'true')
			.attr('id', activeID);
			
		// toggle any class brought in from option
		var currentOptionClasses = (this.newelement.data('optionClasses') ? this.newelement.data('optionClasses') : "");
		var newOptionClasses = (this._selectedOptionLi().data('optionClasses') ? this._selectedOptionLi().data('optionClasses') : "");
		this.newelement
			.removeClass(currentOptionClasses)
			.data('optionClasses', newOptionClasses)
			.addClass( newOptionClasses )
			.find('.' + this.widgetBaseClass + '-status')
			.html( 
				this._selectedOptionLi()
					.find('a:eq(0)')
					.html()
			);

		this.list.attr('aria-activedescendant', activeID);
	},

	_refreshPosition: function() {
		var o = this.options;
		// if its a native pop-up we need to calculate the position of the selected li
		if (o.style == "popup" && !o.positionOptions.offset) {
			var selected = this._selectedOptionLi();
			var _offset = "0";
			if(typeof selected == "undefined" || selected == null || selected.length == 0) {
				_offset = "0 -0";
			} else {
				_offset = "0 -" + (selected.outerHeight() + selected.offset().top - this.list.offset().top);
			}

		}
		// update zIndex if jQuery UI is able to process
		var zIndexElement = this.element.zIndex();
		if (zIndexElement) {
			this.list.css({
				zIndex: zIndexElement
			});
		}
		this.list.position({
				// set options for position plugin
				of: o.positionOptions.of || this.newelement,
				my: o.positionOptions.my,
				at: o.positionOptions.at,
				offset: o.positionOptions.offset || _offset,
				collision: o.positionOptions.collision || 'flip'
			});
	}
});

})(jQuery);
/*
 * --------------------------------------------------------------------
 * jQuery-Plugin - selectToUISlider - creates a UI slider component from a select element(s)
 * by Scott Jehl, scott@filamentgroup.com
 * http://www.filamentgroup.com
 * reference article: http://www.filamentgroup.com/lab/update_jquery_ui_16_slider_from_a_select_element/
 * demo page: http://www.filamentgroup.com/examples/slider_v2/index.html
 * 
 * Copyright (c) 2008 Filament Group, Inc
 * Dual licensed under the MIT (filamentgroup.com/examples/mit-license.txt) and GPL (filamentgroup.com/examples/gpl-license.txt) licenses.
 *
 * Usage Notes: please refer to our article above for documentation
 *  
 * --------------------------------------------------------------------
 */



jQuery.fn.selectToUISlider = function(settings){
	var selects = jQuery(this);
	
	//accessible slider options
	var options = jQuery.extend({
		labels: 3, //number of visible labels
		tooltip: true, //show tooltips, boolean
		tooltipSrc: 'text',//accepts 'value' as well
		labelSrc: 'value',//accepts 'value' as well	,
		sliderOptions: null
	}, settings);

	//handle ID attrs - selects each need IDs for handles to find them
	var handleIds = (function(){
		var tempArr = [];
		selects.each(function(){
			tempArr.push('handle_'+jQuery(this).attr('id'));
		});
		return tempArr;
	})();
	
	//array of all option elements in select element (ignores optgroups)
	var selectOptions = (function(){
		var opts = [];
		selects.eq(0).find('option').each(function(){
			opts.push({
				value: jQuery(this).attr('value'),
				text: jQuery(this).text()
			});
		});
		return opts;
	})();
	
	//array of opt groups if present
	var groups = (function(){
		if(selects.eq(0).find('optgroup').size()>0){
			var groupedData = [];
			selects.eq(0).find('optgroup').each(function(i){
				groupedData[i] = {};
				groupedData[i].label = jQuery(this).attr('label');
				groupedData[i].options = [];
				jQuery(this).find('option').each(function(){
					groupedData[i].options.push({text: jQuery(this).text(), value: jQuery(this).attr('value')});
				});
			});
			return groupedData;
		}
		else return null;
	})();	
	
	//check if obj is array
	function isArray(obj) {
		return obj.constructor == Array;
	}
	//return tooltip text from option index
	function ttText(optIndex){
		return (options.tooltipSrc == 'text') ? selectOptions[optIndex].text : selectOptions[optIndex].value;
	}
	
	//plugin-generated slider options (can be overridden)
	var sliderOptions = {
		step: 1,
		min: 0,
		orientation: 'horizontal',
		max: selectOptions.length-1,
		range: selects.length > 1,//multiple select elements = true
		slide: function(e, ui) {//slide function
				var thisHandle = jQuery(ui.handle);
				//handle feedback 
				var textval = ttText(ui.value);
				thisHandle
					.attr('aria-valuetext', textval)
					.attr('aria-valuenow', ui.value)
					.find('.ui-slider-tooltip .ttContent')
						.text( textval );

				//control original select menu
				var currSelect = jQuery('#' + thisHandle.attr('id').split('handle_')[1]);
				currSelect.find('option').eq(ui.value).attr('selected', 'selected');
		},
		values: (function(){
			var values = [];
			selects.each(function(){
				values.push( jQuery(this).get(0).selectedIndex );
			});
			return values;
		})()
	};
	
	//slider options from settings
	options.sliderOptions = (settings) ? jQuery.extend(sliderOptions, settings.sliderOptions) : sliderOptions;
		
	//select element change event	
	selects.bind('change keyup click', function(){
    var el = jQuery(this).get(0);
    var $el = jQuery(this);
    var elId = $el.attr('id');
    var elIdPos = elId.search(/min$/);

    if(elIdPos != -1) {
      var minValue = parseInt($el.val());
      var rawSelector = elId.slice(0, elIdPos);
      var maxValue = parseInt($('#' + rawSelector + 'max').val());
      if(minValue > maxValue) {
        $el.val(maxValue)
      }
    } else {
      elIdPos = elId.search(/max$/);
      
      if(elIdPos != -1) {
        var maxValue = parseInt($el.val());
        var rawSelector = elId.slice(0, elIdPos);
        var minValue = parseInt($('#' + rawSelector + 'min').val());
        if(minValue > maxValue) {
          $el.val(minValue);
        }
      }
    }

    var thisIndex = el.selectedIndex;
    var thisHandle = jQuery('#handle_'+ jQuery(this).attr('id'));
    var handleIndex = thisHandle.data('handleNum');
    thisHandle.parents('.ui-slider:eq(0)').slider("values", handleIndex, thisIndex);
	});

	//create slider component div
	var sliderComponent = jQuery('<div></div>');

	//CREATE HANDLES
	selects.each(function(i){
		var hidett = '';
		
		//associate label for ARIA
		var thisLabel = jQuery('label[for=' + jQuery(this).attr('id') +']');
		//labelled by aria doesn't seem to work on slider handle. Using title attr as backup
		var labelText = (thisLabel.size()>0) ? 'Slider control for '+ thisLabel.text()+'' : '';
		var thisLabelId = thisLabel.attr('id') || thisLabel.attr('id', 'label_'+handleIds[i]).attr('id');
		
		
		if( options.tooltip == false ){hidett = ' style="display: none;"';}
		jQuery('<a '+
				'href="#" tabindex="0" '+
				'id="'+handleIds[i]+'" '+
				'class="ui-slider-handle" '+
				'role="slider" '+
				'aria-labelledby="'+thisLabelId+'" '+
				'aria-valuemin="'+options.sliderOptions.min+'" '+
				'aria-valuemax="'+options.sliderOptions.max+'" '+
				'aria-valuenow="'+options.sliderOptions.values[i]+'" '+
				'aria-valuetext="'+ttText(options.sliderOptions.values[i])+'" '+
			'><span class="screenReaderContext">'+labelText+'</span>'+
			'<span class="ui-slider-tooltip ui-widget-content ui-corner-all"'+ hidett +'><span class="ttContent"></span>'+
				'<span class="ui-tooltip-pointer-down ui-widget-content"><span class="ui-tooltip-pointer-down-inner"></span></span>'+
			'</span></a>')
			.data('handleNum',i)
			.appendTo(sliderComponent);
	});

	//CREATE SCALE AND TICS

	//write dl if there are optgroups
	if(groups) {
		var inc = 0;
		var scale = sliderComponent.append('<dl class="ui-slider-scale ui-helper-reset" role="presentation"></dl>').find('.ui-slider-scale:eq(0)');
		jQuery(groups).each(function(h){
			scale.append('<dt style="width: '+ (100/groups.length).toFixed(2) +'%' +'; left:'+ (h/(groups.length-1) * 100).toFixed(2)  +'%' +'"><span>'+this.label+'</span></dt>');//class name becomes camelCased label
			var groupOpts = this.options;
			jQuery(this.options).each(function(i){
				var style = (inc == selectOptions.length-1 || inc == 0) ? 'style="display: none;"' : '' ;
				var labelText = (options.labelSrc == 'text') ? groupOpts[i].text : groupOpts[i].value;
				scale.append('<dd style="left:'+ leftVal(inc) +'"><span class="ui-slider-label">'+ labelText +'</span><span class="ui-slider-tic ui-widget-content"'+ style +'></span></dd>');
				inc++;
			});
		});
	}
	//write ol
	else {
		var scale = sliderComponent.append('<ol class="ui-slider-scale ui-helper-reset" role="presentation"></ol>').find('.ui-slider-scale:eq(0)');
		jQuery(selectOptions).each(function(i){
			var style = (i == selectOptions.length-1 || i == 0) ? 'style="display: none;"' : '' ;
			var labelText = (options.labelSrc == 'text') ? this.text : this.value;
			scale.append('<li style="left:'+ leftVal(i) +'"><span class="ui-slider-label">'+ labelText +'</span><span class="ui-slider-tic ui-widget-content"'+ style +'></span></li>');
		});
	}

	function leftVal(i){
		return (i/(selectOptions.length-1) * 100).toFixed(2)  +'%';
		
	}

	//show and hide labels depending on labels pref
	//show the last one if there are more than 1 specified
	if(options.labels > 1) sliderComponent.find('.ui-slider-scale li:last span.ui-slider-label, .ui-slider-scale dd:last span.ui-slider-label').addClass('ui-slider-label-show');

	//set increment
	var increm = Math.max(1, Math.round(selectOptions.length / options.labels));
	//show em based on inc
	for(var j=0; j<selectOptions.length; j+=increm){
		if((selectOptions.length - j) > increm){//don't show if it's too close to the end label
			sliderComponent.find('.ui-slider-scale li:eq('+ j +') span.ui-slider-label, .ui-slider-scale dd:eq('+ j +') span.ui-slider-label').addClass('ui-slider-label-show');
		}
	}

	//style the dt's
	sliderComponent.find('.ui-slider-scale dt').each(function(i){
		jQuery(this).css({
			'left': ((100 /( groups.length))*i).toFixed(2) + '%'
		});
	});

	//inject and return 
	sliderComponent
	.insertAfter(jQuery(this).eq(this.length-1))
	.slider(options.sliderOptions)
	.attr('role','application')
	.find('.ui-slider-label')
	.each(function(){
		jQuery(this).css('marginLeft', -jQuery(this).width()/2);
	});

	//update tooltip arrow inner color
	sliderComponent.find('.ui-tooltip-pointer-down-inner').each(function(){
				var bWidth = jQuery('.ui-tooltip-pointer-down-inner').css('borderTopWidth');
				var bColor = jQuery(this).parents('.ui-slider-tooltip').css('backgroundColor')
				jQuery(this).css('border-top', bWidth+' solid '+bColor);
	});

	var values = sliderComponent.slider('values');

	if(isArray(values)){
		jQuery(values).each(function(i){
			sliderComponent.find('.ui-slider-tooltip .ttContent').eq(i).text( ttText(this) );
		});
	}
	else {
		sliderComponent.find('.ui-slider-tooltip .ttContent').eq(0).text( ttText(values) );
	}

	return this;
}
/*	SWFObject v2.2 <http://code.google.com/p/swfobject/> 
	is released under the MIT License <http://www.opensource.org/licenses/mit-license.php> 
*/

var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="ShockwaveFlash.ShockwaveFlash",q="application/x-shockwave-flash",R="SWFObjectExprInst",x="onreadystatechange",O=window,j=document,t=navigator,T=false,U=[h],o=[],N=[],I=[],l,Q,E,B,J=false,a=false,n,G,m=true,M=function(){var aa=typeof j.getElementById!=D&&typeof j.getElementsByTagName!=D&&typeof j.createElement!=D,ah=t.userAgent.toLowerCase(),Y=t.platform.toLowerCase(),ae=Y?/win/.test(Y):/win/.test(ah),ac=Y?/mac/.test(Y):/mac/.test(ah),af=/webkit/.test(ah)?parseFloat(ah.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,X=!+"\v1",ag=[0,0,0],ab=null;if(typeof t.plugins!=D&&typeof t.plugins[S]==r){ab=t.plugins[S].description;if(ab&&!(typeof t.mimeTypes!=D&&t.mimeTypes[q]&&!t.mimeTypes[q].enabledPlugin)){T=true;X=false;ab=ab.replace(/^.*\s+(\S+\s+\S+$)/,"$1");ag[0]=parseInt(ab.replace(/^(.*)\..*$/,"$1"),10);ag[1]=parseInt(ab.replace(/^.*\.(.*)\s.*$/,"$1"),10);ag[2]=/[a-zA-Z]/.test(ab)?parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0}}else{if(typeof O.ActiveXObject!=D){try{var ad=new ActiveXObject(W);if(ad){ab=ad.GetVariable("$version");if(ab){X=true;ab=ab.split(" ")[1].split(",");ag=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}}catch(Z){}}}return{w3:aa,pv:ag,wk:af,ie:X,win:ae,mac:ac}}(),k=function(){if(!M.w3){return}if((typeof j.readyState!=D&&j.readyState=="complete")||(typeof j.readyState==D&&(j.getElementsByTagName("body")[0]||j.body))){f()}if(!J){if(typeof j.addEventListener!=D){j.addEventListener("DOMContentLoaded",f,false)}if(M.ie&&M.win){j.attachEvent(x,function(){if(j.readyState=="complete"){j.detachEvent(x,arguments.callee);f()}});if(O==top){(function(){if(J){return}try{j.documentElement.doScroll("left")}catch(X){setTimeout(arguments.callee,0);return}f()})()}}if(M.wk){(function(){if(J){return}if(!/loaded|complete/.test(j.readyState)){setTimeout(arguments.callee,0);return}f()})()}s(f)}}();function f(){if(J){return}try{var Z=j.getElementsByTagName("body")[0].appendChild(C("span"));Z.parentNode.removeChild(Z)}catch(aa){return}J=true;var X=U.length;for(var Y=0;Y<X;Y++){U[Y]()}}function K(X){if(J){X()}else{U[U.length]=X}}function s(Y){if(typeof O.addEventListener!=D){O.addEventListener("load",Y,false)}else{if(typeof j.addEventListener!=D){j.addEventListener("load",Y,false)}else{if(typeof O.attachEvent!=D){i(O,"onload",Y)}else{if(typeof O.onload=="function"){var X=O.onload;O.onload=function(){X();Y()}}else{O.onload=Y}}}}}function h(){if(T){V()}else{H()}}function V(){var X=j.getElementsByTagName("body")[0];var aa=C(r);aa.setAttribute("type",q);var Z=X.appendChild(aa);if(Z){var Y=0;(function(){if(typeof Z.GetVariable!=D){var ab=Z.GetVariable("$version");if(ab){ab=ab.split(" ")[1].split(",");M.pv=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}else{if(Y<10){Y++;setTimeout(arguments.callee,10);return}}X.removeChild(aa);Z=null;H()})()}else{H()}}function H(){var ag=o.length;if(ag>0){for(var af=0;af<ag;af++){var Y=o[af].id;var ab=o[af].callbackFn;var aa={success:false,id:Y};if(M.pv[0]>0){var ae=c(Y);if(ae){if(F(o[af].swfVersion)&&!(M.wk&&M.wk<312)){w(Y,true);if(ab){aa.success=true;aa.ref=z(Y);ab(aa)}}else{if(o[af].expressInstall&&A()){var ai={};ai.data=o[af].expressInstall;ai.width=ae.getAttribute("width")||"0";ai.height=ae.getAttribute("height")||"0";if(ae.getAttribute("class")){ai.styleclass=ae.getAttribute("class")}if(ae.getAttribute("align")){ai.align=ae.getAttribute("align")}var ah={};var X=ae.getElementsByTagName("param");var ac=X.length;for(var ad=0;ad<ac;ad++){if(X[ad].getAttribute("name").toLowerCase()!="movie"){ah[X[ad].getAttribute("name")]=X[ad].getAttribute("value")}}P(ai,ah,Y,ab)}else{p(ae);if(ab){ab(aa)}}}}}else{w(Y,true);if(ab){var Z=z(Y);if(Z&&typeof Z.SetVariable!=D){aa.success=true;aa.ref=Z}ab(aa)}}}}}function z(aa){var X=null;var Y=c(aa);if(Y&&Y.nodeName=="OBJECT"){if(typeof Y.SetVariable!=D){X=Y}else{var Z=Y.getElementsByTagName(r)[0];if(Z){X=Z}}}return X}function A(){return !a&&F("6.0.65")&&(M.win||M.mac)&&!(M.wk&&M.wk<312)}function P(aa,ab,X,Z){a=true;E=Z||null;B={success:false,id:X};var ae=c(X);if(ae){if(ae.nodeName=="OBJECT"){l=g(ae);Q=null}else{l=ae;Q=X}aa.id=R;if(typeof aa.width==D||(!/%$/.test(aa.width)&&parseInt(aa.width,10)<310)){aa.width="310"}if(typeof aa.height==D||(!/%$/.test(aa.height)&&parseInt(aa.height,10)<137)){aa.height="137"}j.title=j.title.slice(0,47)+" - Flash Player Installation";var ad=M.ie&&M.win?"ActiveX":"PlugIn",ac="MMredirectURL="+O.location.toString().replace(/&/g,"%26")+"&MMplayerType="+ad+"&MMdoctitle="+j.title;if(typeof ab.flashvars!=D){ab.flashvars+="&"+ac}else{ab.flashvars=ac}if(M.ie&&M.win&&ae.readyState!=4){var Y=C("div");X+="SWFObjectNew";Y.setAttribute("id",X);ae.parentNode.insertBefore(Y,ae);ae.style.display="none";(function(){if(ae.readyState==4){ae.parentNode.removeChild(ae)}else{setTimeout(arguments.callee,10)}})()}u(aa,ab,X)}}function p(Y){if(M.ie&&M.win&&Y.readyState!=4){var X=C("div");Y.parentNode.insertBefore(X,Y);X.parentNode.replaceChild(g(Y),X);Y.style.display="none";(function(){if(Y.readyState==4){Y.parentNode.removeChild(Y)}else{setTimeout(arguments.callee,10)}})()}else{Y.parentNode.replaceChild(g(Y),Y)}}function g(ab){var aa=C("div");if(M.win&&M.ie){aa.innerHTML=ab.innerHTML}else{var Y=ab.getElementsByTagName(r)[0];if(Y){var ad=Y.childNodes;if(ad){var X=ad.length;for(var Z=0;Z<X;Z++){if(!(ad[Z].nodeType==1&&ad[Z].nodeName=="PARAM")&&!(ad[Z].nodeType==8)){aa.appendChild(ad[Z].cloneNode(true))}}}}}return aa}function u(ai,ag,Y){var X,aa=c(Y);if(M.wk&&M.wk<312){return X}if(aa){if(typeof ai.id==D){ai.id=Y}if(M.ie&&M.win){var ah="";for(var ae in ai){if(ai[ae]!=Object.prototype[ae]){if(ae.toLowerCase()=="data"){ag.movie=ai[ae]}else{if(ae.toLowerCase()=="styleclass"){ah+=' class="'+ai[ae]+'"'}else{if(ae.toLowerCase()!="classid"){ah+=" "+ae+'="'+ai[ae]+'"'}}}}}var af="";for(var ad in ag){if(ag[ad]!=Object.prototype[ad]){af+='<param name="'+ad+'" value="'+ag[ad]+'" />'}}aa.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+ah+">"+af+"</object>";N[N.length]=ai.id;X=c(ai.id)}else{var Z=C(r);Z.setAttribute("type",q);for(var ac in ai){if(ai[ac]!=Object.prototype[ac]){if(ac.toLowerCase()=="styleclass"){Z.setAttribute("class",ai[ac])}else{if(ac.toLowerCase()!="classid"){Z.setAttribute(ac,ai[ac])}}}}for(var ab in ag){if(ag[ab]!=Object.prototype[ab]&&ab.toLowerCase()!="movie"){e(Z,ab,ag[ab])}}aa.parentNode.replaceChild(Z,aa);X=Z}}return X}function e(Z,X,Y){var aa=C("param");aa.setAttribute("name",X);aa.setAttribute("value",Y);Z.appendChild(aa)}function y(Y){var X=c(Y);if(X&&X.nodeName=="OBJECT"){if(M.ie&&M.win){X.style.display="none";(function(){if(X.readyState==4){b(Y)}else{setTimeout(arguments.callee,10)}})()}else{X.parentNode.removeChild(X)}}}function b(Z){var Y=c(Z);if(Y){for(var X in Y){if(typeof Y[X]=="function"){Y[X]=null}}Y.parentNode.removeChild(Y)}}function c(Z){var X=null;try{X=j.getElementById(Z)}catch(Y){}return X}function C(X){return j.createElement(X)}function i(Z,X,Y){Z.attachEvent(X,Y);I[I.length]=[Z,X,Y]}function F(Z){var Y=M.pv,X=Z.split(".");X[0]=parseInt(X[0],10);X[1]=parseInt(X[1],10)||0;X[2]=parseInt(X[2],10)||0;return(Y[0]>X[0]||(Y[0]==X[0]&&Y[1]>X[1])||(Y[0]==X[0]&&Y[1]==X[1]&&Y[2]>=X[2]))?true:false}function v(ac,Y,ad,ab){if(M.ie&&M.mac){return}var aa=j.getElementsByTagName("head")[0];if(!aa){return}var X=(ad&&typeof ad=="string")?ad:"screen";if(ab){n=null;G=null}if(!n||G!=X){var Z=C("style");Z.setAttribute("type","text/css");Z.setAttribute("media",X);n=aa.appendChild(Z);if(M.ie&&M.win&&typeof j.styleSheets!=D&&j.styleSheets.length>0){n=j.styleSheets[j.styleSheets.length-1]}G=X}if(M.ie&&M.win){if(n&&typeof n.addRule==r){n.addRule(ac,Y)}}else{if(n&&typeof j.createTextNode!=D){n.appendChild(j.createTextNode(ac+" {"+Y+"}"))}}}function w(Z,X){if(!m){return}var Y=X?"visible":"hidden";if(J&&c(Z)){c(Z).style.visibility=Y}else{v("#"+Z,"visibility:"+Y)}}function L(Y){var Z=/[\\\"<>\.;]/;var X=Z.exec(Y)!=null;return X&&typeof encodeURIComponent!=D?encodeURIComponent(Y):Y}var d=function(){if(M.ie&&M.win){window.attachEvent("onunload",function(){var ac=I.length;for(var ab=0;ab<ac;ab++){I[ab][0].detachEvent(I[ab][1],I[ab][2])}var Z=N.length;for(var aa=0;aa<Z;aa++){y(N[aa])}for(var Y in M){M[Y]=null}M=null;for(var X in swfobject){swfobject[X]=null}swfobject=null})}}();return{registerObject:function(ab,X,aa,Z){if(M.w3&&ab&&X){var Y={};Y.id=ab;Y.swfVersion=X;Y.expressInstall=aa;Y.callbackFn=Z;o[o.length]=Y;w(ab,false)}else{if(Z){Z({success:false,id:ab})}}},getObjectById:function(X){if(M.w3){return z(X)}},embedSWF:function(ab,ah,ae,ag,Y,aa,Z,ad,af,ac){var X={success:false,id:ah};if(M.w3&&!(M.wk&&M.wk<312)&&ab&&ah&&ae&&ag&&Y){w(ah,false);K(function(){ae+="";ag+="";var aj={};if(af&&typeof af===r){for(var al in af){aj[al]=af[al]}}aj.data=ab;aj.width=ae;aj.height=ag;var am={};if(ad&&typeof ad===r){for(var ak in ad){am[ak]=ad[ak]}}if(Z&&typeof Z===r){for(var ai in Z){if(typeof am.flashvars!=D){am.flashvars+="&"+ai+"="+Z[ai]}else{am.flashvars=ai+"="+Z[ai]}}}if(F(Y)){var an=u(aj,am,ah);if(aj.id==ah){w(ah,true)}X.success=true;X.ref=an}else{if(aa&&A()){aj.data=aa;P(aj,am,ah,ac);return}else{w(ah,true)}}if(ac){ac(X)}})}else{if(ac){ac(X)}}},switchOffAutoHideShow:function(){m=false},ua:M,getFlashPlayerVersion:function(){return{major:M.pv[0],minor:M.pv[1],release:M.pv[2]}},hasFlashPlayerVersion:F,createSWF:function(Z,Y,X){if(M.w3){return u(Z,Y,X)}else{return undefined}},showExpressInstall:function(Z,aa,X,Y){if(M.w3&&A()){P(Z,aa,X,Y)}},removeSWF:function(X){if(M.w3){y(X)}},createCSS:function(aa,Z,Y,X){if(M.w3){v(aa,Z,Y,X)}},addDomLoadEvent:K,addLoadEvent:s,getQueryParamValue:function(aa){var Z=j.location.search||j.location.hash;if(Z){if(/\?/.test(Z)){Z=Z.split("?")[1]}if(aa==null){return L(Z)}var Y=Z.split("&");for(var X=0;X<Y.length;X++){if(Y[X].substring(0,Y[X].indexOf("="))==aa){return L(Y[X].substring((Y[X].indexOf("=")+1)))}}}return""},expressInstallCallback:function(){if(a){var X=c(R);if(X&&l){X.parentNode.replaceChild(l,X);if(Q){w(Q,true);if(M.ie&&M.win){l.style.display="block"}}if(E){E(B)}}a=false}}}}();
(function($) {
	$.extend({
		placeholder : {
			settings : {
				focusClass: 'placeholderFocus',
				activeClass: 'placeholder',
				overrideSupport: false,
				preventRefreshIssues: true
			},
			debug : false,
			log : function(msg){
				if(!$.placeholder.debug) return;
				msg = "[Placeholder] " + msg;
				$.placeholder.hasFirebug ?
				console.log(msg) :
				$.placeholder.hasConsoleLog ?
					window.console.log(msg) :
					alert(msg);
			},
			hasFirebug : "console" in window && "firebug" in window.console,
			hasConsoleLog: "console" in window && "log" in window.console
		}

	});

    // check browser support for placeholder
    $.support.placeholder = 'placeholder' in document.createElement('input');

	// Replace the val function to never return placeholders
	$.fn.plVal = $.fn.val;
	$.fn.val = function(value) {
		$.placeholder.log('in val');
		if(this[0]) {
			$.placeholder.log('have found an element');
			var el = $(this[0]);
			if(value != undefined)
			{
				$.placeholder.log('in setter');
				var currentValue = el.plVal();
				var returnValue = $(this).plVal(value);
				if(el.hasClass($.placeholder.settings.activeClass) && currentValue == el.attr('placeholder')){
					el.removeClass($.placeholder.settings.activeClass);
				}
				return returnValue;
			}

			if(el.hasClass($.placeholder.settings.activeClass) && el.plVal() == el.attr('placeholder')) {
				$.placeholder.log('returning empty because it\'s a placeholder');
				return '';
			} else {
				$.placeholder.log('returning original val');
				return el.plVal();
			}
		}
		$.placeholder.log('returning undefined');
		return undefined;
	};

	// Clear placeholder values upon page reload
	$(window).bind('beforeunload.placeholder', function() {
		var els = $('input.' + $.placeholder.settings.activeClass);
		if(els.length > 0)
			els.val('').attr('autocomplete','off');
	});


    // plugin code
	$.fn.placeholder = function(opts) {
		opts = $.extend({},$.placeholder.settings, opts);

		// we don't have to do anything if the browser supports placeholder
		if(!opts.overrideSupport && $.support.placeholder)
		    return this;
			
        return this.each(function() {
            var $el = $(this);

            // skip if we do not have the placeholder attribute
            if(!$el.is('[placeholder]'))
                return;

            // we cannot do password fields, but supported browsers can
            if($el.is(':password'))
                return;
			
			// Prevent values from being reapplied on refresh
			if(opts.preventRefreshIssues)
				$el.attr('autocomplete','off');

            $el.bind('focus.placeholder', function(){
                var $el = $(this);
                if(this.value == $el.attr('placeholder') && $el.hasClass(opts.activeClass))
                    $el.val('')
                       .removeClass(opts.activeClass)
                       .addClass(opts.focusClass);
            });
            $el.bind('blur.placeholder', function(){
                var $el = $(this);
				
				$el.removeClass(opts.focusClass);

                if(this.value == '')
                  $el.val($el.attr('placeholder'))
                     .addClass(opts.activeClass);
            });

            $el.triggerHandler('blur');
			
			// Prevent incorrect form values being posted
			$el.parents('form').submit(function(){
				$el.triggerHandler('focus.placeholder');
			});

        });
    };
})(jQuery);
/*
 * --------------------------------------------------------------------
 * jQuery vzmenu plugin
 * Author: Volker Zöpfel (reklov) volker@zoepfel.de
 * --------------------------------------------------------------------
 */

$.fn.vzselect = function (settings) {

  return $(this).each(function () {
    //reference to this
    var selectElement = $(this);
    selectElement.hide();

    // anton: in order to get rails to empty the array if the user selects nothing, we need to prepend
    // an empty hidden field to have the browser submitting an empty value instead of nothing
    // see WARNING at http://guides.rubyonrails.org/form_helpers.html#combining-them
    var hiddenInputEmptifier = $('<input type="hidden" value="">');
    hiddenInputEmptifier.attr('name', selectElement.attr('name'));
    hiddenInputEmptifier.insertAfter(selectElement);

    //config
    var o = $.extend({
      maxElementsSelected: null,
      maxHeight: 300,
      addButtonText: 'add',
      addButtonTextNullSelect: 'please select',
      buttonType: 'span',
      format: function (text) {
        return text;
      }
    }, settings);

    //add role to body CHECK IF IT HAS A ROLE FIRST
    $('body').attr('role', 'application');

    //get select ID
    var selectElementId = selectElement.attr('id');

    //get all selected options
    var allOptionSelected = function () {
      var returnvalue = new Array();
      selectElement.find('option:selected')
      //convert option classes to array
      .map(function () {
        returnvalue.push($(this).val())
      });
      return returnvalue;
    };

    var selectOptionData = [];
    selectElement.find('option').each(function () {
      selectOptionData.push({
        value: $(this).attr('value'),
        text: $(this).text(),
        selected: $(this).attr('selected'),
        disabled: $(this).attr('disabled'),
        classes: $(this).attr('class'),
        typeahead: $(this).attr('typeahead'),
        parentOptGroup: $(this).parent('optgroup')
      });
    });

    var allOption = selectElement.find('option')
      //convert option classes to array
      .map(function () {
        return $(this).val();
      });
      
    var moveBefore = function($element, $insertPoint){
      $insertPoint.before($element.detach());
    };
    
    var allOptionClasses = selectElement.find('option')
      //convert option classes to array
      .map(function () {
        return $(this).attr('class')
      })
      //join array into string of classes separated by a space
      .get()
      .join(' ');
    
    var nothingSelectedButton = $('<button>' + o.addButtonTextNullSelect + '</button>')
      .attr('id', selectElementId + "-add-button")
      .addClass('vzselect-addbutton')
      .addClass('vzselect-hidden')
      .button({
        label: o.addButtonTextNullSelect
      })
      .insertBefore(selectElement)
      .bind('click', function (e) {
        e.preventDefault();
        menu.trigger('show', [$(this)]);
      });

    var addButton = this.addButton = {};
    addButton.buttonElement = $('<button>' + o.addButtonText + '</button>').attr('id', selectElementId + "-add-button");
    addButton.id = 'vzselect-' + selectElementId + "-add-button";
    addButton.buttonElement.addClass('vzselect-addbutton');
    addButton.buttonElement.button({
      label: o.addButtonText,
      icons: {
        secondary: "ui-icon-custom-new"
      }
    });

    addButton.buttonElement.find('.ui-icon')
      .removeClass('ui-icon')
      .addClass('ui-icon-custom');

    addButton.hideButton = function () {
      //this.buttonElement.hide();
      this.buttonElement.addClass('vzselect-hidden');
    };

    addButton.showButton = function () {
      if (allOption.length > allOptionSelected().length && (typeof(o.maxElementsSelected) == undefined || o.maxElementsSelected === null || allOptionSelected().length < o.maxElementsSelected)) {
        if(allOptionSelected().length == 0) {
          this.buttonElement.addClass('vzselect-hidden');
          nothingSelectedButton.removeClass('vzselect-hidden');
        }
        else {
          this.buttonElement.removeClass('vzselect-hidden');
          nothingSelectedButton.addClass('vzselect-hidden');
        }
      }
      else {
        //this.buttonElement.hide();
        this.buttonElement.addClass('vzselect-hidden');
      }
    };
    addButton.buttonElement.bind('click', function (e) {
      e.preventDefault();
      menu.trigger('show', [$(this)]);
    });
    //show add Button
    addButton.buttonElement.insertBefore(selectElement);

    var menuWidth;
    var createButtonset = function (index) {
      var initialSelectedIndex = index || selectElement[0].selectedIndex;
      var buttonName = selectElement.find('option').eq(initialSelectedIndex).text();
      var buttonValue = selectElement.find('option').eq(initialSelectedIndex).val();
      var $buttonset = $('<' + o.buttonType + ' class="vzselect-buttonset vzselect-buttonset-' + selectElementId + '"><button>' + buttonName + '</button><button>' + buttonName + '</button></' + o.buttonType +'>')
        .attr('id', 'vzselect-buttonset-' + selectElementId + '-' + initialSelectedIndex)
        .data('value', buttonValue).data('position', initialSelectedIndex)
        .find('button:first')
        .button({
          icons: {
            primary: "ui-icon-custom-remove"
          },
          text: false
        })
        .click(function(e) {
          e.preventDefault();
          menu.trigger('hide');
          $(this).parent().remove();
          $(selectElement.find("option")[index]).removeAttr("selected");
          selectElement.trigger('change');
          setMenuEntries();
          addButton.showButton();
        })
        .next().button({
          icons: {
            secondary: "ui-icon-custom-drop-down"
          },
          label: buttonName
        })
        .click(function(e) { // change selected option
          e.preventDefault();
          setMenuEntries();
          $(this).parent().addClass('vzselect-change-element');
          if (allOption.length > allOptionSelected().length) {
            menu.trigger('show', [$(this).parent()]);
          }
        })
        .css('width', menuWidth + 27)
        .parent().buttonset();
        
      $buttonset.find('.ui-icon')
        .removeClass('ui-icon')
        .addClass('ui-icon-custom');
        
      return $buttonset;
    }
    
    /* TODO: FIX THE INIT BUG HERE! */
    for (var i = 0; i < selectOptionData.length; i++) {  
      if (selectOptionData[i].selected == 'selected') {
        addButton.buttonElement.before(createButtonset(i));
      }
    };
    
    var buttons = $('.vzselect-' + selectElementId);

    var enableMenuEntry = function (li) {
      li.removeClass('vzselect-hidden');
      //li.show();
    };
    
    var disableMenuEntry = function (li) {
      //li.hide();
      li.addClass('vzselect-hidden');
    };
    
    var menu = $('<ul class="vzselect-menu" id="vzselect-' + selectElementId + '-menu" role="listbox" aria-labelledby="' + selectElementId + '-button"></ul>');

    var createMenuEntries = function () {
      //find all option elements in selectElement
      selectElement.find('option').each(function (index) {
        //create li with option's text and class attribute
        var li = $('<li class="' + $(this).attr('class') + '" id="vzselect-' + selectElementId + '-menu-item-' + $(this).val() + '"><a href="#' + index + '" tabindex="-1" role="option" >' + o.format($(this).text()) + '</a></li>');
        li.appendTo(menu);
      });
    };

    var setMenuEntries = function () {
      selectElement.find('option')
      //iterate through each option element, tracking the index
      .each(function (index) {
        if ($(this).attr('selected')) {
          var li = menu.find('li').get(index);
          //$(li).hide();
          $(li).addClass('vzselect-hidden');
        }
        else {
          var li = menu.find('li').get(index);
          //$(li).show();
          $(li).removeClass('vzselect-hidden');
        }
      })
    };
    
    createMenuEntries();
    setMenuEntries();
    //append menu to end of page (still visual)	
    menu.appendTo('body');
    
    menuWidth = menu.find('li a').first().width() + 10;
    menu.find('li a').each(function(idx, el) {
      $(el).css('width', menuWidth);
    });
    
    //set height of menu, if needed for overflow 
    if (menu.outerHeight() > o.maxHeight) {
      menu.height(o.maxHeight);
    }

    //hide menu
    //menu.hide();
    menu.addClass('vzselect-hidden');

    //EVENTS
    //custom show event
    menu.bind('show', function (event, s) {
      button = $(s);
      var $this = $(this);
      $this.appendTo('body');
      $this.unbind('mouseenter');
      $this.bind('mouseenter', function () {
        $this.unbind('mouseleave');
        $this.bind('mouseleave', function () {
          menu.trigger('hide');
        });
      });
      // not really sure what (the very, very outdated) jquery.dimension does
      // only offsetLite gets the correct coords in IE, don't know what it does in other browsers
      leftOffset = button.offsetLite().left
//    // use this if you get problems with select menu positioning in non-IE Browsers:
      //  leftOffset = ($.browser.msie && typeof(button.offsetLite) == 'function') ? button.offsetLite().left : button.offset().left
      $this.css({
        top: button.offset().top + button.height() + 5,
        left: leftOffset
      });
      if(button.hasClass('vzselect-addbutton')) {
        $this.addClass('vzselect-new');
        $this.removeClass('vzselect-old');
      } else {
        $this.addClass('vzselect-old');
        $this.removeClass('vzselect-new')
      }
      $this.removeClass('vzselect-hidden');
      //$this.show();
    });

    menu.bind('focusout', function () {
      //$(this).hide();
      $(this).addClass('vzselect-hidden');
      addButton.showButton();
    });

    //custom hide event
    menu.bind('hide', function (event) {
      buttons.removeClass('vzselect-change-element');
      var $this = $(this);
      $this.unbind('mouseleave');
      $this.unbind('mouseenter');
      $this.addClass('vzselect-hidden');
      //$this.hide();
    });

    //event to update select menu with current selection (proxy to select)
    /* TODO: FIX BUG HERE! */
    menu.find('a').bind('select', function () {
      var selectedId = menu.find('li').index($(this).parent('li'));
      menu.addClass('vzselect-hidden');
      if($('.vzselect-buttonset-' + selectElementId + '.vzselect-change-element').length > 0) {
        var buttonId = $('.vzselect-buttonset-' + selectElementId + '.vzselect-change-element').first().attr('id').replace('vzselect-buttonset-' + selectElementId + '-', '');
        $(selectElement.find("option")[buttonId]).removeAttr("selected");
        selectElement.trigger('change')
      }
      disableMenuEntry($(this).parent('li'));
      //addSelection(menu.find('a').index(this))
      addSelection(selectedId);
      var buttonSet = createButtonset(selectedId);
      //if element changed insert it at the same position
      //otherwise (in case it is new) add it to the end
      if ($('.vzselect-change-element').index() >= 0) {
        $('.vzselect-change-element').after(buttonSet);
      } else {
        addButton.buttonElement.before(buttonSet);
      }
      //remove all .vzselect-change-element to clean up
      $('.vzselect-change-element').remove();
      addButton.showButton();
    });

    var addSelection = function (index) {
      var newValue = allOptionSelected();
      selection = allOption[index];
      newValue.push(selection);
      selectElement.find("[value='" + selection + "']").attr('selected', 'selected');
      selectElement.val(newValue);
      selectElement.trigger('change');
    };

    //specific events
    //apply click to button	
    buttons.mousedown(function () {
      menu.trigger('toggle', $(this));
      return false;
    });

    //disable click event (use mousedown/up instead)
    buttons.click(function () {
      return false;
    });

    //apply mouseup event to menu, for making selections	
    //allows us to drag and release
    menu.find('a').mouseup(function (event) {
      $(this).trigger('select');
      //prevent browser scroll
      return false;
    });

    //hover and focus states
    menu.find('a').bind('mouseover focus', function () {
      //remove class from previous hover-focused option
      menu
        .find('.hover-focus')
        .removeClass('hover-focus');
      //add class to this option
      $(this).parent().addClass('hover-focus');
    })
    .bind('mouseout blur', function () {
      //remove class from this option
      $(this).parent().removeClass('hover-focus');
    });

    selectElement.data('selectmenu', menu);
    // show add Button
    addButton.showButton();
    //hide native select
    //selectElement.addClass('vzselect-hidden').attr('aria-hidden', true);
  });
};
 // STYLING FILE INPUTS 1.0 | Shaun Inman <http://www.shauninman.com/> | 2007-09-07
 if (!window.SI) { var SI = {}; };
 SI.Files =
 {
  htmlClass : 'SI-FILES-STYLIZED',
  fileClass : 'file',
  wrapClass : 'cabinet',
  
  fini : false,
  able : false,
  init : function()
  {
    this.fini = true;
    
    var ie = 0 //@cc_on + @_jscript_version
    if (window.opera || (ie && ie < 5.5) || !document.getElementsByTagName) { return; } // no support for opacity or the DOM
    this.able = true;
    
    var html = document.getElementsByTagName('html')[0];
    html.className += (html.className != '' ? ' ' : '') + this.htmlClass;
  },
  
  stylize : function(elem)
  {
    if (!this.fini) { this.init(); };
    if (!this.able) { return; };
    
    elem.parentNode.file = elem;
    elem.parentNode.onmousemove = function(e)
    {
      if (typeof e == 'undefined') e = window.event;
      if (typeof e.pageY == 'undefined' &&  typeof e.clientX == 'number' && document.documentElement)
      {
        e.pageX = e.clientX + document.documentElement.scrollLeft;
        e.pageY = e.clientY + document.documentElement.scrollTop;
      };
 
      var ox = oy = 0;
      var elem = this;
      if (elem.offsetParent)
      {
        ox = elem.offsetLeft;
        oy = elem.offsetTop;
        while (elem = elem.offsetParent)
        {
          ox += elem.offsetLeft;
          oy += elem.offsetTop;
        };
      };
 
      var x = e.pageX - ox;
      var y = e.pageY - oy;
      var w = this.file.offsetWidth;
      var h = this.file.offsetHeight;
 
      this.file.style.top   = y - (h / 2)  + 'px';
      this.file.style.left  = x - (w - 30) + 'px';
    };
  },
  
  stylizeById : function(id)
  {
    this.stylize(document.getElementById(id));
  },
  
  stylizeAll : function()
  {
    if (!this.fini) { this.init(); };
    if (!this.able) { return; };
    
    var inputs = document.getElementsByTagName('input');
    for (var i = 0; i < inputs.length; i++)
    {
      var input = inputs[i];
      if (input.type == 'file' && input.className.indexOf(this.fileClass) != -1 && input.parentNode.className.indexOf(this.wrapClass) != -1)
      {
        this.stylize(input);
      };
    };
  }
 };
/* Copyright (c) 2006 Brandon Aaron (http://brandonaaron.net)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * $LastChangedDate: 2007-06-20 03:23:36 +0200 (Mi, 20 Jun 2007) $
 * $Rev: 2110 $
 *
 * Version 2.1
 */


(function($){

/**
 * The bgiframe is chainable and applies the iframe hack to get 
 * around zIndex issues in IE6. It will only apply itself in IE 
 * and adds a class to the iframe called 'bgiframe'. The iframe
 * is appeneded as the first child of the matched element(s) 
 * with a tabIndex and zIndex of -1.
 * 
 * By default the plugin will take borders, sized with pixel units,
 * into account. If a different unit is used for the border's width,
 * then you will need to use the top and left settings as explained below.
 *
 * NOTICE: This plugin has been reported to cause perfromance problems
 * when used on elements that change properties (like width, height and
 * opacity) a lot in IE6. Most of these problems have been caused by 
 * the expressions used to calculate the elements width, height and 
 * borders. Some have reported it is due to the opacity filter. All 
 * these settings can be changed if needed as explained below.
 *
 * @example $('div').bgiframe();
 * @before <div><p>Paragraph</p></div>
 * @result <div><iframe class="bgiframe".../><p>Paragraph</p></div>
 *
 * @param Map settings Optional settings to configure the iframe.
 * @option String|Number top The iframe must be offset to the top
 * 		by the width of the top border. This should be a negative 
 *      number representing the border-top-width. If a number is 
 * 		is used here, pixels will be assumed. Otherwise, be sure
 *		to specify a unit. An expression could also be used. 
 * 		By default the value is "auto" which will use an expression 
 * 		to get the border-top-width if it is in pixels.
 * @option String|Number left The iframe must be offset to the left
 * 		by the width of the left border. This should be a negative 
 *      number representing the border-left-width. If a number is 
 * 		is used here, pixels will be assumed. Otherwise, be sure
 *		to specify a unit. An expression could also be used. 
 * 		By default the value is "auto" which will use an expression 
 * 		to get the border-left-width if it is in pixels.
 * @option String|Number width This is the width of the iframe. If
 *		a number is used here, pixels will be assume. Otherwise, be sure
 * 		to specify a unit. An experssion could also be used.
 *		By default the value is "auto" which will use an experssion
 * 		to get the offsetWidth.
 * @option String|Number height This is the height of the iframe. If
 *		a number is used here, pixels will be assume. Otherwise, be sure
 * 		to specify a unit. An experssion could also be used.
 *		By default the value is "auto" which will use an experssion
 * 		to get the offsetHeight.
 * @option Boolean opacity This is a boolean representing whether or not
 * 		to use opacity. If set to true, the opacity of 0 is applied. If
 *		set to false, the opacity filter is not applied. Default: true.
 * @option String src This setting is provided so that one could change 
 *		the src of the iframe to whatever they need.
 *		Default: "javascript:false;"
 *
 * @name bgiframe
 * @type jQuery
 * @cat Plugins/bgiframe
 * @author Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
 */
$.fn.bgIframe = $.fn.bgiframe = function(s) {
	// This is only for IE6
	if ( $.browser.msie && parseInt($.browser.version) <= 6 ) {
		s = $.extend({
			top     : 'auto', // auto == .currentStyle.borderTopWidth
			left    : 'auto', // auto == .currentStyle.borderLeftWidth
			width   : 'auto', // auto == offsetWidth
			height  : 'auto', // auto == offsetHeight
			opacity : true,
			src     : 'javascript:false;'
		}, s || {});
		var prop = function(n){return n&&n.constructor==Number?n+'px':n;},
		    html = '<iframe class="bgiframe"frameborder="0"tabindex="-1"src="'+s.src+'"'+
		               'style="display:block;position:absolute;z-index:-1;'+
			               (s.opacity !== false?'filter:Alpha(Opacity=\'0\');':'')+
					       'top:'+(s.top=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderTopWidth)||0)*-1)+\'px\')':prop(s.top))+';'+
					       'left:'+(s.left=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderLeftWidth)||0)*-1)+\'px\')':prop(s.left))+';'+
					       'width:'+(s.width=='auto'?'expression(this.parentNode.offsetWidth+\'px\')':prop(s.width))+';'+
					       'height:'+(s.height=='auto'?'expression(this.parentNode.offsetHeight+\'px\')':prop(s.height))+';'+
					'"/>';
		return this.each(function() {
			if ( $('> iframe.bgiframe', this).length == 0 )
				this.insertBefore( document.createElement(html), this.firstChild );
		});
	}
	return this;
};

// Add browser.version if it doesn't exist
if (!$.browser.version)
	$.browser.version = navigator.userAgent.toLowerCase().match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)[1];

})(jQuery);
/*
 * jQuery tooltip_2 plugin 1.3
 *
 * http://bassistance.de/jquery-plugins/jquery-plugin-tooltip_2/
 * http://docs.jquery.com/Plugins/tooltip_2
 *
 * Copyright (c) 2006 - 2008 Jörn Zaefferer
 *
 * $Id: jquery.tooltip_2.js 5741 2008-06-21 15:22:16Z joern.zaefferer $
 * 
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 */

 
(function($) {
	
		// the tooltip_2 element
	var helper = {},
		// the current tooltip_2ped element
		current,
		// the title of the current element, used for restoring
		title,
		// timeout id for delayed tooltip_2s
		tID,
		// IE 5.5 or 6
		IE = $.browser.msie && /MSIE\s(5\.5|6\.)/.test(navigator.userAgent),
		// flag for mouse tracking
		track = false;
	
	$.tooltip_2 = {
		blocked: false,
		defaults: {
			delay: 200,
			fade: false,
			showURL: true,
			extraClass: "",
			top: 15,
			left: 15,
			id: "tooltip_2"
		},
		block: function() {
			$.tooltip_2.blocked = !$.tooltip_2.blocked;
		}
	};
	
	$.fn.extend({
		tooltip_2: function(settings) {
			settings = $.extend({}, $.tooltip_2.defaults, settings);
			createHelper(settings);
			return this.each(function() {
					$.data(this, "tooltip_2", settings);
					this.tOpacity = helper.parent.css("opacity");
					// copy tooltip_2 into its own expando and remove the title
					this.tooltip_2Text = this.title;
					$(this).removeAttr("title");
					// also remove alt attribute to prevent default tooltip_2 in IE
					this.alt = "";
				})
				.mouseover(save)
				.mouseout(hide)
				.click(hide);
		},
		fixPNG: IE ? function() {
			return this.each(function () {
				var image = $(this).css('backgroundImage');
				if (image.match(/^url\(["']?(.*\.png)["']?\)$/i)) {
					image = RegExp.$1;
					$(this).css({
						'backgroundImage': 'none',
						'filter': "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='" + image + "')"
					}).each(function () {
						var position = $(this).css('position');
						if (position != 'absolute' && position != 'relative')
							$(this).css('position', 'relative');
					});
				}
			});
		} : function() { return this; },
		unfixPNG: IE ? function() {
			return this.each(function () {
				$(this).css({'filter': '', backgroundImage: ''});
			});
		} : function() { return this; },
		hideWhenEmpty: function() {
			return this.each(function() {
				$(this)[ $(this).html() ? "show" : "hide" ]();
			});
		},
		url: function() {
			return this.attr('href') || this.attr('src');
		}
	});
	
	function createHelper(settings) {
		// there can be only one tooltip_2 helper
		if( helper.parent )
			return;
		// create the helper, h3 for title, div for url
		helper.parent = $('<div id="' + settings.id + '"><h1></h1><div class="body"></div><div class="url"></div></div>')
			// add to document
			.appendTo(document.body)
			// hide it at first
			.hide();
			
		// apply bgiframe if available
		if ( $.fn.bgiframe )
			helper.parent.bgiframe();
		
		// save references to title and url elements
		helper.title = $('h1', helper.parent);
		helper.body = $('div.body', helper.parent);
		helper.url = $('div.url', helper.parent);
	}
	
	function settings(element) {
		return $.data(element, "tooltip_2");
	}
	
	// main event handler to start showing tooltip_2s
	function handle(event) {
		// show helper, either with timeout or on instant
		if( settings(this).delay )
			tID = setTimeout(show, settings(this).delay);
		else
			show();
		
		// if selected, update the helper position when the mouse moves
		track = !!settings(this).track;
		$(document.body).bind('mousemove', update);
			
		// update at least once
		update(event);
	}
	
	// save elements title before the tooltip_2 is displayed
	function save() {
		// if this is the current source, or it has no title (occurs with click event), stop
		if ( $.tooltip_2.blocked || this == current || (!this.tooltip_2Text && !settings(this).bodyHandler) )
			return;

		// save current
		current = this;
		title = this.tooltip_2Text;
		
		if ( settings(this).bodyHandler ) {
			helper.title.hide();
			var bodyContent = settings(this).bodyHandler.call(this);
			if (bodyContent.nodeType || bodyContent.jquery) {
				helper.body.empty().append(bodyContent)
			} else {
				helper.body.html( bodyContent );
			}
			helper.body.show();
		} else if ( settings(this).showBody ) {
			var parts = title.split(settings(this).showBody);
			helper.title.html(parts.shift()).show();
			helper.body.empty();
			for(var i = 0, part; (part = parts[i]); i++) {
				if(i > 0)
					helper.body.append("<br/>");
				helper.body.append(part);
			}
			helper.body.hideWhenEmpty();
		} else {
			helper.title.html(title).show();
			helper.body.hide();
		}
		
		// if element has href or src, add and show it, otherwise hide it
		if( settings(this).showURL && $(this).url() )
			helper.url.html( $(this).url().replace('http://', '') ).show();
		else 
			helper.url.hide();
		
		// add an optional class for this tip
		helper.parent.addClass(settings(this).extraClass);

		// fix PNG background for IE
		if (settings(this).fixPNG )
			helper.parent.fixPNG();
			
		handle.apply(this, arguments);
	}
	
	// delete timeout and show helper
	function show() {
		tID = null;
		if ((!IE || !$.fn.bgiframe) && settings(current).fade) {
			if (helper.parent.is(":animated"))
				helper.parent.stop().show().fadeTo(settings(current).fade, current.tOpacity);
			else
				helper.parent.is(':visible') ? helper.parent.fadeTo(settings(current).fade, current.tOpacity) : helper.parent.fadeIn(settings(current).fade);
		} else {
			helper.parent.show();
		}
		update();
	}
	
	/**
	 * callback for mousemove
	 * updates the helper position
	 * removes itself when no current element
	 */
	function update(event)	{
		if($.tooltip_2.blocked)
			return;
		
		if (event && event.target.tagName == "OPTION") {
			return;
		}
		
		// stop updating when tracking is disabled and the tooltip_2 is visible
		if ( !track && helper.parent.is(":visible")) {
			$(document.body).unbind('mousemove', update)
		}
		
		// if no current element is available, remove this listener
		if( current == null ) {
			$(document.body).unbind('mousemove', update);
			return;	
		}
		
		// remove position helper classes
		helper.parent.removeClass("viewport-right").removeClass("viewport-bottom");
		
		var left = helper.parent[0].offsetLeft;
		var top = helper.parent[0].offsetTop;
		if (event) {
			// position the helper 15 pixel to bottom right, starting from mouse position
			left = event.pageX + settings(current).left;
			top = event.pageY + settings(current).top;
			var right='auto';
			if (settings(current).positionLeft) {
				right = $(window).width() - left;
				left = 'auto';
			}
			helper.parent.css({
				left: left,
				right: right,
				top: top
			});
		}
		
		var v = viewport(),
			h = helper.parent[0];
		// check horizontal position
		if (v.x + v.cx < h.offsetLeft + h.offsetWidth) {
			left -= h.offsetWidth + 20 + settings(current).left;
			helper.parent.css({left: left + 'px'}).addClass("viewport-right");
		}
		// check vertical position
		if (v.y + v.cy < h.offsetTop + h.offsetHeight) {
			top -= h.offsetHeight + 20 + settings(current).top;
			helper.parent.css({top: top + 'px'}).addClass("viewport-bottom");
		}
	}
	
	function viewport() {
		return {
			x: $(window).scrollLeft(),
			y: $(window).scrollTop(),
			cx: $(window).width(),
			cy: $(window).height()
		};
	}
	
	// hide helper and restore added classes and the title
	function hide(event) {
		if($.tooltip_2.blocked)
			return;
		// clear timeout if possible
		if(tID)
			clearTimeout(tID);
		// no more current element
		current = null;
		
		var tsettings = settings(this);
		function complete() {
			helper.parent.removeClass( tsettings.extraClass ).hide().css("opacity", "");
		}
		if ((!IE || !$.fn.bgiframe) && tsettings.fade) {
			if (helper.parent.is(':animated'))
				helper.parent.stop().fadeTo(tsettings.fade, 0, complete);
			else
				helper.parent.stop().fadeOut(tsettings.fade, complete);
		} else
			complete();
		
		if( settings(this).fixPNG )
			helper.parent.unfixPNG();
	}
	
})(jQuery);
// EZPZ Tooltip v1.0; Copyright (c) 2009 Mike Enriquez, http://theezpzway.com; Released under the MIT License
(function($){
	$.fn.ezpz_tooltip = function(options){
		var settings = $.extend({}, $.fn.ezpz_tooltip.defaults, options);
		
		return this.each(function(){
			var	content = $("#" + getContentId(this.id));
			var targetMousedOver = $(this).mouseover(function(){
				settings.beforeShow(content, $(this));
			}).mousemove(function(e){
				contentInfo = getElementDimensionsAndPosition(content);
				targetInfo = getElementDimensionsAndPosition($(this));
				contentInfo = $.fn.ezpz_tooltip.positions[settings.contentPosition](contentInfo, e.pageX, e.pageY, settings.offset, targetInfo);
				contentInfo = keepInWindow(contentInfo);
				
				content.css('top', contentInfo['top']);
				content.css('left', contentInfo['left']);
				
				settings.showContent(content);
			});
			
			if (settings.stayOnContent && this.id != "") {
				$("#" + this.id + ", #" + getContentId(this.id)).mouseover(function(){
					content.css('display', 'block');
				}).mouseout(function(){
					content.css('display', 'none');
					settings.afterHide();
				});
			}
			else {
				targetMousedOver.mouseout(function(){
					settings.hideContent(content);
					settings.afterHide();
				})
			}
			
		});
		
		function getContentId(targetId){
			if (settings.contentId == "") {
				var name = targetId.split('-')[0];
				var id = targetId.split('-')[2];
				return name + '-content-' + id;
			}
			else {
				return settings.contentId;
			}
		};
		
		function getElementDimensionsAndPosition(element){
			var height = element.outerHeight(true);
			var width = element.outerWidth(true);
			var top = $(element).offset().top;
			var left = $(element).offset().left;
			var info = new Array();
			
			// Set dimensions
			info['height'] = height;
			info['width'] = width;
			
			// Set position
			info['top'] = top;
			info['left'] = left;
			
			return info;
		};
		
		function keepInWindow(contentInfo){
			var windowWidth = $(window).width();
			var windowTop = $(window).scrollTop();
			var output = new Array();
			
			output = contentInfo;
			
			if (contentInfo['top'] < windowTop) { // Top edge is too high
				output['top'] = windowTop;
			}
			if ((contentInfo['left'] + contentInfo['width']) > windowWidth) { // Right edge is past the window
				output['left'] = windowWidth - contentInfo['width'];
			}
			if (contentInfo['left'] < 0) { // Left edge is too far left
				output['left'] = 0;
			}
			
			return output;
		};
	};
	
	$.fn.ezpz_tooltip.positionContent = function(contentInfo, mouseX, mouseY, offset, targetInfo) {
		contentInfo['top'] = mouseY - offset - contentInfo['height'];
		contentInfo['left'] = mouseX + offset;
		
		return contentInfo;
	};
	
	$.fn.ezpz_tooltip.positions = {
		aboveRightFollow: function(contentInfo, mouseX, mouseY, offset, targetInfo) {
			contentInfo['top'] = mouseY - offset - contentInfo['height'];
			contentInfo['left'] = mouseX + offset;

			return contentInfo;
		}
	};
	
	$.fn.ezpz_tooltip.defaults = {
		contentPosition: 'aboveRightFollow',
		stayOnContent: false,
		offset: 10,
		contentId: "",
		beforeShow: function(content){},
		showContent: function(content){
			content.show();
		},
		hideContent: function(content){
			content.hide();
		},
		afterHide: function(){}
	};
	
})(jQuery);

// Plugin for different content positions. Keep what you need, remove what you don't need to reduce file size.

(function($){
	$.fn.ezpz_tooltip.positions.aboveFollow = function(contentInfo, mouseX, mouseY, offset, targetInfo) {
		contentInfo['top'] = mouseY - offset - contentInfo['height'];
		contentInfo['left'] = mouseX - (contentInfo['width'] / 2);
		
		return contentInfo;
	};
	
	$.fn.ezpz_tooltip.positions.rightFollow = function(contentInfo, mouseX, mouseY, offset, targetInfo) {
		contentInfo['top'] = mouseY - (contentInfo['height'] / 2);
		contentInfo['left'] = mouseX + offset;
		
		return contentInfo;
	};
	
	$.fn.ezpz_tooltip.positions.belowRightFollow = function(contentInfo, mouseX, mouseY, offset, targetInfo) {
		contentInfo['top'] = mouseY + offset;
		contentInfo['left'] = mouseX + offset;
		
		return contentInfo;
	};
	
	$.fn.ezpz_tooltip.positions.belowFollow = function(contentInfo, mouseX, mouseY, offset, targetInfo) {
		contentInfo['top'] = mouseY + offset;
		contentInfo['left'] = mouseX - (contentInfo['width'] / 2);
		
		return contentInfo;
	};
	
	$.fn.ezpz_tooltip.positions.aboveStatic = function(contentInfo, mouseX, mouseY, offset, targetInfo) {
		contentInfo['top'] = targetInfo['top'] - offset - contentInfo['height'];
		contentInfo['left'] = (targetInfo['left'] + (targetInfo['width'] / 2)) - (contentInfo['width'] / 2);
		
		return contentInfo;
	};
	
	$.fn.ezpz_tooltip.positions.rightStatic = function(contentInfo, mouseX, mouseY, offset, targetInfo) {
		contentInfo['top'] = (targetInfo['top'] + (targetInfo['height'] / 2)) - (contentInfo['height'] / 2);
		contentInfo['left'] = targetInfo['left'] + targetInfo['width'] + offset;
		
		return contentInfo;
	};
	
	$.fn.ezpz_tooltip.positions.belowStatic = function(contentInfo, mouseX, mouseY, offset, targetInfo) {
		contentInfo['top'] = targetInfo['top'] + targetInfo['height'] + offset;
		contentInfo['left'] = (targetInfo['left'] + (targetInfo['width'] / 2)) - (contentInfo['width'] / 2);
		
		return contentInfo;
	};
	
})(jQuery);
/* Copyright (c) 2006-2007 Mathias Bank (http://www.mathias-bank.de)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 * 
 * Version 2.1
 * 
 * Thanks to 
 * Hinnerk Ruemenapf - http://hinnerk.ruemenapf.de/ for bug reporting and fixing.
 * Tom Leonard for some improvements
 * 
 */

jQuery.fn.extend({
/**
* Returns get parameters.
*
* If the desired param does not exist, null will be returned
*
* To get the document params:
* @example value = $(document).getUrlParam("paramName");
* 
* To get the params of a html-attribut (uses src attribute)
* @example value = $('#imgLink').getUrlParam("paramName");
*/ 
 getUrlParam: function(strParamName){
	  strParamName = escape(unescape(strParamName));
	  
	  var returnVal = new Array();
	  var qString = null;
	  
	  if ($(this).attr("nodeName")=="#document") {
	  	//document-handler
		
		if (window.location.search.search(strParamName) > -1 ){
			
			qString = window.location.search.substr(1,window.location.search.length).split("&");
		}
			
	  } else if ($(this).attr("src")!="undefined") {
	  	
	  	var strHref = $(this).attr("src")
	  	if ( strHref.indexOf("?") > -1 ){
	    	var strQueryString = strHref.substr(strHref.indexOf("?")+1);
	  		qString = strQueryString.split("&");
	  	}
	  } else if ($(this).attr("href")!="undefined") {
	  	
	  	var strHref = $(this).attr("href")
	  	if ( strHref.indexOf("?") > -1 ){
	    	var strQueryString = strHref.substr(strHref.indexOf("?")+1);
	  		qString = strQueryString.split("&");
	  	}
	  } else {
	  	return null;
	  }
	  	
	  
	  if (qString==null) return null;
	  
	  
	  for (var i=0;i<qString.length; i++){
			if (escape(unescape(qString[i].split("=")[0])) == strParamName){
				returnVal.push(qString[i].split("=")[1]);
			}
			
	  }
	  
	  
	  if (returnVal.length==0) return null;
	  else if (returnVal.length==1) return returnVal[0];
	  else return returnVal;
	}
});
/*	
 *	jQuery dotdotdot 1.3.1
 *	
 *	Copyright (c) 2011 Fred Heusschen
 *	www.frebsite.nl
 *
 *	Plugin website:
 *	dotdotdot.frebsite.nl
 *
 *	Dual licensed under the MIT and GPL licenses.
 *	http://en.wikipedia.org/wiki/MIT_License
 *	http://en.wikipedia.org/wiki/GNU_General_Public_License
 */


(function($) {
	if ($.fn.dotdotdot) return;

	$.fn.dotdotdot = function(o) {
		if (this.length == 0) {
			debug(true, 'No element found for "'+this.selector+'".');
			return this;
		}
		if (this.length > 1) {
			return this.each(function() {
				$(this).dotdotdot(o);
			});
		}


		var $dot = this,
			$tt0 = this[0];

		if ($dot.data('dotdotdot')) {
			$dot.trigger('destroy.dot');
		}

		$dot.bind_events = function() {
			$dot.bind('update.dot', function(e, stop) {
				e.preventDefault();
				e.stopPropagation();

				opts.maxHeight = (typeof opts.height == 'number') ? opts.height : getTrueInnerHeight($dot);
				opts.maxHeight += opts.tolerance;

				$inr.empty();
				$inr.append(orgContent.clone(true));

				var after = false,
					trunc = false;

				if (conf.afterElement) {
					after = conf.afterElement.clone(true);
					conf.afterElement.remove();
				}
				if (test($inr, opts)) {
					if (opts.wrap == 'children') {
						trunc = children($inr, opts, after);
					} else {
						trunc = ellipsis($inr, $inr, opts, after);
					}
				}
				conf.isTruncated = trunc;
				return trunc;
			});
			$dot.bind('isTruncated.dot', function(e, fn) {
				e.preventDefault();
				e.stopPropagation();

				var t = conf.isTruncated;
				if (typeof fn == 'function') {
					fn.call($tt0, t);
				}
				return t;
			});
			$dot.bind('originalContent.dot', function(e, fn) {
				e.preventDefault();
				e.stopPropagation();

				var c = orgContent;
				if (typeof fn == 'function') {
					fn.call($tt0, c);
				}
				return c;
			});
			$dot.bind('destroy.dot', function(e) {
				e.preventDefault();
				e.stopPropagation();

				$dot.unwatch();
				$dot.unbind_events();
				$dot.empty();
				$dot.append(orgContent);
				$dot.data('dotdotdot', false);
			});
		};	//	/bind_events

		$dot.unbind_events = function() {
			$dot.unbind('.dot');
		};	//	/unbind_events

		$dot.watch = function() {
			$dot.unwatch();
			if (opts.watch == 'window') {
				$(window).bind('resize.dot', function() {
					if (watchInt) {
						clearInterval(watchInt);
					}
					watchInt = setTimeout(function() {
						$dot.trigger('update.dot');
					}, 10);
				});
			} else {
				watchOrg = getSizes($dot);
				watchInt = setInterval(function() {
					var watchNew = getSizes($dot);
					if (watchOrg.width  != watchNew.width ||
						watchOrg.height != watchNew.height
					) {
						$dot.trigger('update.dot');
						watchOrg = getSizes($dot);
					}
				}, 100);
			}
		};
		$dot.unwatch = function() {
			if (watchInt) {
				clearInterval(watchInt);
			}
		};

		var	orgContent	= $dot.contents(),
			opts 		= $.extend(true, {}, $.fn.dotdotdot.defaults, o),
			conf		= {},
			watchOrg	= {},
			watchInt	= null,
			$inr		= $dot.wrapInner('<'+opts.wrapper+' class="dotdotdot" />').children();

		conf.afterElement	= getElement(opts.after, $inr);
		conf.isTruncated	= false;

		$inr.css({
			'height'	: 'auto',
			'width'		: 'auto'
		});

		$dot.data('dotdotdot', true);
		$dot.bind_events();
		$dot.trigger('update.dot');
		if (opts.watch) {
			$dot.watch();
		}

		return $dot;
	};



	//	public
	$.fn.dotdotdot.defaults = {
		'wrapper'	: 'div',
		'ellipsis'	: '... ',
		'wrap'		: 'word',
		'tolerance'	: 0,
		'after'		: null,
		'height'	: null,
		'watch'		: false,
		'debug'		: false
	};
	

	//	private
	function children($elem, o, after) {
		var $elements = $elem.children(),
			isTruncated = false;

		$elem.empty();

		for (var a = 0, l = $elements.length; a < l; a++) {
			var $e = $elements.eq(a);
			$elem.append($e);
			if (after) {
				$elem.append(after);
			}
			if (test($elem, o)) {
				$e.remove();
				isTruncated = true;
				break;
			} else {
				if (after) {
					after.remove();
				}
			}
		}
		return isTruncated;
	}
	function ellipsis($elem, $i, o, after) {
		var $elements = $elem.contents(),
			isTruncated = false;

		$elem.empty();

		var notx = 'table, thead, tbody, tfoot, tr, col, colgroup, object, embed, param, ol, ul, dl, select, optgroup, option, textarea, script, style';

		for (var a = 0, l = $elements.length; a < l; a++) {

			if (isTruncated) {
				break;
			}

			var e	= $elements[a],
				$e	= $(e);

			if (typeof e == 'undefined') {
				continue;
			}

			$elem.append($e);
			if (after) {
				var func = ($elem.is(notx)) ? 'after' : 'append';
				$elem[func](after);
			}
			if (e.nodeType == 3) {
				if (test($i, o)) {
					isTruncated = ellipsisElement($e, $i, o, after);
				}
			} else {
				isTruncated = ellipsis($e, $i, o, after);
			}

			if (!isTruncated) {
				if (after) {
					after.remove();
				}
			}
		}
		return isTruncated;
	}
	function ellipsisElement($e, $i, o, after) {
		var isTruncated	= false,
			e			= $e[0];

		if (typeof e == 'undefined') {
			return false;
		}

		var seporator	= (o.wrap == 'letter') ? '' : ' ',
			textArr		= getTextContent(e).split(seporator);

		setTextContent(e, textArr.join(seporator) + o.ellipsis);

		for (var a = textArr.length - 1; a >= 0; a--) {
			if (test($i, o)) {

				var end = getTextContent(e).length - (textArr[a].length + seporator.length + o.ellipsis.length),
					txt = (end > 0) ? getTextContent(e).substring(0, end) : '';

				setTextContent(e, txt + o.ellipsis);

			} else {
				isTruncated = true;
				break;
			}
		}


		if (!isTruncated) {
			var $w = $e.parent();
			$e.remove();
			$n = $w.contents().eq(-1);

			isTruncated = ellipsisElement($n, $i, o, after);
		}


		return isTruncated;
	}
	function test($i, o) {
		return $i.innerHeight() > o.maxHeight;
	}
	function getSizes($d) {
		return {
			'width'	: $d.innerWidth(),
			'height': $d.innerHeight()
		};
	}
	function setTextContent(e, content) {
		if (e.innerText) {
			e.innerText = content;
		} else if (e.nodeValue) {
			e.nodeValue = content;
		} else if (e.textContent) {
			e.textContent = content;
		}
	}
	function getTextContent(e) {
		if (e.innerText) {
			return e.innerText;
		} else if (e.nodeValue) {
			return e.nodeValue;
		} else if (e.textContent) {
			return e.textContent;
		} else {
			return "";
		}
	}
	function getElement(e, $i) {
		if (typeof e == 'undefined') {
			return false;
		}
		if (!e) {
			return false;
		}
		if (typeof e == 'string') {
			e = $(e, $i);
			return (e.length) ? e : false;
		}
		if (typeof e == 'object') {
			return (typeof e.jquery == 'undefined') ? false : e;
		}
		return false;
	}
	function getTrueInnerHeight($el) {
		var h = $el.innerHeight(),
			a = ['paddingTop', 'paddingBottom'];

		for (z = 0, l = a.length; z < l; z++) {
			var m = parseInt($el.css(a[z]));
			if (isNaN(m)) m = 0;
			h -= m;
		}
		return h;
	}
	function debug(d, m) {
		if (!d) return false;
		if (typeof m == 'string') m = 'dotdotdot: ' + m;
		else m = ['dotdotdot:', m];

		if (window.console && window.console.log) window.console.log(m);
		return false;
	}

})(jQuery);

