World of Merix Studio

// code from http://javascript.about.com/library/bltime4.htm

function daylightSaving() {
  var gmt = new Date;
  var lsm = new Date;
  var lso = new Date;
  lsm.setMonth(2); // March
  lsm.setDate(31);
  var day = lsm.getDay(); // day of week of 31st
  lsm.setDate(31 - day); // last Sunday
  lso.setMonth(9); // October
  lso.setDate(31);
  day = lso.getDay();
  lso.setDate(31 - day);
  if (gmt < lsm || gmt >= lso) return 0;
  return 1;
}

var IE6 = $.browser.msie && $.browser.version <= 6;

if ($.browser.msie && $.browser.version <= 8) jQuery.fx.off = true;

$.fn.extend({
  hrefId: function() {
    return $(this).attr("href").substr($(this).attr("href").indexOf("#"));
  },
  fixIE7: function() {
    if ($.browser.msie && $.browser.version == 7) $(this).each(function() {
      this.style.removeAttribute("filter");
    });
    return $(this);
  },
  typedVal: function() {
    var t = $(this)[0];
    return t.value == t.defaultText ? "" : t.value;
  }
});


Date.prototype.toTimeString = function() {
  return (this.getHours() < 10 ? "0" + this.getHours() : this.getHours()) + ":" + (this.getMinutes() < 10 ? "0" + this.getMinutes() : this.getMinutes()) + ":" + (this.getSeconds() < 10 ? "0" + this.getSeconds() : this.getSeconds());
};

Number.prototype.toRemaining = function() {
  var m = Math.ceil(this / 60000) + 2;
  return m <= 1 ? "1 minute" : (m < 60 ? m + " minutes" : (m / 60 <= 1 ? "1 hour" : (Math.floor(m / 60) <= 1 ? "1 hour" : Math.floor(m / 60) + " hours") + (m % 60 < 1 ? "" : (m % 60 == 1 ? " 1 minute" : " " + (m % 60) + " minutes"))));
};


$(window).load(function() {
  var $loading = $("body>.loading:first");
  setTimeout(function() {
    $loading.animate({
      opacity: 0
    }, 1000, function() {
      $(this).remove();
    });
  }, 500);
});


var windowW = $(window).width(),
  windowH = $(window).height();


$(window).resize(function() {
  windowW = $(window).width();
  windowH = $(window).height();
});


var map = new function() {
    var
    $map = $('<div class="map"></div>').appendTo("body"),
      mapW = (5500 - windowW) / 2,
      mapH = (2100 - windowH) / 2,
      angleX = Math.random() * 360,
      angleY = Math.random() * 360,
      speed = 0,
      x = -Math.floor((Math.sin(angleX * Math.PI / 180) + 1) * mapW),
      y = -Math.floor((Math.cos(angleY * Math.PI / 180) + 1) * mapH),
      pause = false,
      dragEndTimer = false,
      markerPos = 0,
      align = {
        "r": "",
        "l": " left",
        "br": " bottom-right",
        "bl": " bottom-left",
        "tr": " top-right",
        "tl": " top-left"
      },
      calign = {
        "l": " clients-left"
      },
      siteTypes = ["many", "design", "programming", "marketing"];

    var showMarker = function() {
        if (markerPos < cities.length) {
          var m = cities[markerPos];
          var $m = $('<span class="city' + align[typeof m[3] == "string" ? m[3] : "r"] + (m[3] !== true && m[4] !== true ? ' city-capital' : '') + '" style="left: ' + m[1] + 'px; top: ' + m[2] + 'px"><span>' + m[0] + '</span></span>').appendTo($map);
          if (!$.browser.msie) $m.animate({
            opacity: 1
          }, 2000, function() {
            $(this).fixIE7();
          });
        }

        if (markerPos < clients.length) {
          var m = clients[markerPos];
          var $m = $('<p class="clients' + (m[4] ? calign[m[4]] : '') + '" style="left: ' + m[0] + 'px; top: ' + m[1] + 'px; z-index: ' + m[1] + '"><em>' + m[3] + ' <span>(' + m[2] + ')</span></em></p>').appendTo($map);
          if (!$.browser.msie) $m.animate({
            opacity: 1
          }, 2000, function() {
            $(this).fixIE7();
          });
          navigation.addMarker(m[0], m[1]);
        }

        if (markerPos < sites.length) {
          var m = sites[markerPos];
          var $m = $('<a target="_blank" class="site' + align[m[5] || "r"] + ' site-' + siteTypes[m[2]] + '" href="http://' + m[3] + '/" style="left: ' + m[0] + 'px; top: ' + m[1] + 'px; z-index: ' + m[1] + '"><span>' + m[4] + '</span></a>').appendTo($map);
          if (!$.browser.msie) $m.animate({
            opacity: 1
          }, 2000, function() {
            $(this).fixIE7();
          });

          $m.mousemove(function() {
            speed = 2;
          });
        }

        if (markerPos < cities.length - 1 || markerPos < clients.length - 1 || markerPos < sites.length - 1) {
          markerPos++;
          setTimeout(showMarker, 25);
        }
      };

    this.resume = function() {
      if (dragEndTimer) clearTimeout(dragEndTimer);

      dragEndTimer = setTimeout(function() {
        dragEndTimer = false;
        $map.stop(true).animate({
          left: x + "px",
          top: y + "px"
        }, 10000, function() {
          speed = 0;
          pause = false;
        });
        navigation.animateTo(x, y, 10000);
      }, 10000);
    };

    var moveMap = function() {
        if (pause) return;

        speed < 10 ? speed += 0.05 : speed = 10;
        angleX < 360 ? angleX += .01 * speed : angleX -= 360;
        angleY < 360 ? angleY += .003 * speed : angleY -= 360;

        x = -Math.floor((Math.sin(angleX * Math.PI / 180) + 1) * mapW);
        y = -Math.floor((Math.cos(angleY * Math.PI / 180) + 1) * mapH);

        $map.css({
          left: x + "px",
          top: y + "px"
        });
        navigation.goTo(x, y);
      };

    $map.bind("mousedown", function() {
      pause = true;
      $map.stop(true);
      navigation.stop();
    }).bind("drag", function(event) {
      $map.stop(true).animate({
        left: event.offsetX + "px",
        top: event.offsetY + "px"
      }, 0);
      navigation.goTo(event.offsetX, event.offsetY);
    }).bind("mouseup dragend", function() {
      map.resume();
    });

    $(window).resize(function() {
      mapW = (5500 - windowW) / 2;
      mapH = (2100 - windowH) / 2;
    });

    this.animateTo = function(x, y, time) {
      pause = true;
      $map.stop(true).animate({
        left: (-x + windowW / 2) + "px",
        top: (-y + windowH / 2) + "px"
      }, time);
    };
    this.goTo = function(x, y) {
      pause = true;
      $map.stop(true).css({
        left: (-x) + "px",
        top: (-y) + "px"
      });
    };
    this.getX = function() {
      return x;
    };
    this.getY = function() {
      return y;
    };
    this.stop = function() {
      pause = true;
      $map.stop(true);
    };
    this.showClients = function() {
      $map.attr("class", "map map-clients");
    };
    this.showCities = function() {
      $map.attr("class", "map map-cities");
    };
    this.showSites = function() {
      $map.attr("class", "map map-sites");
    };

    $(window).load(function() {
      showMarker();
      setInterval(moveMap, 33);
    });
  };


var navigation = new function() {
    var
    $navigation = $('<div class="navigation"><div><p class="map"><a><span class="top"></span><span class="right"></span><span class="bottom"></span><span class="left"></span></a></p><p class="controls">Show: <a class="clients">Our Clients</a> <a class="sites">Web resources</a> <a class="cities">Cities</a></p></div></div>').appendTo("body"),
      $navigationWindow = $navigation.find("p.map>a"),
      folded = false;

    var fold = function() {
        $navigation.stop(true).animate({
          opacity: .15
        }, 500).find("p.map:first").stop(true).animate({
          marginTop: "-126px"
        }, 500);
      };
    var unfold = function() {
        $navigation.stop(true).animate({
          opacity: 1
        }, 500, function() {
          $(this).fixIE7();
        }).find("p.map:first").stop(true).animate({
          marginTop: 0
        }, 500);
      };

    $navigation.find("p.controls a").click(function() {
      $(this).addClass("on").siblings().removeClass("on");
      return false;
    });
    $navigation.find("p.controls a.clients").click(function() {
      map.showClients();
    }).click();
    $navigation.find("p.controls a.cities").click(function() {
      map.showCities();
    });
    $navigation.find("p.controls a.sites").click(function() {
      map.showSites();
    });

    $navigation.find("p.map").click(function(event) {
      var pos = $(this).offset(),
        x = event.pageX - pos.left,
        y = event.pageY - pos.top;
      $navigationWindow.stop(true).animate({
        left: (x - $navigationWindow.outerWidth() / 2) + "px",
        top: (y - $navigationWindow.outerHeight() / 2) + "px"
      }, 333);
      map.animateTo(x * 20, y * 20, 333);
      map.resume();
      return false;
    });

    $navigationWindow.css({
      display: "block",
      left: (-map.getX() * .05) + "px",
      top: (-map.getY() * .05) + "px",
      width: (windowW * .05) + "px",
      height: (windowH * .05) + "px"
    }).click(function() {
      return true;
    }).bind("mousedown dragstart", function() {
      map.stop();
      $navigationWindow.stop(true);
    }).bind("mouseup dragend", function() {
      map.resume();
    }).bind("click", function() {
      return false;
    }).bind("drag", function(event) {
      var pos = $(this).parent().offset();
      var x = event.offsetX - pos.left;
      var y = event.offsetY - pos.top;

      map.goTo(x / 275 * 5500, y / 105 * 2100);
      $navigationWindow.stop(true).css({
        left: x + "px",
        top: y + "px"
      });
    });;

    $(window).resize(function() {
      $navigationWindow.css({
        width: Math.floor(windowW * .05) + "px",
        height: Math.floor(windowH * .05) + "px"
      });
    });

    this.stop = function() {
      $navigationWindow.stop(true);
    };
    this.goTo = function(x, y) {
      $navigationWindow.stop(true).css({
        left: (-x * .05) + "px",
        top: (-y * .05) + "px"
      });
    };
    this.animateTo = function(x, y, time) {
      $navigationWindow.stop(true).animate({
        left: (-x * .05) + "px",
        top: (-y * .05) + "px"
      }, time);
    };
    this.fold = function() {
      folded = true;
      fold();
    };
    this.unfold = function() {
      folded = false;
      unfold();
    };
    this.addMarker = function(x, y) {
      $('<span class="clients" style="left: ' + Math.round(x * .05) + 'px; top: ' + Math.round(y * .05) + 'px"></span>').appendTo($navigation.find("p.map:first"));
    };
  };



var validation = new function() {
    var
    self = this,
      messages = {
        "required": "This field is mandatory.",
        "max_length": "Text is too long.",
        "valid_email": "This isn't valid e-mail address.",
        "valid_address": "This isn't valid address."
      },
      functions = {
        "required": function(s) {
          return typeof s == "string" && s.length > 0;
        },
        "max_length": function(s, l) {
          return typeof s == "string" && s.length <= parseInt(l);
        },
        "valid_email": function(s) {
          return typeof s == "string" && s.match(/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/i);
        },
        "valid_address": function(s) {
          return typeof s == "string" && s.match(/^(?:(?:ht|f)tp(?:s?)\:\/\/|~\/|\/)?(?:\w+:\w+@)?(?:(?:[-\w]+\.)+(?:com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|travel|[a-z]{2}))(?::[\d]{1,5})?(?:(?:(?:\/(?:[-\w~!$+|.,=]|%[a-f\d]{2})+)+|\/)+|\?|#)?(?:(?:\?(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)(?:&(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)*)*(?:#(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)?$/i);
        }
      };

    self.check = function(fields) {
      var result = true;
      for (var f in fields) {
        var rules = fields[f].rules.split("|");
        for (var r = 0; r < rules.length; r++) {
          var rule = rules[r],
            param = rule.indexOf("[");
          if (param > 0) {
            rule = rule.slice(0, param);
            param = rules[r].slice(param + 1);
            param = param.slice(0, param.length - 1);
          }

          if (!functions[rule](fields[f].value, param)) {
            if (result === true) result = {};
            result[f] = messages[rule];
            break;
          }
        }
      }

      return result;
    };
  };


$("ul.gallery").each(function() {
  var $gallery = $(this),
    c = $gallery.children().length,
    t = 750;

  $gallery.wrap('<div class="gallery-clip"></div>').width(c * 345);
  $gallery.parent().before('<h3 class="alt"></h3><p class="gallery-nav gallery-nav-prev"><a>&lt;</a></p><p class="gallery-nav gallery-nav-next"><a>&gt;</a></p>');

  var $thumbs = $('<ul class="thumbnails"></ul>').appendTo($gallery.parent()).width(c * 88),
    $w = $gallery.closest(".window"),
    i = 0,
    $h = $w.find("h3:first");

  var galleryUpdate = function() {
      $h.text($gallery.find(">li:eq(" + i + ")>img").attr("title") + " (" + (i + 1) + "/" + c + ")");
      $thumbs.children().eq(i).children("a").addClass("selected").parent().siblings().children("a.selected").removeClass("selected");
    };

  $w.find("p.gallery-nav-prev a").click(function() {
    if (i > 0) {
      $gallery.stop(true).animate({
        left: (--i * -345) + "px"
      }, t);
      if (c > 4 && i < c - 3) $thumbs.stop(true).animate({
        left: (i * -88) + "px"
      }, t);
    }
    galleryUpdate();
    return false;
  });

  $w.find("p.gallery-nav-next a").click(function() {
    if (i < c - 1) {
      $gallery.stop(true).animate({
        left: (++i * -345) + "px"
      }, t);
      if (c > 4 && i < c - 3) $thumbs.stop(true).animate({
        left: (i * -88) + "px"
      }, t);
    }
    galleryUpdate();
    return false;
  });

  $gallery.children().each(function() {
    var $img = $(this).find("img");
    $('<li><a><img src="' + $img.attr("src") + '" title="' + $img.attr("title") + '"></a></li>').appendTo($thumbs).children("a").click(function() {
      i = $thumbs.children().index($(this).parent()) - 1;
      $gallery.stop(true).animate({
        left: (++i * -345) + "px"
      }, t);
      if (c > 4) $thumbs.stop(true).animate({
        left: ((i < c - 3 ? i : c - 4) * -88) + "px"
      }, t);
      galleryUpdate();
      return false;
    });
  });

  galleryUpdate();
});


var windows = new function() {
    $("body").append('<div class="window" id="window-time-zones"><div class="window"><div><p class="text-center"><img src="images/' + (IE6 ? 'ie6/' : '') + 'timezones_map.png" width="708" height="376" alt=""></p><p class="location">Poznań / Poland <span></span></p><p class="user-time">Your time is <strong></strong></p><p class="remaining-time"></p><p class="our-time">Merix Studio time is <strong></strong></p></div></div></div>' + '<div class="window window-small" id="window-newsletter"><div class="window"><h2>Newsletter</h2><form action="" method="post"><p>Get exclusive previews of new projects.</p><p><input type="text" class="text" name="name" value="Your Name" size="64" maxlength="64"></p><p><input type="text" class="text" name="e-mail" value="Your e-mail address" size="48" maxlength="96"></p><p class="no-margin"><button type="submit"><span><span>Add</span></span></button></p></form></div></div>' + '<div class="window window-small" id="window-newsletter-sent"><div class="window"><h2>Confirm subscription</h2><p>Thank you for signing up for our newsletter. Please check out your inbox to confirm subscription.</p><p class="no-margin"><button class="close"><span><span>Close</span></span></button></p></div></div>' + '<div class="window window-small" id="window-sending"><div class="window"><h2>Sending message…</h2><p class="loading">Please wait, sending data to server.</p></div></div>' + '<div class="window window-small" id="window-contact-sent"><div class="window"><h2>Thank You!</h2><p>Message has been sent! We will get back to you as soon as possible.</p><p>Hey, don\'t go away yet - there is still time to have some fun. <a href="http://www.merixstudio.com/mblocks">Play mBlocks now</a> - 100% JavaScript experience guaranteed!</p><p class="no-margin"><button class="close"><span><span>Close</span></span></button></p></div></div>' + '<div class="window window-small" id="window-error-sending"><div class="window"><h2>Server error</h2><p>Message could not be sent because server error occurred. Please try again later.</p><p class="no-margin"><button class="close"><span><span>Close</span></span></button></p></div></div>' + '<div class="window window-small" id="window-suggest"><div class="window"><h2>Suggest a site</h2><form action="" method="post"><p>If you know an interesting website that you believe should be added to our map, just give us its address and we\'ll do the rest!</p><p><input type="text" class="text" name="address" value="Website URL" size="64" maxlength="256"></p><p class="no-margin"><button type="submit"><span><span>Add</span></span></button></p></form></div></div>' + '<div class="window window-small" id="window-suggest-sent"><div class="window"><h2>Thank you</h2><p>Your submission has been sent. We\'ll review it and if it meets our criteria it will be added to the World of Merix Studio map.</p><p class="no-margin"><button class="close"><span><span>Close</span></span></button></p></div></div>');

    $("body>.footer").prepend('<div class="window window-special" id="window-legend"><div class="window"><h2>World map legend</h2><h3>Our Clients</h3><p><span class="marker marker-clients"></span> Number of Merix Studio clients in this country</p><h3>Web Resources</h3><ul><li class="left"><span class="marker marker-site-many"></span> Mixed content</li><li class="right"><span class="marker marker-site-design"></span> Web design</li><li class="left"><span class="marker marker-site-programming"></span> Web development</li><li class="right"><span class="marker marker-site-marketing"></span> Marketing, ePR, SEM</li></ul><h3>Cities</h3><ul><li class="left"><span class="marker marker-city-capital"></span> Capital city</li><li class="right"><span class="marker marker-city"></span> Large city</li></ul></div></div><p class="legend"><a href="#window-legend">Legend</a></p>');

    $("body>.header:first>ul").append('<li><a class="alt" href="#window-newsletter"><span>Newsletter</span></a></li>');

    var $windows = $("body>.window,body>.footer>.window"),
      h = {},
      mt = {},
      time = false,
      opened = {},
      self = this;

    if (!$.browser.opera) $windows.filter("#window-contact").removeClass("window-small").children(".window").append('<div class="right"><h3>Contact Form</h3><form action="" method="post"><p><label for="contact-name">Your name:</label> <input type="text" class="text" id="contact-name" name="name" size="64" maxlength="64"></p><p><label for="contact-company">Company:</label> <input type="text" class="text" id="contact-company" name="company" size="64" maxlength="64"></p><p><label for="contact-e-mail">E-mail:</label> <input type="text" class="text" id="contact-e-mail" name="e-mail" size="48" maxlength="96"></p><p><label for="contact-message">Message:</label> <textarea rows="5" cols="80" id="contact-message" name="message"></textarea></p><p><button type="submit"><span><span>Send Message</span></span></button></p></form></div>');

    $windows.each(function() {
      $(this).prepend('<p class="close"><a>X</a></p>');
      var id = $(this).attr("id");
      h[id] = $(this).innerHeight() - parseInt($(this).css("padding-top")) - parseInt($(this).children(".window").css("padding-bottom"));
      mt[id] = (-$(this).outerHeight()) / 2;
      opened[id] = false;
    });

    $.fn.extend({
      close: function() {
        navigation.unfold();
        $("body>.footer:first,body>.header:first").stop(true).animate({
          opacity: 1
        }, 750, function() {
          $(this).fixIE7();
        });
        return $(this).each(function() {
          opened[$(this).attr("id")] = false;
          $(this).trigger("close");
          if (!$(this).hasClass("window-special")) $(this).animate({
            opacity: 0
          }, 500, function() {
            $(this).css({
              display: "none"
            }).find(">.window>div").css({
              opacity: 0
            });
          });
        });
      }
    });

    $windows.find(">p.close>a,button.close").click(function() {
      var $w = $(this).parents(".window:last").close();
      var $f = $w.find("form");
      if ($f.length) $f[0].reset();
      $f.find("p.error").remove();
    });
    $windows.find("button[type=reset]").click(function() {
      $(this).closest("form").find("p.error").remove();
    });

    self.open = function(id) {
      if (opened[id]) return;

      $windows.not("#" + id).close();
      opened[id] = true;
      var $w = $windows.filter("#" + id);

      if (!$w.hasClass("window-special")) {
        navigation.fold();
        $("body>.footer,body>.header").stop(true).animate({
          opacity: .15
        }, 750); //.find('*').fold();

        $w.children(".window").removeAttr("style");
        h[id] = $w.innerHeight() - parseInt($w.css("padding-top")) - parseInt($w.children(".window").css("padding-bottom"));
        mt[id] = (-$w.outerHeight()) / 2;

        $w.children(".window").height(0).children().stop(true).css({
          opacity: 0
        });
        $w.trigger("open").css({
          display: "block",
          marginTop: "-40px"
        }).stop(true).animate({
          opacity: 1
        }, 750, function() {
          $(this).fixIE7().animate({
            marginTop: mt[id] + "px"
          }, 750).children(".window").animate({
            height: h[id] + "px"
          }, 750).children().animate({
            opacity: 1
          }, 2000, function() {
            $(this).fixIE7();
          });
        });
      } else $w.trigger("open");

    };

    this.toggle = function(id) {
      if (opened[id]) $windows.filter("#" + id).close();
      else self.open(id);
    };

    this.recalcHeight = function(id) {
      var $w = $windows.filter("#" + id);

      var oldH = $w.children(".window").height();
      $w.children(".window").removeAttr("style");
      h[id] = $w.innerHeight() - parseInt($w.css("padding-top")) - parseInt($w.children(".window").css("padding-bottom"));
      mt[id] = (-$w.outerHeight()) / 2;
      $w.children(".window").height(oldH);

      $w.animate({
        marginTop: mt[id] + "px"
      }, 750).children(".window").animate({
        height: h[id] + "px"
      }, 750);
    };

    this.get = function(name) {
      return $windows.filter("#window-" + name);
    };

    this.get("time-zones").bind("open", function() {
      if (time) clearInterval(time);

      var $w = $(this);
      time = setInterval(function() {
        var d = new Date();

        $w.find(".user-time strong").text(d.toTimeString());

        var m = d.getTime() + (d.getTimezoneOffset() * 60000) + (1 + daylightSaving()) * 3600000;
        m = new Date(m);
        $w.find(".our-time strong").text(m.toTimeString());
        $w.find(".location span").text(m.toTimeString() + " UTC+1");

        if (m.getHours() >= 8 && m.getHours() < 16 && m.getDay() != 6 && m.getDay() != 0) {
          var n = new Date(d.getFullYear(), d.getMonth(), d.getDate(), 16, 0, 0);
          $w.find(".remaining-time").html('Our office is now open and will close at <strong>16:00 UTC+1</strong>.<br>Remaining ' + (n.getTime() - m.getTime() - 2 * 60000).toRemaining() + '.');
        } else {
          var day = m.getHours() < 8 ? m.getDate() : (m.getDay() >= 5 || m.getDay() == 0 ? m.getDate() + (m.getDay() >= 5 ? 8 - m.getDay() : 1) : m.getDate() + 1)
          var n = new Date(d.getFullYear(), d.getMonth(), day, 8, 0, 0);
          $w.find(".remaining-time").html('Our office will be opened ' + (m.getDay() >= 5 || m.getDay() == 0 ? 'on Monday ' : '') + 'at <strong>8:00 UTC+1</strong>.<br>Remaining ' + (n.getTime() - m.getTime() - 2 * 60000).toRemaining() + '.');
        }
      }, 500);
    }).bind("close", function() {
      if (time) {
        clearInterval(time);
        time = false;
      }
    });

    this.get("legend").bind("open", function() {
      var $w = $(this),
        m = -$w.outerHeight();
      $w.css({
        display: "block",
        marginTop: (m - m / 8) + "px"
      }).stop(true).animate({
        opacity: 1,
        marginTop: m + "px"
      }, 750, function() {
        $(this).fixIE7();
      });
    }).bind("close", function() {
      $(this).animate({
        opacity: 0
      }, 500, function() {
        $(this).css({
          display: "none"
        }).find(">.window>div").css({
          opacity: 0
        });
      });
    });


    var validateForm = function($form, fields, name, data) {
        var result = validation.check(fields);
        $form.find("p.error").remove();

        if (result === true) {
          windows.open("window-sending");
          data["first-rule-of-fight-club"] = "you-dont-talk-about-fight-club";
          $.post(name, data, function(result) {
            if (result.status) windows.open("window-" + name + "-sent");
            else {
              var $e = {},
                any = false;
              for (var err in result.errors) {
                $e[err] = $('<p class="error' + (err == "message" ? ' error-alt' : '') + '">' + result.errors[err] + '</p>').insertAfter($form.find("[name='" + err + "']").parent()).css("visibility", "hidden");
                any = true;
              }

              if (any) {
                windows.recalcHeight("window-" + name);
                for (var err in $e)
                $e[err].css("visibility", "visible").animate({
                  height: "hide",
                  opacity: 0
                }, 0).animate({
                  height: "show",
                  opacity: 1
                }, 500);
              } else windows.open("window-error-sending");
            }
          }, "json");
        } else {
          var $e = {};
          for (var r in result)
          $e[r] = $('<p class="error' + (r == "message" ? ' error-alt' : '') + '">' + result[r] + '</p>').insertAfter($form.find("[name='" + r + "']").parent()).css("visibility", "hidden");
          windows.recalcHeight("window-" + name);
          for (var e in $e)
          $e[e].animate({
            height: "hide",
            opacity: 0
          }, 0).animate({
            height: "show",
            opacity: 1
          }, 500).css("visibility", "visible");
        }
      };


    var $contact = this.get("contact").find("form:first").submit(function() {
      var d = {
        "name": $(this).find("input[name='name']").typedVal(),
        "company": $(this).find("input[name='company']").typedVal(),
        "e-mail": $(this).find("input[name='e-mail']").typedVal(),
        "message": $(this).find("textarea[name='message']").typedVal()
      };

      validateForm($contact, {
        "name": {
          "value": d["name"],
          "rules": "required|max_length[64]"
        },
        "company": {
          "value": d["company"],
          "rules": "max_length[64]"
        },
        "e-mail": {
          "value": d["e-mail"],
          "rules": "required|max_length[64]|valid_email"
        },
        "message": {
          "value": d["message"],
          "rules": "required|max_length[1024]"
        }
      }, "contact", d);

      return false;
    });


    var $newsletter = this.get("newsletter").find("form:first").submit(function() {
      var d = {
        "name": $(this).find("input[name='name']").typedVal(),
        "e-mail": $(this).find("input[name='e-mail']").typedVal()
      };

      validateForm($newsletter, {
        "name": {
          "value": d["name"],
          "rules": "required|max_length[64]"
        },
        "e-mail": {
          "value": d["e-mail"],
          "rules": "required|max_length[64]|valid_email"
        }
      }, "newsletter", d);

      return false;
    });

    var $suggest = this.get("suggest").find("form:first").submit(function() {
      var d = {
        "address": $(this).find("input[name='address']").typedVal()
      };
      validateForm($suggest, {
        "address": {
          "value": d["address"],
          "rules": "required|max_length[256]|valid_address"
        }
      }, "suggest", d);
      return false;
    });
  };


$(":text,textarea").each(function() {
  this.defaultText = this.value;
  $(this).focus(function() {
    if (this.value == this.defaultText) this.value = "";
  }).blur(function() {
    if (this.value == "" && this.defaultText) this.value = this.defaultText;
  });
});


var loc = window.location.href;

if (loc.indexOf("#") >= 0) {
  loc = loc.substr(loc.indexOf("#") + 1);
  if (loc.length) windows.open(loc);
}

$("body>.footer p.right").append(' | <a href="#window-suggest">Suggest a site</a>');
$("a[href*='#window-']").click(function() {
  windows.toggle($(this).hrefId().substr(1));
  return false;
});

if ($.browser.msie && $.browser.version <= 6) {
  $("body>.header:first,body>.footer:first").bind("mouseenter mouseleave", function() {
    $(this).toggleClass("hover");
  });
  $("a:not([href])").attr("href", "#");
}

Cufon.replace(".window h2", {
  fontFamily: "Haptic Light"
});
Cufon.replace(".header ul a,.footer ul a", {
  fontFamily: "Haptic Regular",
  hover: true
});
// code from http://javascript.about.com/library/bltime4.htm
function daylightSaving()
{
	var gmt = new Date;
	var lsm = new Date;
	var lso = new Date;
	lsm.setMonth(2); // March
	lsm.setDate(31);
	var day = lsm.getDay();// day of week of 31st
	lsm.setDate(31 - day); // last Sunday
	lso.setMonth(9); // October
	lso.setDate(31);
	day = lso.getDay();
	lso.setDate(31 - day);
	if (gmt < lsm || gmt >= lso)
		return 0;
	return 1;
}

var IE6 = $.browser.msie && $.browser.version <= 6;

if ($.browser.msie && $.browser.version <= 8)
	jQuery.fx.off = true;

$.fn.extend
({
	hrefId: function() { return $(this).attr("href").substr($(this).attr("href").indexOf("#")); }
,	fixIE7: function() { if ($.browser.msie && $.browser.version == 7) $(this).each(function() { this.style.removeAttribute("filter"); }); return $(this); }
,	typedVal: function() { var t = $(this)[0]; return t.value == t.defaultText ? "" : t.value; }
});


Date.prototype.toTimeString = function() { return (this.getHours() < 10 ? "0" + this.getHours() : this.getHours()) + ":" + (this.getMinutes() < 10 ? "0" + this.getMinutes() : this.getMinutes()) + ":" + (this.getSeconds() < 10 ? "0" + this.getSeconds() : this.getSeconds()); };

Number.prototype.toRemaining = function()
{
	var m = Math.ceil(this / 60000) + 2;
	return m <= 1 ? "1 minute" : (m < 60 ? m + " minutes" : (m / 60 <= 1 ? "1 hour" : (Math.floor(m / 60) <= 1 ? "1 hour" : Math.floor(m / 60) + " hours") + (m % 60 < 1 ? "" : (m % 60 == 1 ? " 1 minute" : " " + (m % 60) + " minutes"))));
};


$(window).load(function()
{
	var $loading = $("body>.loading:first");
	setTimeout(function() { $loading.animate({ opacity: 0 }, 1000, function() { $(this).remove(); }); }, 500);
});


var windowW = $(window).width(), windowH = $(window).height();


$(window).resize(function()
{
	windowW = $(window).width();
	windowH = $(window).height();
});


var map = new function()
{
	var
		$map = $('<div class="map"></div>').appendTo("body")
	,	mapW = (5500 - windowW) / 2
	,	mapH = (2100 - windowH) / 2
	,	angleX = Math.random() * 360
	,	angleY = Math.random() * 360
	,	speed = 0
	,	x = -Math.floor((Math.sin(angleX * Math.PI / 180) + 1) * mapW)
	,	y = -Math.floor((Math.cos(angleY * Math.PI / 180) + 1) * mapH)
	,	pause = false
	,	dragEndTimer = false
	,	markerPos = 0
	,	align = { "r": "", "l": " left", "br": " bottom-right", "bl": " bottom-left", "tr": " top-right", "tl": " top-left" }
	,	calign = { "l": " clients-left" }
	,	siteTypes = [ "many", "design", "programming", "marketing" ]
	;

	var showMarker = function()
	{
		if (markerPos < cities.length)
		{
			var m = cities[markerPos];
			var $m = $('<span class="city' + align[typeof m[3] == "string" ? m[3] : "r"] + (m[3] !== true && m[4] !== true ? ' city-capital' : '') + '" style="left: ' + m[1] + 'px; top: ' + m[2] + 'px"><span>' + m[0] + '</span></span>').appendTo($map);
			if (!$.browser.msie)
				$m.animate({ opacity: 1 }, 2000, function() { $(this).fixIE7(); });
		}

		if (markerPos < clients.length)
		{
			var m = clients[markerPos];
			var $m = $('<p class="clients' + (m[4] ? calign[m[4]] : '') + '" style="left: ' + m[0] + 'px; top: ' + m[1] + 'px; z-index: ' + m[1] + '"><em>' + m[3] + ' <span>(' + m[2] + ')</span></em></p>').appendTo($map);
			if (!$.browser.msie)
				$m.animate({ opacity: 1 }, 2000, function() { $(this).fixIE7(); });
			navigation.addMarker(m[0], m[1]);
		}

		if (markerPos < sites.length)
		{
			var m = sites[markerPos];
			var $m = $('<a target="_blank" class="site' + align[m[5] || "r"] + ' site-' + siteTypes[m[2]] + '" href="http://' + m[3] + '/" style="left: ' + m[0] + 'px; top: ' + m[1] + 'px; z-index: ' + m[1] + '"><span>' + m[4] + '</span></a>').appendTo($map);
			if (!$.browser.msie)
				$m.animate({ opacity: 1 }, 2000, function() { $(this).fixIE7(); });

			$m.mousemove(function() { speed = 2; });
		}

		if (markerPos < cities.length - 1 || markerPos < clients.length - 1 || markerPos < sites.length - 1)
		{
			markerPos++;
			setTimeout(showMarker, 25);
		}
	};

	this.resume = function()
	{
		if (dragEndTimer)
			clearTimeout(dragEndTimer);

		dragEndTimer = setTimeout(function()
		{
			dragEndTimer = false;
			$map.stop(true).animate({ left: x + "px", top: y + "px" }, 10000, function() { speed = 0; pause = false; });
			navigation.animateTo(x, y, 10000);
		}, 10000);
	};

	var moveMap = function()
	{
		if (pause)
			return;

		speed < 10 ? speed += 0.05 : speed = 10;
		angleX < 360 ? angleX += .01 * speed : angleX -= 360;
		angleY < 360 ? angleY += .003 * speed : angleY -= 360;

		x = -Math.floor((Math.sin(angleX * Math.PI / 180) + 1) * mapW);
		y = -Math.floor((Math.cos(angleY * Math.PI / 180) + 1) * mapH);

		$map.css({ left: x + "px", top: y + "px" });
		navigation.goTo(x, y);
	};

	$map
		.bind("mousedown", function() { pause = true; $map.stop(true); navigation.stop(); })
		.bind("drag", function(event)
		{
			$map.stop(true).animate({ left: event.offsetX + "px", top: event.offsetY + "px" }, 0);
			navigation.goTo(event.offsetX, event.offsetY);
		})
		.bind("mouseup dragend", function() { map.resume(); })
	;

	$(window).resize(function()
	{
		mapW = (5500 - windowW) / 2;
		mapH = (2100 - windowH) / 2;
	});

	this.animateTo = function(x, y, time) { pause = true; $map.stop(true).animate({ left: (-x + windowW / 2) + "px", top: (-y + windowH / 2) + "px" }, time); };
	this.goTo = function(x, y) { pause = true; $map.stop(true).css({ left: (-x) + "px", top: (-y) + "px" }); };
	this.getX = function() { return x; };
	this.getY = function() { return y; };
	this.stop = function() { pause = true; $map.stop(true); };
	this.showClients = function() { $map.attr("class", "map map-clients"); };
	this.showCities = function() { $map.attr("class", "map map-cities"); };
	this.showSites = function() { $map.attr("class", "map map-sites"); };

	$(window).load(function() { showMarker(); setInterval(moveMap, 33); });
};


var navigation = new function()
{
	var
		$navigation = $('<div class="navigation"><div><p class="map"><a><span class="top"></span><span class="right"></span><span class="bottom"></span><span class="left"></span></a></p><p class="controls">Show: <a class="clients">Our Clients</a> <a class="sites">Web resources</a> <a class="cities">Cities</a></p></div></div>').appendTo("body")
	,	$navigationWindow = $navigation.find("p.map>a")
	,	folded = false
	;

	var fold = function() { $navigation.stop(true).animate({ opacity: .15 }, 500).find("p.map:first").stop(true).animate({ marginTop: "-126px" }, 500); };
	var unfold = function() { $navigation.stop(true).animate({ opacity: 1 }, 500, function() { $(this).fixIE7(); }).find("p.map:first").stop(true).animate({ marginTop: 0 }, 500); };

	$navigation.find("p.controls a").click(function() { $(this).addClass("on").siblings().removeClass("on"); return false; });
	$navigation.find("p.controls a.clients").click(function() { map.showClients(); }).click();
	$navigation.find("p.controls a.cities").click(function() { map.showCities(); });
	$navigation.find("p.controls a.sites").click(function() { map.showSites(); });

	$navigation.find("p.map").click(function(event)
	{
		var pos = $(this).offset(), x = event.pageX - pos.left, y = event.pageY - pos.top;
		$navigationWindow.stop(true).animate({ left: (x - $navigationWindow.outerWidth() / 2) + "px", top: (y - $navigationWindow.outerHeight() / 2) + "px" }, 333);
		map.animateTo(x * 20, y * 20, 333);
		map.resume();
		return false;
	});

	$navigationWindow.css({ display: "block", left: (-map.getX() * .05) + "px", top: (-map.getY() * .05) + "px", width: (windowW * .05) + "px", height: (windowH * .05) + "px" })
		.click(function() { return true; })
		.bind("mousedown dragstart", function() { map.stop(); $navigationWindow.stop(true); })
		.bind("mouseup dragend", function() { map.resume(); })
		.bind("click", function() { return false; })
		.bind("drag", function(event)
		{
			var pos = $(this).parent().offset();
			var x = event.offsetX - pos.left;
			var y = event.offsetY - pos.top;

			map.goTo(x / 275 * 5500, y / 105 * 2100);
			$navigationWindow.stop(true).css({ left: x + "px", top: y + "px" });
		});
	;

	$(window).resize(function() { $navigationWindow.css({ width: Math.floor(windowW * .05) + "px", height: Math.floor(windowH * .05) + "px" }); });

	this.stop = function() { $navigationWindow.stop(true); };
	this.goTo = function(x, y) { $navigationWindow.stop(true).css({ left: (-x * .05) + "px", top: (-y * .05) + "px" }); };
	this.animateTo = function(x, y, time) { $navigationWindow.stop(true).animate({ left: (-x * .05) + "px", top: (-y * .05) + "px" }, time); };
	this.fold = function() { folded = true; fold(); };
	this.unfold = function() { folded = false; unfold(); };
	this.addMarker = function(x, y) { $('<span class="clients" style="left: ' + Math.round(x * .05) + 'px; top: ' + Math.round(y * .05) + 'px"></span>').appendTo($navigation.find("p.map:first")); };
};



var validation = new function()
{
	var
		self = this
	,	messages =
		{
			"required": "This field is mandatory."
		,	"max_length": "Text is too long."
		,	"valid_email": "This isn't valid e-mail address."
		,	"valid_address": "This isn't valid address."
		}
	,	functions =
		{
			"required": function(s) { return typeof s == "string" && s.length > 0; }
		,	"max_length": function(s, l) { return typeof s == "string" && s.length <= parseInt(l); }
		,	"valid_email": function(s) { return typeof s == "string" && s.match(/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/i); }
		,	"valid_address": function(s) { return typeof s == "string" && s.match(/^(?:(?:ht|f)tp(?:s?)\:\/\/|~\/|\/)?(?:\w+:\w+@)?(?:(?:[-\w]+\.)+(?:com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|travel|[a-z]{2}))(?::[\d]{1,5})?(?:(?:(?:\/(?:[-\w~!$+|.,=]|%[a-f\d]{2})+)+|\/)+|\?|#)?(?:(?:\?(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)(?:&(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)*)*(?:#(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)?$/i); }
		}
	;

	self.check = function(fields)
	{
		var result = true;
		for (var f in fields)
		{
			var rules = fields[f].rules.split("|");
			for (var r = 0; r < rules.length; r++)
			{
				var rule = rules[r], param = rule.indexOf("[");
				if (param > 0)
				{
					rule = rule.slice(0, param);
					param = rules[r].slice(param + 1);
					param = param.slice(0, param.length - 1);
				}

				if (!functions[rule](fields[f].value, param))
				{
					if (result === true)
						result = {};
					result[f] = messages[rule];
					break;
				}
			}
		}

		return result;
	};
};


$("ul.gallery").each(function()
{
	var $gallery = $(this), c = $gallery.children().length, t = 750;

	$gallery.wrap('<div class="gallery-clip"></div>').width(c * 345);
	$gallery.parent().before('<h3 class="alt"></h3><p class="gallery-nav gallery-nav-prev"><a>&lt;</a></p><p class="gallery-nav gallery-nav-next"><a>&gt;</a></p>');

	var $thumbs = $('<ul class="thumbnails"></ul>').appendTo($gallery.parent()).width(c * 88), $w = $gallery.closest(".window"), i = 0, $h = $w.find("h3:first");

	var galleryUpdate = function()
	{
		$h.text($gallery.find(">li:eq(" + i + ")>img").attr("title") + " (" + (i + 1) + "/" + c + ")");
		$thumbs.children().eq(i).children("a").addClass("selected").parent().siblings().children("a.selected").removeClass("selected");
	};

	$w.find("p.gallery-nav-prev a").click(function()
	{
		if (i > 0)
		{
			$gallery.stop(true).animate({ left: (--i * -345) + "px" }, t);
			if (c > 4 && i < c - 3)
				$thumbs.stop(true).animate({ left: (i * -88) + "px" }, t);
		}
		galleryUpdate();
		return false;
	});

	$w.find("p.gallery-nav-next a").click(function()
	{
		if (i < c - 1)
		{
			$gallery.stop(true).animate({ left: (++i * -345) + "px" }, t);
			if (c > 4 && i < c - 3)
				$thumbs.stop(true).animate({ left: (i * -88) + "px" }, t);
		}
		galleryUpdate();
		return false;
	});

	$gallery.children().each(function()
	{
		var $img = $(this).find("img");
		$('<li><a><img src="' + $img.attr("src") + '" title="' + $img.attr("title") + '"></a></li>').appendTo($thumbs).children("a").click(function()
		{
			i = $thumbs.children().index($(this).parent()) - 1;
			$gallery.stop(true).animate({ left: (++i * -345) + "px" }, t);
			if (c > 4)
				$thumbs.stop(true).animate({ left: ((i < c - 3 ? i : c - 4) * -88) + "px" }, t);
			galleryUpdate();
			return false;
		});
	});

	galleryUpdate();
});


var windows = new function()
{
	$("body").append
	(
		'<div class="window" id="window-time-zones"><div class="window"><div><p class="text-center"><img src="images/' + (IE6 ? 'ie6/' : '') + 'timezones_map.png" width="708" height="376" alt=""></p><p class="location">Poznań / Poland <span></span></p><p class="user-time">Your time is <strong></strong></p><p class="remaining-time"></p><p class="our-time">Merix Studio time is <strong></strong></p></div></div></div>'
	+	'<div class="window window-small" id="window-newsletter"><div class="window"><h2>Newsletter</h2><form action="" method="post"><p>Get exclusive previews of new projects.</p><p><input type="text" class="text" name="name" value="Your Name" size="64" maxlength="64"></p><p><input type="text" class="text" name="e-mail" value="Your e-mail address" size="48" maxlength="96"></p><p class="no-margin"><button type="submit"><span><span>Add</span></span></button></p></form></div></div>'
	+	'<div class="window window-small" id="window-newsletter-sent"><div class="window"><h2>Confirm subscription</h2><p>Thank you for signing up for our newsletter. Please check out your inbox to confirm subscription.</p><p class="no-margin"><button class="close"><span><span>Close</span></span></button></p></div></div>'
	+	'<div class="window window-small" id="window-sending"><div class="window"><h2>Sending message…</h2><p class="loading">Please wait, sending data to server.</p></div></div>'
	+	'<div class="window window-small" id="window-contact-sent"><div class="window"><h2>Thank You!</h2><p>Message has been sent! We will get back to you as soon as possible.</p><p>Hey, don\'t go away yet - there is still time to have some fun. <a href="http://www.merixstudio.com/mblocks">Play mBlocks now</a> - 100% JavaScript experience guaranteed!</p><p class="no-margin"><button class="close"><span><span>Close</span></span></button></p></div></div>'
	+	'<div class="window window-small" id="window-error-sending"><div class="window"><h2>Server error</h2><p>Message could not be sent because server error occurred. Please try again later.</p><p class="no-margin"><button class="close"><span><span>Close</span></span></button></p></div></div>'
	+	'<div class="window window-small" id="window-suggest"><div class="window"><h2>Suggest a site</h2><form action="" method="post"><p>If you know an interesting website that you believe should be added to our map, just give us its address and we\'ll do the rest!</p><p><input type="text" class="text" name="address" value="Website URL" size="64" maxlength="256"></p><p class="no-margin"><button type="submit"><span><span>Add</span></span></button></p></form></div></div>'
	+	'<div class="window window-small" id="window-suggest-sent"><div class="window"><h2>Thank you</h2><p>Your submission has been sent. We\'ll review it and if it meets our criteria it will be added to the World of Merix Studio map.</p><p class="no-margin"><button class="close"><span><span>Close</span></span></button></p></div></div>'
	);

	$("body>.footer").prepend('<div class="window window-special" id="window-legend"><div class="window"><h2>World map legend</h2><h3>Our Clients</h3><p><span class="marker marker-clients"></span> Number of Merix Studio clients in this country</p><h3>Web Resources</h3><ul><li class="left"><span class="marker marker-site-many"></span> Mixed content</li><li class="right"><span class="marker marker-site-design"></span> Web design</li><li class="left"><span class="marker marker-site-programming"></span> Web development</li><li class="right"><span class="marker marker-site-marketing"></span> Marketing, ePR, SEM</li></ul><h3>Cities</h3><ul><li class="left"><span class="marker marker-city-capital"></span> Capital city</li><li class="right"><span class="marker marker-city"></span> Large city</li></ul></div></div><p class="legend"><a href="#window-legend">Legend</a></p>');

	$("body>.header:first>ul").append('<li><a class="alt" href="#window-newsletter"><span>Newsletter</span></a></li>');

	var $windows = $("body>.window,body>.footer>.window"), h = {}, mt = {}, time = false, opened = {}, self = this;

	if (!$.browser.opera)
		$windows.filter("#window-contact").removeClass("window-small").children(".window").append('<div class="right"><h3>Contact Form</h3><form action="" method="post"><p><label for="contact-name">Your name:</label> <input type="text" class="text" id="contact-name" name="name" size="64" maxlength="64"></p><p><label for="contact-company">Company:</label> <input type="text" class="text" id="contact-company" name="company" size="64" maxlength="64"></p><p><label for="contact-e-mail">E-mail:</label> <input type="text" class="text" id="contact-e-mail" name="e-mail" size="48" maxlength="96"></p><p><label for="contact-message">Message:</label> <textarea rows="5" cols="80" id="contact-message" name="message"></textarea></p><p><button type="submit"><span><span>Send Message</span></span></button></p></form></div>');

	$windows.each(function()
	{
		$(this).prepend('<p class="close"><a>X</a></p>');
		var id = $(this).attr("id");
		h[id] = $(this).innerHeight() - parseInt($(this).css("padding-top")) - parseInt($(this).children(".window").css("padding-bottom"));
		mt[id] = (-$(this).outerHeight()) / 2;
		opened[id] = false;
	});

	$.fn.extend({ close: function()
	{
		navigation.unfold();
		$("body>.footer:first,body>.header:first").stop(true).animate({ opacity: 1 }, 750, function() { $(this).fixIE7(); });
		return $(this).each(function()
		{
			opened[$(this).attr("id")] = false;
			$(this).trigger("close");
			if (!$(this).hasClass("window-special"))
				$(this).animate({ opacity: 0 }, 500, function() { $(this).css({ display: "none" }).find(">.window>div").css({ opacity: 0 }); });
		});
	}});

	$windows.find(">p.close>a,button.close").click(function() { var $w = $(this).parents(".window:last").close(); var $f = $w.find("form"); if ($f.length) $f[0].reset(); $f.find("p.error").remove(); });
	$windows.find("button[type=reset]").click(function() { $(this).closest("form").find("p.error").remove(); });

	self.open = function(id)
	{
		if (opened[id])
			return;

		$windows.not("#" + id).close();
		opened[id] = true;
		var $w = $windows.filter("#" + id);

		if (!$w.hasClass("window-special"))
		{
			navigation.fold();
			$("body>.footer,body>.header").stop(true).animate({ opacity: .15 }, 750);//.find('*').fold();

			$w.children(".window").removeAttr("style");
			h[id] = $w.innerHeight() - parseInt($w.css("padding-top")) - parseInt($w.children(".window").css("padding-bottom"));
			mt[id] = (-$w.outerHeight()) / 2;

			$w.children(".window").height(0).children().stop(true).css({ opacity: 0 });
			$w.trigger("open").css({ display: "block", marginTop: "-40px" }).stop(true).animate({ opacity: 1 }, 750, function() { $(this).fixIE7().animate({ marginTop: mt[id] + "px" }, 750).children(".window").animate({ height: h[id] + "px" }, 750).children().animate({ opacity: 1 }, 2000, function() { $(this).fixIE7(); }); });
		}
		else
			$w.trigger("open");

	};

	this.toggle = function(id) { if (opened[id]) $windows.filter("#" + id).close(); else self.open(id); };

	this.recalcHeight = function(id)
	{
		var $w = $windows.filter("#" + id);

		var oldH = $w.children(".window").height();
		$w.children(".window").removeAttr("style");
		h[id] = $w.innerHeight() - parseInt($w.css("padding-top")) - parseInt($w.children(".window").css("padding-bottom"));
		mt[id] = (-$w.outerHeight()) / 2;
		$w.children(".window").height(oldH);

		$w.animate({ marginTop: mt[id] + "px" }, 750).children(".window").animate({ height: h[id] + "px" }, 750);
	};

	this.get = function(name) { return $windows.filter("#window-" + name); };

	this.get("time-zones")
		.bind("open", function()
		{
			if (time)
				clearInterval(time);

			var $w = $(this);
			time = setInterval(function()
			{
				var d = new Date();

				$w.find(".user-time strong").text(d.toTimeString());

				var m = d.getTime() + (d.getTimezoneOffset() * 60000) + (1 + daylightSaving()) * 3600000;
				m = new Date(m);
				$w.find(".our-time strong").text(m.toTimeString());
				$w.find(".location span").text(m.toTimeString() + " UTC+1");

				if (m.getHours() >= 8 && m.getHours() < 16 && m.getDay() != 6 && m.getDay() != 0)
				{
					var n = new Date(d.getFullYear(), d.getMonth(), d.getDate(), 16, 0, 0);
					$w.find(".remaining-time").html('Our office is now open and will close at <strong>16:00 UTC+1</strong>.<br>Remaining ' + (n.getTime() - m.getTime() - 2 * 60000).toRemaining() + '.');
				}
				else
				{
					var day = m.getHours() < 8 ? m.getDate() : (m.getDay() >= 5 || m.getDay() == 0 ? m.getDate() + (m.getDay() >= 5 ? 8 - m.getDay() : 1) : m.getDate() + 1)
					var n = new Date(d.getFullYear(), d.getMonth(), day, 8, 0, 0);
					$w.find(".remaining-time").html('Our office will be opened ' + (m.getDay() >= 5 || m.getDay() == 0 ? 'on Monday ' : '') + 'at <strong>8:00 UTC+1</strong>.<br>Remaining ' + (n.getTime() - m.getTime() - 2 * 60000).toRemaining() + '.');
				}
			}, 500);
		})
		.bind("close", function()
		{
			if (time)
			{
				clearInterval(time);
				time = false;
			}
		})
	;

	this.get("legend")
		.bind("open", function()
		{
			var $w = $(this), m = -$w.outerHeight();
			$w.css({ display: "block", marginTop: (m - m / 8) + "px" }).stop(true).animate({ opacity: 1, marginTop: m + "px" }, 750, function() { $(this).fixIE7(); });
		})
		.bind("close", function() { $(this).animate({ opacity: 0 }, 500, function() { $(this).css({ display: "none" }).find(">.window>div").css({ opacity: 0 }); }); })
	;


	var validateForm = function($form, fields, name, data)
	{
		var result = validation.check(fields);
		$form.find("p.error").remove();

		if (result === true)
		{
			windows.open("window-sending");
			data["first-rule-of-fight-club"] = "you-dont-talk-about-fight-club";
			$.post(name, data, function(result)
			{
				if (result.status)
					windows.open("window-" + name + "-sent");
				else
				{
					var $e = {}, any = false;
					for (var err in result.errors)
					{
						$e[err] = $('<p class="error' + (err == "message" ? ' error-alt' : '') + '">' + result.errors[err] + '</p>').insertAfter($form.find("[name='" + err + "']").parent()).css("visibility", "hidden");
						any = true;
					}

					if (any)
					{
						windows.recalcHeight("window-" + name);
						for (var err in $e)
							$e[err].css("visibility", "visible").animate({ height: "hide", opacity: 0 }, 0).animate({ height: "show", opacity: 1 }, 500);
					}
					else
						windows.open("window-error-sending");
				}
			}, "json");
		}
		else
		{
			var $e = {};
			for (var r in result)
				$e[r] = $('<p class="error' + (r == "message" ? ' error-alt' : '') + '">' + result[r] + '</p>').insertAfter($form.find("[name='" + r + "']").parent()).css("visibility", "hidden");
			windows.recalcHeight("window-" + name);
			for (var e in $e)
				$e[e].animate({ height: "hide", opacity: 0 }, 0).animate({ height: "show", opacity: 1 }, 500).css("visibility", "visible");
		}
	};


	var $contact = this.get("contact").find("form:first").submit(function()
	{
		var d =
		{
			"name": $(this).find("input[name='name']").typedVal()
		,	"company": $(this).find("input[name='company']").typedVal()
		,	"e-mail": $(this).find("input[name='e-mail']").typedVal()
		,	"message": $(this).find("textarea[name='message']").typedVal()
		};

		validateForm($contact,
		{
			"name": { "value": d["name"], "rules": "required|max_length[64]" }
		,	"company": { "value": d["company"], "rules": "max_length[64]" }
		,	"e-mail": { "value": d["e-mail"], "rules": "required|max_length[64]|valid_email" }
		,	"message": { "value": d["message"], "rules": "required|max_length[1024]" }
		}, "contact", d);

		return false;
	});


	var $newsletter = this.get("newsletter").find("form:first").submit(function()
	{
		var d =
		{
			"name": $(this).find("input[name='name']").typedVal()
		,	"e-mail": $(this).find("input[name='e-mail']").typedVal()
		};

		validateForm($newsletter,
		{
			"name": { "value": d["name"], "rules": "required|max_length[64]" }
		,	"e-mail": { "value": d["e-mail"], "rules": "required|max_length[64]|valid_email" }
		}, "newsletter", d);

		return false;
	});

	var $suggest = this.get("suggest").find("form:first").submit(function()
	{
		var d = { "address": $(this).find("input[name='address']").typedVal() };
		validateForm($suggest, { "address": { "value": d["address"], "rules": "required|max_length[256]|valid_address" } }, "suggest", d);
		return false;
	});
};


$(":text,textarea").each(function()
{
	this.defaultText = this.value;
	$(this)
		.focus(function() { if (this.value == this.defaultText) this.value = ""; })
		.blur(function() { if (this.value == "" && this.defaultText) this.value = this.defaultText; });
});


var loc = window.location.href;

if (loc.indexOf("#") >= 0)
{
	loc = loc.substr(loc.indexOf("#") + 1);
	if (loc.length)
		windows.open(loc);
}

$("body>.footer p.right").append(' | <a href="#window-suggest">Suggest a site</a>');
$("a[href*='#window-']").click(function() { windows.toggle($(this).hrefId().substr(1)); return false; });

if ($.browser.msie && $.browser.version <= 6)
{
	$("body>.header:first,body>.footer:first").bind("mouseenter mouseleave", function() { $(this).toggleClass("hover"); });
	$("a:not([href])").attr("href", "#");
}

Cufon.replace(".window h2", { fontFamily: "Haptic Light" });
Cufon.replace(".header ul a,.footer ul a", { fontFamily: "Haptic Regular", hover: true });