$.ajaxSetup({
  dataFilter:function(data, type) {
    if ((typeof type == 'undefined' || type == 'html') && data.match(/SESSION TIMEOUT/) == 'SESSION TIMEOUT') {
      Overlay.close()
      window.top.location = '/sessions/login'
      return ""
    }else{
      return data;
    }
  }
})

/*Skifta - Friends*/
var Friends = (function(){
  // Private
  if(typeof String.prototype.trim !== 'function'){
    String.prototype.trim = function(){
      return this.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); 
    }
  }
  
  var doSearch = true

  function doFind() { return doSearch }

  function find(){
    if (doSearch) {
      $('#found-friends').html(AjaxLoader.element('Searching...'))
      var search_string = $("#search_string").val().trim();
      if(search_string == ""){
        $('#found-friends').html("<span class='error'>Please enter a friend's name</span>")
      } else {
        doSearch = false
        $.get('/find-friends/' + search_string, function(data){  
          $('#found-friends').html(data)
          doSearch = true
        })
      }
    }
    return false
  };
  
  function add(link, username, email){
    var postdata = { 'username':username, 'email':email }
    $.post('/add-friend', postdata, function(data){
      if(data == "Added"){
        var message = "<span>" + data + "</span>"
        $(link).replaceWith(message);
      }else{
        // TODO: Make this a jalert?
        $(link).replaceWith("We could not add this user at this time");
      } 
    })
    return false;
  };
  
  function confirmSingle(username){
    var postdata = { 'username':username }
    $.post('/confirm-friend', postdata, function(data){ 
      if(data == "Confirmed"){
        document.location = "/my-account"
      }else{
        // TODO: Make this a jalert?
        $(link).replaceWith("We could not accept this user at this time");
      }
    })
    return false;
  };
  
  function confirmAll(usernames){
    var postdata = { 'usernames': usernames }
    $.post('/confirm-all-friends', postdata, function(data){
      document.location = "/my-account"
    })
    return false
  };
  
  function remove(username){
    jConfirm("Are you sure you want to remove this friend?", 'Confirmation Dialog', function(r) {
      if(r){
        var postdata = { 'username':username }
        $.post('/remove-friend', postdata, function(data){ 
          if(data == "Removed"){
            document.location = "/my-account"
          }else{
            // TODO: Make something instead of an alert
            $(link).replaceWith("We could not remove this user at this time");
          }
        })
      }
    });
    return false;
  };
  
  function removePending(username){
    jConfirm("Are you sure you want to remove this friend request?", 'Confirmation Dialog', function(r) {
      if(r){
        var postdata = { 'username':username }
        $.post('/remove-pending-friend', postdata, function(data){ 
          if(data == "Removed"){
            document.location = "/my-account"
          }else{
            // TODO: Make something instead of an alert
            $(link).replaceWith("We could not remove this user at this time");
          }
        })
      }
    });
    return false;
  };
  // Public
  return {  
    Find:function(){
      return find();
    },
    
    Add:function(link, username, email){
      return add(link, username, email);
    },
    
    Confirm:function(username){
      return confirmSingle(username);
    },
    
    ConfirmAll: function(usernames){
      return confirmAll(usernames);
    },
    
    Remove:function(username){
      return remove(username);
    },
    
    RemovePending:function(username){
      return removePending(username);
    }
  }
})();

/*Skifta - Modal*/
var Modal = (function(){
  // Private
  function showRegister(){
    var holder = parent.document.getElementById('modal-holder');
    $(holder).removeClass('login-holder').addClass('register-holder');
    document.location = "/modal-register-form";
  };
  
  function submitRegister(f){
    var validator = f.validator()
    if (validator.data("validator").checkValidity()) {
      showSending();
      $.post("/registration", $(f).serialize(), function(data){ 
        switch(data){
          case "OK":
            parent.document.location = "/register-message";
            break;
          default:
            $('#register-form-holder').html(data);
            break;
        }
      })
    }
    return false;
  };
  
  function submitLogin(f){
    var validator = f.validator();
    if (validator.data("validator").checkValidity()) {
      $.post("/sessions/login", $(f).serialize(), function(data){ 
        switch(data){
          case "OK":
            parent.document.location = $('#login-referer').val();
            break;
          case "NOT_ACTIVE":
            parent.document.location = "/register-message";
            break;
          default:
            $('#login-form-holder').html(data);
            break;
        }
      })
    }
    return false;
  };
  
  function submitForgotUsername(f){
    var validator = f.validator();
    if (validator.data("validator").checkValidity()) {
      $.post("/forgotten-username", $(f).serialize(), function(data){ 
        switch(data){
          case "OK":
            document.location = "/modal-forgotten-username-sent";
            break;
          default:
            $('#forgot-username-form-holder').html(data);
            break;
        }       
      })
    }
    return false;
  };
  
  function submitForgotPassword(f){
    var validator = f.validator();
    if (validator.data("validator").checkValidity()) {
      $.post("/forgotten-password", $(f).serialize(), function(data){ 
        switch(data){
          case "OK":
            document.location = "/modal-forgotten-password-sent";
            break;
          default:
            $('#forgot-password-form-holder').html(data);
            break;
        }       
      })
    }
    return false;
  };
  
  function showSending(){
    
  }
    
  function goToPage(url){
    parent.document.location = url;
  };
  
  // Public
  return {  
    ShowRegister:function(){
      showRegister();
    },
    
    SubmitRegister:function(f){
      Pages.removeElement("#error-message");
      submitRegister(f);
      return false
    },
    
    SubmitLogin:function(f){
      Pages.removeElement(".error-message");
      submitLogin(f);
      return false;
    },
    
    SubmitForgotUsername:function(f){
      Pages.removeElement(".error-message");
      submitForgotUsername(f);
      return false;
    },
    
    SubmitForgotPassword:function(f){
      Pages.removeElement(".error-message");
      submitForgotPassword(f);
      return false;
    },
    
    SubmitEditDetails:function(f){
      Pages.removeElement(".error-message");
      submitEditDetails(f);
    },
    
    GoToPage:function(url){
      goToPage(url);
    },
    
    ShowSending:function(){
      showSending();
    }
  }
})();

/*Skifta - Channel*/
var Channel = (function(){
  var CHANNEL_REMOVAL_MSG = "Are you sure you'd like to remove this channel?\nYou will need to download and where applicable pay for this channel again should you wish to use it in the future.\n\n"
  var LOADER = '<img src="/images/ajax-loader1.gif" class="loader">';
  // Private
  
  // Public
  return {  
    windowObj: null,
    
    removeForUser: function(channel_id, link) {
      var original =  $(link).parent("div.channel-status").html();
      $(link).unbind('click').addClass("deactivated");
      $(link).find("span").html("Removing...");
      $(link).parent("div.channel-status").append(LOADER);
      
      var redirect = document.location
      jConfirm(CHANNEL_REMOVAL_MSG, 'Confirmation Dialog', function(r) {
        if (r){
          $.post('/channels/' + channel_id + '/remove', {}, function(data){
            document.location = redirect;
          });
        }else{
          $(link).parent("div.channel-status").html(original);
        }
      });
      return false
    },
    
    addRemoveDomains:function(){
      // Reset domain id's
      $("#add_to_domain_ids").val('');
      $("#remove_from_domain_ids").val('');
      var add_to_domain_ids = [];
      var remove_from_domain_ids = [];
      // Loop through checked boxes
      $("input:checkbox").each(function(index) {
        if($(this).is(':checked')){
          add_to_domain_ids.push($(this).val());
        }else{
          remove_from_domain_ids.push($(this).val());
        }
      })
      // Add domain ids to input box
      $('#add_to_domain_ids').val(add_to_domain_ids.join(","));
      $('#remove_from_domain_ids').val(remove_from_domain_ids.join(","));
      return true;
    },
        
    addChannelWithConfig:function(channel_id){
      $.get('/session_alive', function(data) {
        if(data != ""){
          var url = "/channel/" + channel_id + "/configure"
          Channel.configOverlay(url);
        }
      })
      return false
    },
    
    addChannelWithoutConfig:function(channel_id, link){
      // Deactivate link
      $(link).unbind('click').addClass("deactivated");
      $(link).find("span").html("Adding channel...");
      $(link).parent("div.channel-status").append(LOADER);
      
      $.get('/session_alive', function(data) {
        if(data != ""){
          // Send channel stuff
          var url = "/channel/" + channel_id + "/add"
          $.post(url, function(data) {
            location = data
          });
        }
      })
      return false;
    },
    
    configOverlay:function(url){
      $("#overlay").addClass("config-modal");
      // save the overlay element
      Overlay.element = $("#overlay");
       
      // load overlay
      $("#overlay").overlay({
        mask: '#000',
        api: true,
        load: true,
        fixed: false,
        speed: 'fast',
        onBeforeLoad: function() {
          this.getOverlay().find("#overlay-target").load(url);
        },
        onClose:function(){
          this.getOverlay().find("#overlay-target").html('');
          $("#overlay").removeClass("config-modal");
          location = "/channels";
        }
      });
    }

  }
})();

/*Skifta - Source*/
var Source = {
  select:function(source_id, device_id){
    Target.showLoading();
    Shift.resetConnect();
    $.get('/use-skifta/source/' + source_id + '/device/' + device_id, function(data){ 
      $('#new-connection-destination').html(data);
      // Reset the target browsers treeview
      Target.setTreeView();
    })
    return false
  },
  
  setTreeView:function(){
    // Treeview
	  $("#sources-browser").treeview({
		  collapsed: true
	  });
	  $("#sources-browser span.file a").click(function(){
		   p = $(this).parent();
		   $("#sources-browser span.file").not(p).css('background','#eeeef2');
		   p.css('background','#A7A7BF');
		});
  }
  
}

/*Skifta - Target*/
var Target = {
  select:function(source_id, device_id, target_id, username){
    postdata = {'source_id':source_id, 'device_id':device_id, 'target_id':target_id, 'username':username}
    $.post('/use-skifta/target', postdata, function(data){ 
      $('#new-connection-connect').html(data);
    })
    return false;
  },
  
  setTreeView:function(){
    $("#targets-browser").treeview({
	    collapsed: true
    });
    //Treeview Selected
    $("#targets-browser div.file a").click(function(){
       p = $(this).parent();
       $("#targets-browser div.file").not(p).css('background','#eeeef2');
       p.css('background','#A7A7BF');
    });
  },
  
  showLoading:function(){
    $("#new-connection-destination").html(AjaxLoader.element('Loading destinations'));
  }
}

/*Skifta - Shift*/
var Shift = {
  start:function(fromSelection, shift_data){
    if(fromSelection){
      Shift.showLoading();
    }
    $.post('/use-skifta/connect', shift_data, function(data){ 
      if(fromSelection){
        $('#new-connection-connect').html(data)
      }
      Shift.connected();
    })
    return false;
  },
  
  stop:function(shift_data){
    jConfirm("Are you sure you want to stop this shift?", 'Confirmation Dialog', function(r) {
      if (r){
        $.post('/use-skifta/disconnect', shift_data, function(data){
          Shift.connected();
        })
      }
    });
    return false
  },
  
  connected:function(){
    $.get('/use-skifta/connections', function(data){
      $('#current-connections').html(data);
      Shift.updateFavourites();
      Shift.updateRecent();
    });
  },
  
  addFavourite : function(el, favourite_data) {
    $(el).removeClass('favourite-off')
	  $(el).addClass('favourite-on')
	  $(el).attr('title','Remove this favorite connection')
    $.post('/use-skifta/add-favourite', favourite_data, function(data) {
      if (data == 'FAIL') {
        $('#favourites').append('<span class="error">Could not add this favorite</span>')
        $(el).removeClass('favourite-on')
	      $(el).addClass('favourite-off')
        setTimeout("$('#favourites span.error').remove()", 3000)
      } else {
        Shift.updateFavourites();
      }
    });
    return false;
  },
  
  updateFavourites:function(){
    var api = $("ul.tabs").data("tabs");
 	  var selectedTab = api.getIndex();
    $.get('/use-skifta/favourites', function(data){
      $('#favourites').html(data)
      $("ul.tabs").tabs("div.panes > div", {
        tabs:'li',
        initialIndex:selectedTab
      });
    });
  },
      
  updateRecent:function(){
    var api = $("ul.tabs").data("tabs");
 	  var selectedTab = api.getIndex();
    $.get('/use-skifta/recent-connections', function(data){
      $('#recent-connections').html(data)
      $("ul.tabs").tabs("div.panes > div", {
        tabs:'li',
        initialIndex:selectedTab
      });
    })
  },
  
  removeFavourite : function(el, favourite_data) {
    jConfirm("Are you sure you want to remove this favourite?", 'Confirmation Dialog', function(r) {
      if (r){
        $(el).removeClass('favourite-on')
	      $(el).addClass('favourite-off')
	      $(el).attr('title','Add as a favorite connection')
        $.post('/use-skifta/remove-favourite', favourite_data, function(data) {
          if (data == 'FAIL') {
            $('#favourites').append('<span class="error">Could not remove this favorite</span>')
            $(el).removeClass('favourite-off')
	          $(el).addClass('favourite-on')
            setTimeout("$('#favourites span.error').remove()", 3000)
          } else {
            Shift.updateFavourites();
          }
        });
      }
    });
    return false;
  },
  
  toggleFavourite : function(el, favourite_data) {
    var retVal = $(el).hasClass("favourite-off") ?
    this.addFavourite(el, favourite_data) : this.removeFavourite(el, favourite_data);
    return retVal;
  },
  
  startFavOrRecent : function(el, favourite_data) {
    $(el).parent().html('<img src="/images/ajax-loader.gif" alt="Loading...">');
    return Shift.start(false, favourite_data);
  },
  
  resetConnect:function(){
    var text = $("<p class=\"new-connection-info\">Select a source & destination then hit connect.</p>");
    $("#new-connection-connect").html(text);
  },
  
  showLoading:function(){
    $("#new-connection-connect").html(AjaxLoader.element('Starting connection'));
  }
}

/*Skifta - Event*/

var Event = {
  clear_recent_shifts:function(){
    $.post('/use-skifta/clear-recent-connections', {}, function(data){
      $('#recent-connections').html(data)
    })
    return false
  }
}

/*Skifta - Overlay*/
var Overlay = {
  // List of overlay handlers 
  element: null,
  
  init:function(){
    // register the click event for ajax load and page load
    $("a[rel='#overlay'], a[rel='#learn-overlay']").live('click', function (e) {
      e.preventDefault();
      // save the overlay element
      Overlay.element = $(this); 
      // load overlay
      $(this).overlay({
        mask: '#000',
        api: true,
        load: true,
        fixed: false,
        speed: 'fast',
        onBeforeLoad: function() {
          this.getOverlay().find("#overlay-target").load(this.getTrigger().attr("href"));
        },
        onClose:function(){
          this.getOverlay().find("#overlay-target").html('');
        }
      });
    });
  },
    
  close:function(){
    if(Overlay.element != null)
      Overlay.element.overlay().close();
  }
};

/*Skifta - Pages*/
var Pages = {
  clearPasswordStrength:function(){
    $("span.testresult span").html("");
  },
  
  flashMessage:function(){
	  $(".flash-notice").delay(5000).fadeOut(400);
  },
  
  removeElement:function(el){
    $(el).remove();
  }
};

/*Skifta - AjaxLoader*/

var AjaxLoader = {
  element : function(msg) {
    return $('<p class="loader">'+msg+'<br /><img src="/images/ajax-loader.gif" alt="Loading..."></p>')
  },
  show : function(el) {
    $(el).append($('<div id="ajax-loader"></div>'))
    $("#ajax-loader").css('display','block')
  },
  hide: function() {
    $("#ajax-loader").css('display','none')
  }
};

var Hero = {
  items: [],
  current: -1,
  
  loadXml:function(){
    $.ajax({
      type: "GET",
      url: "/xml/hero.xml",
      dataType: "xml",
      success: function(xml) {
        Hero.processXml(xml);
      }
    });
  },
  
  processXml:function(xml){
    var banners = $(xml).find('item');
    banners.each(function(i){
      Hero.items[i] = Hero.createItem(i, $(this));
      Hero.createNumber(i);
    });
    Hero.embedItem();
    Hero.fadeAction();
  },
  
  createItem:function(i, item){
    var obj = {}
    obj.link = item.find('link').text();
    obj.text = item.find('text').text();
    obj.img = item.find('image').text();
    return obj;
  },
  
  createNumber:function(i){
    var html = '<li>';
    html += '<a href="#" onclick="Hero.show(' + i + '); return false">';
    html += i + 1;
    html += '</a>';
    html += '</li>';
    $("div#hero ul#numbers").append(html);
  },
  
  embedItem:function(){
    var i = Hero.current + 1;
    if(i > Hero.items.length - 1){
      i = 0;    
    }
    var obj = Hero.items[i];
    $("div#hero div#banner").html("");
    var html = '<a href="' + obj.link + '" style="display:none;" class="fadeable">';
    html += '<img src="' + obj.img + '" alt="' + obj.text + '" onload="Hero.fadeAction();" />';
    html += '</a>';
    $("div#hero div#banner").html(html);
    Hero.setNumber(i);
    Hero.current = i;
  },
  
  setNumber:function(i){
    $("div#hero ul#numbers li a").each(function(index) {
      if(i == index){
        $(this).addClass("active");
      }else{
        $(this).removeClass("active");
      }
    });
  },
  
  fadeAction:function(){
    var e = $("div#hero .fadeable");
    e.fadeIn(800).
      delay(5000).
      fadeOut('slow', function(){
        Hero.embedItem();
      }
    );
  },
  
  show:function(i){
    if(i != Hero.current){
      $("div#hero .fadeable").clearQueue();
      Hero.current = (i - 1);
      $("div#hero .fadeable").fadeOut('slow', function(){
        Hero.embedItem();
      });
    }
  }
};


var Hero = {
  items: [],
  current: -1,
  
  loadXml:function(){
    $.ajax({
      type: "GET",
      url: "/xml/hero.xml",
      dataType: "xml",
      success: function(xml) {
        Hero.processXml(xml);
      }
    });
  },
  
  loadInternationalXml:function(){
    $.ajax({
      type: "GET",
      url: "/xml/internationalHero.xml",
      dataType: "xml",
      success: function(xml) {
        Hero.processXml(xml);
      }
    });
  },
  
  processXml:function(xml){
    var banners = $(xml).find('item');
    banners.each(function(i){
      Hero.items[i] = Hero.createItem(i, $(this));
      Hero.createNumber(i);
    });
    Hero.embedItem();
    Hero.fadeAction();
  },
  
  createItem:function(i, item){
    var obj = {}
    obj.link = item.find('link').text();
    obj.text = item.find('text').text();
    obj.img = item.find('image').text();
    return obj;
  },
  
  createNumber:function(i){
    var html = '<li>';
    html += '<a href="#" onclick="Hero.show(' + i + '); return false">';
    html += i + 1;
    html += '</a>';
    html += '</li>';
    $("div#hero ul#numbers").append(html);
  },
  
  embedItem:function(){
    var i = Hero.current + 1;
    if(i > Hero.items.length - 1){
      i = 0;    
    }
    var obj = Hero.items[i];
    $("div#hero div#banner").html("");
    var html = '<a href="' + obj.link + '" style="display:none;" class="fadeable">';
    html += '<img src="' + obj.img + '" alt="' + obj.text + '" onload="Hero.fadeAction();" />';
    html += '</a>';
    $("div#hero div#banner").html(html);
    Hero.setNumber(i);
    Hero.current = i;
  },
  
  setNumber:function(i){
    $("div#hero ul#numbers li a").each(function(index) {
      if(i == index){
        $(this).addClass("active");
      }else{
        $(this).removeClass("active");
      }
    });
  },
  
  fadeAction:function(){
    var e = $("div#hero .fadeable");
    e.fadeIn(800).
      delay(5000).
      fadeOut('slow', function(){
        Hero.embedItem();
      }
    );
  },
  
  show:function(i){
    if(i != Hero.current){
      $("div#hero .fadeable").clearQueue();
      Hero.current = (i - 1);
      $("div#hero .fadeable").fadeOut('slow', function(){
        Hero.embedItem();
      });
    }
  }
};








/* Getting Started */
var GetStarted = {
  items: [],
  current: -1,
  
  loadXml:function(){
    $.ajax({
      type: "GET",
      url: "/xml/get-started.xml",
      dataType: "xml",
      success: function(xml) {
        GetStarted.processXml(xml);
      }
    });
  },
  
  processXml:function(xml){
    var learning = $(xml).find('item');
    learning.each(function(i){
      GetStarted.items[i] = GetStarted.createItem(i, $(this));
      GetStarted.createNumber(i);
    });
    GetStarted.embedItem();
    GetStarted.fadeAction();
  },
  
  createItem:function(i, item){
    var obj = {}
	obj.map = item.find('map').text();
	obj.maptwo = item.find('maptwo').text();
    obj.link = item.find('link').text();
	obj.linktwo = item.find('linktwo').text();
	obj.text = item.find('text').text();
    obj.img = item.find('image').text();
    return obj;
  },
  
  createNumber:function(i){
    var html = '<li>';
    html += '<a href="#" onclick="GetStarted.show(' + i + '); return false">';
    html += i + 1;
    html += '</a>';
    html += '</li>';
    $("div#getstarted ul#numbers").append(html);
  },
  
  embedItem:function(){
    var i = GetStarted.current + 1;
    if(i > GetStarted.items.length - 1){
      i = 0;    
    }
    var obj = GetStarted.items[i];
    $("div#getstarted div#learning").html("");
    var html = '<h2>' + obj.text + '</h2>';
	
    html += '<a href="#" class="fadeable" style="cursor:default">';
    html += '<img src="' + obj.img + '" onload="Hero.fadeAction();" usemap="#Map" />';
    html += '</a>';

    html += '<map name="Map" id="Map">';
    html += '<area shape="rect" coords="' + obj.map + '" href="' + obj.link + '" target="_blank" />';
    html += '<area shape="rect" coords="' + obj.maptwo + '" href="' + obj.linktwo + '" target="_blank" />';
    html += '</map>';
	
	
    $("div#getstarted div#learning").html(html);
    GetStarted.setNumber(i);
    GetStarted.current = i;
  },
   
  setNumber:function(i){
    $("div#getstarted ul#numbers li a").each(function(index) {
      if(i == index){
        $(this).addClass("active");
      }else{
        $(this).removeClass("active");
      }
    });
	
	  if(GetStarted.current == -1){
	    $("div#previous").hide();
	    }else{$("div#previous").show();
	  }
	
	  if(GetStarted.current == 6){
	    $("div#next").hide();
	    }else{$("div#next").show();
	  };	
  },
  
  fadeAction:function(){
    var e = $("div#getstarted .fadeable");
    e.fadeIn(800).pause().fadeOut('slow', function(){
        GetStarted.embedItem();
      }
    );
  },
  
  show:function(i){
    if(i != GetStarted.current){
      $("div#getstarted .fadeable").clearQueue();
      GetStarted.current = (i - 1);
      $("div#getstarted .fadeable").fadeOut('slow', function(){
        GetStarted.embedItem();
      });
    }
  }
};

/*Twitter API functions*/
var Twitter = (function(){
  // Private
  function processTweets(tweets){
    var statusHTML = [];
    for (var i=0; i<tweets.length; i++){
      var username = tweets[i].user.screen_name;
      var user_img = tweets[i].user.profile_image_url;
      var status = tweets[i].text.replace(/((https?|s?ftp|ssh)\:\/\/[^"\s\<\>]*[^.,;'">\:\s\<\>\)\]\!])/g, function(url){
        return '<a href="'+url+'">'+url+'</a>';
      }).replace(/\B@([_a-z0-9]+)/ig, function(reply){
        return  reply.charAt(0)+'<a href="http://twitter.com/'+reply.substring(1)+'">'+reply.substring(1)+'</a>';
      });
      statusHTML.push('<div class="tweet"><img src="' + user_img + '" alt="" /><p>'+status+'</p><p><a href="http://twitter.com/'+username+'/statuses/'+tweets[i].id+'">'+relativeTime(tweets[i].created_at)+'</a></p><div class="clear"></div></div>');
    }
    document.getElementById('tweets').innerHTML = statusHTML.join('');
  };
  
  function relativeTime(time_value){
    var values = time_value.split(" ");
    time_value = values[1] + " " + values[2] + ", " + values[5] + " " + values[3];
    var parsed_date = Date.parse(time_value);
    var relative_to = (arguments.length > 1) ? arguments[1]:new Date();
    var delta = parseInt((relative_to.getTime() - parsed_date) / 1000);
    delta = delta + (relative_to.getTimezoneOffset() * 60);
    if (delta < 60){
      return 'less than a minute ago';
    } else if(delta < 120){
      return 'about a minute ago';
    } else if(delta < (60*60)){
      return (parseInt(delta / 60)).toString() + ' minutes ago';
    } else if(delta < (120*60)){
      return 'about an hour ago';
    } else if(delta < (24*60*60)){
      return 'about ' + (parseInt(delta / 3600)).toString() + ' hours ago';
    } else if(delta < (48*60*60)){
      return '1 day ago';
    } else {
      return (parseInt(delta / 86400)).toString() + ' days ago';
    }
  };
  // Public
  return {  
    init: function() {
      var script = document.createElement('script')
      script.type = 'text/javascript'
      script.src = 'http://twitter.com/statuses/user_timeline/skifta.json?callback=Twitter.Callback&count=3'
      $("body").append(script)
    },
    Callback:function(tweets){
      processTweets(tweets);
    }
  }
})();

/*Share This API functions*/
var ShareThisAPI = (function(){
  // Private
  function createButton(){
    //Create your sharelet with desired properties and set button element to false
    var object = SHARETHIS.addEntry({
      title:'Share',
      summary: 'Sharing is good for the soul.'},
      {button:false}
    );
    if(object != null){
      //Output your customized button
      $('#sharethis-holder').html('<a id="share" href="javascript:void(0);" class="share">Share this</a>');
      //Tie customized button to ShareThis button functionality.
      var element = document.getElementById("share");
      object.attachButton(element);
    }
  };
  // Public
  return {  
    init:function(){
      $.getScript('http://w.sharethis.com/button/sharethis.js?publisher=491572f3-f324-4ebf-bd28-7ca53839ba89&amp;type=website&amp;post_services=email%2Cfacebook%2Ctwitter%2Cgbuzz%2Cmyspace%2Cdigg%2Csms%2Cwindows_live%2Cdelicious%2Cstumbleupon%2Creddit%2Cgoogle_bmarks%2Clinkedin%2Cbebo%2Cybuzz%2Cblogger%2Cyahoo_bmarks%2Cmixx%2Ctechnorati%2Cfriendfeed%2Cpropeller%2Cwordpress%2Cnewsvine', function() {
        createButton();
      });
    }
  }
})();

/****************************
 Jquery Tools - Tabs*/

// Tabs effect for adding the current css to the parent element
$.tools.tabs.addEffect("add_css_to_parent", function(tabIndex, done) {
  if(Overlay.element != null)
    Overlay.element.overlay().close();
	// hide all panes and show the one that is clicked
	this.getPanes().hide().eq(tabIndex).show();
	// Add the current property to the a tags parent
  this.getTabs().each(function(index) {
    if(index != tabIndex)
      $(this).parent().removeClass('current')
    else
      $(this).parent().addClass('current');
  });

	// the supplied callback must be called after the effect has finished its job
	done.call();
});

/****************************
 Jquery Tools - Validator*/

// Custom function to check data between 2 fields
$.tools.validator.fn("[data-equals]", "Value not equal with the $1 field", function(input) {
	var name = input.attr("data-equals"),
		 field = this.getInputs().filter("[name=" + name + "]"); 
	return input.val() == field.val() ? true : [name]; 
});

// Custom function for terms and conditions
$.tools.validator.fn("[name=terms_and_conditions]", function(input, value) { 
  if($(input).attr("type") == "checkbox"){
    if($(input).is(':checked')){
      $('#terms-holder').removeClass("terms-holder-error");
      return true;
    }else{
      // Add error class to terms holder
      $('#terms-holder').addClass("terms-holder-error");
      return ""
    }
  }
});

// Custom function for minimum length
$.tools.validator.fn("[minlength]", function(input, value) {
	var min = input.attr("minlength");
	
	return value.length >= min ? true : {     
		en: "Please provide at least " +min+ " character" + (min > 1 ? "s" : "")
	};
});

/*!
 * Copyright (c) 2011 Simo Kinnunen.
 * Licensed under the MIT license.
 *
 * @version ${Version}
 */

var Cufon = (function() {

	var api = function() {
		return api.replace.apply(null, arguments);
	};

	var DOM = api.DOM = {

		ready: (function() {

			var complete = false, readyStatus = { loaded: 1, complete: 1 };

			var queue = [], perform = function() {
				if (complete) return;
				complete = true;
				for (var fn; fn = queue.shift(); fn());
			};

			// Gecko, Opera, WebKit r26101+

			if (document.addEventListener) {
				document.addEventListener('DOMContentLoaded', perform, false);
				window.addEventListener('pageshow', perform, false); // For cached Gecko pages
			}

			// Old WebKit, Internet Explorer

			if (!window.opera && document.readyState) (function() {
				readyStatus[document.readyState] ? perform() : setTimeout(arguments.callee, 10);
			})();

			// Internet Explorer

			if (document.readyState && document.createStyleSheet) (function() {
				try {
					document.body.doScroll('left');
					perform();
				}
				catch (e) {
					setTimeout(arguments.callee, 1);
				}
			})();

			addEvent(window, 'load', perform); // Fallback

			return function(listener) {
				if (!arguments.length) perform();
				else complete ? listener() : queue.push(listener);
			};

		})(),

		root: function() {
			return document.documentElement || document.body;
		},

		strict: (function() {
			var doctype;
			// no doctype (doesn't always catch it though.. IE I'm looking at you)
			if (document.compatMode == 'BackCompat') return false;
			// WebKit, Gecko, Opera, IE9+
			doctype = document.doctype;
			if (doctype) {
				return !/frameset|transitional/i.test(doctype.publicId);
			}
			// IE<9, firstChild is the doctype even if there's an XML declaration
			doctype = document.firstChild;
			if (doctype.nodeType != 8 || /^DOCTYPE.+(transitional|frameset)/i.test(doctype.data)) {
				return false;
			}
			return true;
		})()

	};

	var CSS = api.CSS = {

		Size: function(value, base) {

			this.value = parseFloat(value);
			this.unit = String(value).match(/[a-z%]*$/)[0] || 'px';

			this.convert = function(value) {
				return value / base * this.value;
			};

			this.convertFrom = function(value) {
				return value / this.value * base;
			};

			this.toString = function() {
				return this.value + this.unit;
			};

		},

		addClass: function(el, className) {
			var current = el.className;
			el.className = current + (current && ' ') + className;
			return el;
		},

		color: cached(function(value) {
			var parsed = {};
			parsed.color = value.replace(/^rgba\((.*?),\s*([\d.]+)\)/, function($0, $1, $2) {
				parsed.opacity = parseFloat($2);
				return 'rgb(' + $1 + ')';
			});
			return parsed;
		}),

		// has no direct CSS equivalent.
		// @see http://msdn.microsoft.com/en-us/library/system.windows.fontstretches.aspx
		fontStretch: cached(function(value) {
			if (typeof value == 'number') return value;
			if (/%$/.test(value)) return parseFloat(value) / 100;
			return {
				'ultra-condensed': 0.5,
				'extra-condensed': 0.625,
				condensed: 0.75,
				'semi-condensed': 0.875,
				'semi-expanded': 1.125,
				expanded: 1.25,
				'extra-expanded': 1.5,
				'ultra-expanded': 2
			}[value] || 1;
		}),

		getStyle: function(el) {
			var view = document.defaultView;
			if (view && view.getComputedStyle) return new Style(view.getComputedStyle(el, null));
			if (el.currentStyle) return new Style(el.currentStyle);
			return new Style(el.style);
		},

		gradient: cached(function(value) {
			var gradient = {
				id: value,
				type: value.match(/^-([a-z]+)-gradient\(/)[1],
				stops: []
			}, colors = value.substr(value.indexOf('(')).match(/([\d.]+=)?(#[a-f0-9]+|[a-z]+\(.*?\)|[a-z]+)/ig);
			for (var i = 0, l = colors.length, stop; i < l; ++i) {
				stop = colors[i].split('=', 2).reverse();
				gradient.stops.push([ stop[1] || i / (l - 1), stop[0] ]);
			}
			return gradient;
		}),

		quotedList: cached(function(value) {
			// doesn't work properly with empty quoted strings (""), but
			// it's not worth the extra code.
			var list = [], re = /\s*((["'])([\s\S]*?[^\\])\2|[^,]+)\s*/g, match;
			while (match = re.exec(value)) list.push(match[3] || match[1]);
			return list;
		}),

		recognizesMedia: cached(function(media) {
			var el = document.createElement('style'), sheet, container, supported;
			el.type = 'text/css';
			el.media = media;
			try { // this is cached anyway
				el.appendChild(document.createTextNode('/**/'));
			} catch (e) {}
			container = elementsByTagName('head')[0];
			container.insertBefore(el, container.firstChild);
			sheet = (el.sheet || el.styleSheet);
			supported = sheet && !sheet.disabled;
			container.removeChild(el);
			return supported;
		}),

		removeClass: function(el, className) {
			var re = RegExp('(?:^|\\s+)' + className +  '(?=\\s|$)', 'g');
			el.className = el.className.replace(re, '');
			return el;
		},

		supports: function(property, value) {
			var checker = document.createElement('span').style;
			if (checker[property] === undefined) return false;
			checker[property] = value;
			return checker[property] === value;
		},

		textAlign: function(word, style, position, wordCount) {
			if (style.get('textAlign') == 'right') {
				if (position > 0) word = ' ' + word;
			}
			else if (position < wordCount - 1) word += ' ';
			return word;
		},

		textShadow: cached(function(value) {
			if (value == 'none') return null;
			var shadows = [], currentShadow = {}, result, offCount = 0;
			var re = /(#[a-f0-9]+|[a-z]+\(.*?\)|[a-z]+)|(-?[\d.]+[a-z%]*)|,/ig;
			while (result = re.exec(value)) {
				if (result[0] == ',') {
					shadows.push(currentShadow);
					currentShadow = {};
					offCount = 0;
				}
				else if (result[1]) {
					currentShadow.color = result[1];
				}
				else {
					currentShadow[[ 'offX', 'offY', 'blur' ][offCount++]] = result[2];
				}
			}
			shadows.push(currentShadow);
			return shadows;
		}),

		textTransform: (function() {
			var map = {
				uppercase: function(s) {
					return s.toUpperCase();
				},
				lowercase: function(s) {
					return s.toLowerCase();
				},
				capitalize: function(s) {
					return s.replace(/(?:^|\s)./g, function($0) {
						return $0.toUpperCase();
					});
				}
			};
			return function(text, style) {
				var transform = map[style.get('textTransform')];
				return transform ? transform(text) : text;
			};
		})(),

		whiteSpace: (function() {
			var ignore = {
				inline: 1,
				'inline-block': 1,
				'run-in': 1
			};
			var wsStart = /^\s+/, wsEnd = /\s+$/;
			return function(text, style, node, previousElement, simple) {
				if (simple) return text.replace(wsStart, '').replace(wsEnd, ''); // @fixme too simple
				if (previousElement) {
					if (previousElement.nodeName.toLowerCase() == 'br') {
						text = text.replace(wsStart, '');
					}
				}
				if (ignore[style.get('display')]) return text;
				if (!node.previousSibling) text = text.replace(wsStart, '');
				if (!node.nextSibling) text = text.replace(wsEnd, '');
				return text;
			};
		})()

	};

	CSS.ready = (function() {

		// don't do anything in Safari 2 (it doesn't recognize any media type)
		var complete = !CSS.recognizesMedia('all'), hasLayout = false;

		var queue = [], perform = function() {
			complete = true;
			for (var fn; fn = queue.shift(); fn());
		};

		var links = elementsByTagName('link'), styles = elementsByTagName('style');

		var checkTypes = {
			'': 1,
			'text/css': 1
		};

		function isContainerReady(el) {
			if (!checkTypes[el.type.toLowerCase()]) return true;
			return el.disabled || isSheetReady(el.sheet, el.media || 'screen');
		}

		function isSheetReady(sheet, media) {
			// in Opera sheet.disabled is true when it's still loading,
			// even though link.disabled is false. they stay in sync if
			// set manually.
			if (!CSS.recognizesMedia(media || 'all')) return true;
			if (!sheet || sheet.disabled) return false;
			try {
				var rules = sheet.cssRules, rule;
				if (rules) {
					// needed for Safari 3 and Chrome 1.0.
					// in standards-conforming browsers cssRules contains @-rules.
					// Chrome 1.0 weirdness: rules[<number larger than .length - 1>]
					// returns the last rule, so a for loop is the only option.
					search: for (var i = 0, l = rules.length; rule = rules[i], i < l; ++i) {
						switch (rule.type) {
							case 2: // @charset
								break;
							case 3: // @import
								if (!isSheetReady(rule.styleSheet, rule.media.mediaText)) return false;
								break;
							default:
								// only @charset can precede @import
								break search;
						}
					}
				}
			}
			catch (e) {} // probably a style sheet from another domain
			return true;
		}

		function allStylesLoaded() {
			// Internet Explorer's style sheet model, there's no need to do anything
			if (document.createStyleSheet) return true;
			// standards-compliant browsers
			var el, i;
			for (i = 0; el = links[i]; ++i) {
				if (el.rel.toLowerCase() == 'stylesheet' && !isContainerReady(el)) return false;
			}
			for (i = 0; el = styles[i]; ++i) {
				if (!isContainerReady(el)) return false;
			}
			return true;
		}

		DOM.ready(function() {
			// getComputedStyle returns null in Gecko if used in an iframe with display: none
			if (!hasLayout) hasLayout = CSS.getStyle(document.body).isUsable();
			if (complete || (hasLayout && allStylesLoaded())) perform();
			else setTimeout(arguments.callee, 10);
		});

		return function(listener) {
			if (complete) listener();
			else queue.push(listener);
		};

	})();

	function Font(data) {

		var face = this.face = data.face, wordSeparators = {
			'\u0020': 1,
			'\u00a0': 1,
			'\u3000': 1
		};

		this.glyphs = (function(glyphs) {
			var key, fallbacks = {
				'\u2011': '\u002d',
				'\u00ad': '\u2011'
			};
			for (key in fallbacks) {
				if (!hasOwnProperty(fallbacks, key)) continue;
				if (!glyphs[key]) glyphs[key] = glyphs[fallbacks[key]];
			}
			return glyphs;
		})(data.glyphs);

		this.w = data.w;
		this.baseSize = parseInt(face['units-per-em'], 10);

		this.family = face['font-family'].toLowerCase();
		this.weight = face['font-weight'];
		this.style = face['font-style'] || 'normal';

		this.viewBox = (function () {
			var parts = face.bbox.split(/\s+/);
			var box = {
				minX: parseInt(parts[0], 10),
				minY: parseInt(parts[1], 10),
				maxX: parseInt(parts[2], 10),
				maxY: parseInt(parts[3], 10)
			};
			box.width = box.maxX - box.minX;
			box.height = box.maxY - box.minY;
			box.toString = function() {
				return [ this.minX, this.minY, this.width, this.height ].join(' ');
			};
			return box;
		})();

		this.ascent = -parseInt(face.ascent, 10);
		this.descent = -parseInt(face.descent, 10);

		this.height = -this.ascent + this.descent;

		this.spacing = function(chars, letterSpacing, wordSpacing) {
			var glyphs = this.glyphs, glyph,
				kerning, k,
				jumps = [],
				width = 0, w,
				i = -1, j = -1, chr;
			while (chr = chars[++i]) {
				glyph = glyphs[chr] || this.missingGlyph;
				if (!glyph) continue;
				if (kerning) {
					width -= k = kerning[chr] || 0;
					jumps[j] -= k;
				}
				w = glyph.w;
				if (isNaN(w)) w = +this.w; // may have been a String in old fonts
				if (w > 0) {
					w += letterSpacing;
					if (wordSeparators[chr]) w += wordSpacing;
				}
				width += jumps[++j] = ~~w; // get rid of decimals
				kerning = glyph.k;
			}
			jumps.total = width;
			return jumps;
		};

	}

	function FontFamily() {

		var styles = {}, mapping = {
			oblique: 'italic',
			italic: 'oblique'
		};

		this.add = function(font) {
			(styles[font.style] || (styles[font.style] = {}))[font.weight] = font;
		};

		this.get = function(style, weight) {
			var weights = styles[style] || styles[mapping[style]]
				|| styles.normal || styles.italic || styles.oblique;
			if (!weights) return null;
			// we don't have to worry about "bolder" and "lighter"
			// because IE's currentStyle returns a numeric value for it,
			// and other browsers use the computed value anyway
			weight = {
				normal: 400,
				bold: 700
			}[weight] || parseInt(weight, 10);
			if (weights[weight]) return weights[weight];
			// http://www.w3.org/TR/CSS21/fonts.html#propdef-font-weight
			// Gecko uses x99/x01 for lighter/bolder
			var up = {
				1: 1,
				99: 0
			}[weight % 100], alts = [], min, max;
			if (up === undefined) up = weight > 400;
			if (weight == 500) weight = 400;
			for (var alt in weights) {
				if (!hasOwnProperty(weights, alt)) continue;
				alt = parseInt(alt, 10);
				if (!min || alt < min) min = alt;
				if (!max || alt > max) max = alt;
				alts.push(alt);
			}
			if (weight < min) weight = min;
			if (weight > max) weight = max;
			alts.sort(function(a, b) {
				return (up
					? (a >= weight && b >= weight) ? a < b : a > b
					: (a <= weight && b <= weight) ? a > b : a < b) ? -1 : 1;
			});
			return weights[alts[0]];
		};

	}

	function HoverHandler() {

		function contains(node, anotherNode) {
			try {
				if (node.contains) return node.contains(anotherNode);
				return node.compareDocumentPosition(anotherNode) & 16;
			}
			catch(e) {} // probably a XUL element such as a scrollbar
			return false;
		}

		// mouseover/mouseout (standards) mode
		function onOverOut(e) {
			var related = e.relatedTarget;
			// there might be no relatedTarget if the element is right next
			// to the window frame
			if (related && contains(this, related)) return;
			trigger(this, e.type == 'mouseover');
		}

		// mouseenter/mouseleave (probably ie) mode
		function onEnterLeave(e) {
			if (!e) e = window.event;
			// ie model, we don't have access to "this", but
			// mouseenter/leave doesn't bubble so it's fine.
			trigger(e.target || e.srcElement, e.type == 'mouseenter');
		}

		function trigger(el, hoverState) {
			// A timeout is needed so that the event can actually "happen"
			// before replace is triggered. This ensures that styles are up
			// to date.
			setTimeout(function() {
				var options = sharedStorage.get(el).options;
				if (hoverState) {
					options = merge(options, options.hover);
					options._mediatorMode = 1;
				}
				api.replace(el, options, true);
			}, 10);
		}

		this.attach = function(el) {
			if (el.onmouseenter === undefined) {
				addEvent(el, 'mouseover', onOverOut);
				addEvent(el, 'mouseout', onOverOut);
			}
			else {
				addEvent(el, 'mouseenter', onEnterLeave);
				addEvent(el, 'mouseleave', onEnterLeave);
			}
		};

		this.detach = function(el) {
			if (el.onmouseenter === undefined) {
				removeEvent(el, 'mouseover', onOverOut);
				removeEvent(el, 'mouseout', onOverOut);
			}
			else {
				removeEvent(el, 'mouseenter', onEnterLeave);
				removeEvent(el, 'mouseleave', onEnterLeave);
			}
		};

	}

	function ReplaceHistory() {

		var list = [], map = {};

		function filter(keys) {
			var values = [], key;
			for (var i = 0; key = keys[i]; ++i) values[i] = list[map[key]];
			return values;
		}

		this.add = function(key, args) {
			map[key] = list.push(args) - 1;
		};

		this.repeat = function() {
			var snapshot = arguments.length ? filter(arguments) : list, args;
			for (var i = 0; args = snapshot[i++];) api.replace(args[0], args[1], true);
		};

	}

	function Storage() {

		var map = {}, at = 0;

		function identify(el) {
			return el.cufid || (el.cufid = ++at);
		}

		this.get = function(el) {
			var id = identify(el);
			return map[id] || (map[id] = {});
		};

	}

	function Style(style) {

		var custom = {}, sizes = {};

		this.extend = function(styles) {
			for (var property in styles) {
				if (hasOwnProperty(styles, property)) custom[property] = styles[property];
			}
			return this;
		};

		this.get = function(property) {
			return custom[property] != undefined ? custom[property] : style[property];
		};

		this.getSize = function(property, base) {
			return sizes[property] || (sizes[property] = new CSS.Size(this.get(property), base));
		};

		this.isUsable = function() {
			return !!style;
		};

	}

	function addEvent(el, type, listener) {
		if (el.addEventListener) {
			el.addEventListener(type, listener, false);
		}
		else if (el.attachEvent) {
			// we don't really need "this" right now, saves code
			el.attachEvent('on' + type, listener);
		}
	}

	function attach(el, options) {
		if (options._mediatorMode) return el;
		var storage = sharedStorage.get(el);
		var oldOptions = storage.options;
		if (oldOptions) {
			if (oldOptions === options) return el;
			if (oldOptions.hover) hoverHandler.detach(el);
		}
		if (options.hover && options.hoverables[el.nodeName.toLowerCase()]) {
			hoverHandler.attach(el);
		}
		storage.options = options;
		return el;
	}

	function cached(fun) {
		var cache = {};
		return function(key) {
			if (!hasOwnProperty(cache, key)) cache[key] = fun.apply(null, arguments);
			return cache[key];
		};
	}

	function getFont(el, style) {
		var families = CSS.quotedList(style.get('fontFamily').toLowerCase()), family;
		for (var i = 0; family = families[i]; ++i) {
			if (fonts[family]) return fonts[family].get(style.get('fontStyle'), style.get('fontWeight'));
		}
		return null;
	}

	function elementsByTagName(query) {
		return document.getElementsByTagName(query);
	}

	function hasOwnProperty(obj, property) {
		return obj.hasOwnProperty(property);
	}

	function merge() {
		var merged = {}, arg, key;
		for (var i = 0, l = arguments.length; arg = arguments[i], i < l; ++i) {
			for (key in arg) {
				if (hasOwnProperty(arg, key)) merged[key] = arg[key];
			}
		}
		return merged;
	}

	function process(font, text, style, options, node, el) {
		var fragment = document.createDocumentFragment(), processed;
		if (text === '') return fragment;
		var separate = options.separate;
		var parts = text.split(separators[separate]), needsAligning = (separate == 'words');
		if (needsAligning && HAS_BROKEN_REGEXP) {
			// @todo figure out a better way to do this
			if (/^\s/.test(text)) parts.unshift('');
			if (/\s$/.test(text)) parts.push('');
		}
		for (var i = 0, l = parts.length; i < l; ++i) {
			processed = engines[options.engine](font,
				needsAligning ? CSS.textAlign(parts[i], style, i, l) : parts[i],
				style, options, node, el, i < l - 1);
			if (processed) fragment.appendChild(processed);
		}
		return fragment;
	}

	function removeEvent(el, type, listener) {
		if (el.removeEventListener) {
			el.removeEventListener(type, listener, false);
		}
		else if (el.detachEvent) {
			el.detachEvent('on' + type, listener);
		}
	}

	function replaceElement(el, options) {
		var name = el.nodeName.toLowerCase();
		if (options.ignore[name]) return;
		if (options.ignoreClass && options.ignoreClass.test(el.className)) return;
		if (options.onBeforeReplace) options.onBeforeReplace(el, options);
		var replace = !options.textless[name], simple = (options.trim === 'simple');
		var style = CSS.getStyle(attach(el, options)).extend(options);
		// may cause issues if the element contains other elements
		// with larger fontSize, however such cases are rare and can
		// be fixed by using a more specific selector
		if (parseFloat(style.get('fontSize')) === 0) return;
		var font = getFont(el, style), node, type, next, anchor, text, lastElement;
		var isShy = options.softHyphens, anyShy = false, pos, shy, reShy = /\u00ad/g;
		var modifyText = options.modifyText;
		if (!font) return;
		for (node = el.firstChild; node; node = next) {
			type = node.nodeType;
			next = node.nextSibling;
			if (replace && type == 3) {
				if (isShy && el.nodeName.toLowerCase() != TAG_SHY) {
					pos = node.data.indexOf('\u00ad');
					if (pos >= 0) {
						node.splitText(pos);
						next = node.nextSibling;
						next.deleteData(0, 1);
						shy = document.createElement(TAG_SHY);
						shy.appendChild(document.createTextNode('\u00ad'));
						el.insertBefore(shy, next);
						next = shy;
						anyShy = true;
					}
				}
				// Node.normalize() is broken in IE 6, 7, 8
				if (anchor) {
					anchor.appendData(node.data);
					el.removeChild(node);
				}
				else anchor = node;
				if (next) continue;
			}
			if (anchor) {
				text = anchor.data;
				if (!isShy) text = text.replace(reShy, '');
				text = CSS.whiteSpace(text, style, anchor, lastElement, simple);
				// modify text only on the first replace
				if (modifyText) text = modifyText(text, anchor, el, options);
				el.replaceChild(process(font, text, style, options, node, el), anchor);
				anchor = null;
			}
			if (type == 1) {
				if (node.firstChild) {
					if (node.nodeName.toLowerCase() == 'cufon') {
						engines[options.engine](font, null, style, options, node, el);
					}
					else arguments.callee(node, options);
				}
				lastElement = node;
			}
		}
		if (isShy && anyShy) {
			updateShy(el);
			if (!trackingShy) addEvent(window, 'resize', updateShyOnResize);
			trackingShy = true;
		}
		if (options.onAfterReplace) options.onAfterReplace(el, options);
	}

	function updateShy(context) {
		var shys, shy, parent, glue, newGlue, next, prev, i;
		shys = context.getElementsByTagName(TAG_SHY);
		// unfortunately there doesn't seem to be any easy
		// way to avoid having to loop through the shys twice.
		for (i = 0; shy = shys[i]; ++i) {
			shy.className = C_SHY_DISABLED;
			glue = parent = shy.parentNode;
			if (glue.nodeName.toLowerCase() != TAG_GLUE) {
				newGlue = document.createElement(TAG_GLUE);
				newGlue.appendChild(shy.previousSibling);
				parent.insertBefore(newGlue, shy);
				newGlue.appendChild(shy);
			}
			else {
				// get rid of double glue (edge case fix)
				glue = glue.parentNode;
				if (glue.nodeName.toLowerCase() == TAG_GLUE) {
					parent = glue.parentNode;
					while (glue.firstChild) {
						parent.insertBefore(glue.firstChild, glue);
					}
					parent.removeChild(glue);
				}
			}
		}
		for (i = 0; shy = shys[i]; ++i) {
			shy.className = '';
			glue = shy.parentNode;
			parent = glue.parentNode;
			next = glue.nextSibling || parent.nextSibling;
			// make sure we're comparing same types
			prev = (next.nodeName.toLowerCase() == TAG_GLUE) ? glue : shy.previousSibling;
			if (prev.offsetTop >= next.offsetTop) {
				shy.className = C_SHY_DISABLED;
				if (prev.offsetTop < next.offsetTop) {
					// we have an annoying edge case, double the glue
					newGlue = document.createElement(TAG_GLUE);
					parent.insertBefore(newGlue, glue);
					newGlue.appendChild(glue);
					newGlue.appendChild(next);
				}
			}
		}
	}

	function updateShyOnResize() {
		if (ignoreResize) return; // needed for IE
		CSS.addClass(DOM.root(), C_VIEWPORT_RESIZING);
		clearTimeout(shyTimer);
		shyTimer = setTimeout(function() {
			ignoreResize = true;
			CSS.removeClass(DOM.root(), C_VIEWPORT_RESIZING);
			updateShy(document);
			ignoreResize = false;
		}, 100);
	}

	var HAS_BROKEN_REGEXP = ' '.split(/\s+/).length == 0;
	var TAG_GLUE = 'cufonglue';
	var TAG_SHY = 'cufonshy';
	var C_SHY_DISABLED = 'cufon-shy-disabled';
	var C_VIEWPORT_RESIZING = 'cufon-viewport-resizing';

	var sharedStorage = new Storage();
	var hoverHandler = new HoverHandler();
	var replaceHistory = new ReplaceHistory();
	var initialized = false;
	var trackingShy = false;
	var shyTimer;
	var ignoreResize = false;

	var engines = {}, fonts = {}, defaultOptions = {
		autoDetect: false,
		engine: null,
		forceHitArea: false,
		hover: false,
		hoverables: {
			a: true
		},
		ignore: {
			applet: 1,
			canvas: 1,
			col: 1,
			colgroup: 1,
			head: 1,
			iframe: 1,
			map: 1,
			noscript: 1,
			optgroup: 1,
			option: 1,
			script: 1,
			select: 1,
			style: 1,
			textarea: 1,
			title: 1,
			pre: 1
		},
		ignoreClass: null,
		modifyText: null,
		onAfterReplace: null,
		onBeforeReplace: null,
		printable: true,
		selector: (
				window.Sizzle
			||	(window.jQuery && function(query) { return jQuery(query); }) // avoid noConflict issues
			||	(window.dojo && dojo.query)
			||	(window.glow && glow.dom && glow.dom.get)
			||	(window.Ext && Ext.query)
			||	(window.YAHOO && YAHOO.util && YAHOO.util.Selector && YAHOO.util.Selector.query)
			||	(window.$$ && function(query) { return $$(query); })
			||	(window.$ && function(query) { return $(query); })
			||	(document.querySelectorAll && function(query) { return document.querySelectorAll(query); })
			||	elementsByTagName
		),
		separate: 'words', // 'none' and 'characters' are also accepted
		softHyphens: true,
		textless: {
			dl: 1,
			html: 1,
			ol: 1,
			table: 1,
			tbody: 1,
			thead: 1,
			tfoot: 1,
			tr: 1,
			ul: 1
		},
		textShadow: 'none',
		trim: 'advanced'
	};

	var separators = {
		// The first pattern may cause unicode characters above
		// code point 255 to be removed in Safari 3.0. Luckily enough
		// Safari 3.0 does not include non-breaking spaces in \s, so
		// we can just use a simple alternative pattern.
		words: /\s/.test('\u00a0') ? /[^\S\u00a0]+/ : /\s+/,
		characters: '',
		none: /^/
	};

	api.now = function() {
		DOM.ready();
		return api;
	};

	api.refresh = function() {
		replaceHistory.repeat.apply(replaceHistory, arguments);
		return api;
	};

	api.registerEngine = function(id, engine) {
		if (!engine) return api;
		engines[id] = engine;
		return api.set('engine', id);
	};

	api.registerFont = function(data) {
		if (!data) return api;
		var font = new Font(data), family = font.family;
		if (!fonts[family]) fonts[family] = new FontFamily();
		fonts[family].add(font);
		return api.set('fontFamily', '"' + family + '"');
	};

	api.replace = function(elements, options, ignoreHistory) {
		options = merge(defaultOptions, options);
		if (!options.engine) return api; // there's no browser support so we'll just stop here
		if (!initialized) {
			CSS.addClass(DOM.root(), 'cufon-active cufon-loading');
			CSS.ready(function() {
				// fires before any replace() calls, but it doesn't really matter
				CSS.addClass(CSS.removeClass(DOM.root(), 'cufon-loading'), 'cufon-ready');
			});
			initialized = true;
		}
		if (options.hover) options.forceHitArea = true;
		if (options.autoDetect) delete options.fontFamily;
		if (typeof options.ignoreClass == 'string') {
			options.ignoreClass = new RegExp('(?:^|\\s)(?:' + options.ignoreClass.replace(/\s+/g, '|') + ')(?:\\s|$)');
		}
		if (typeof options.textShadow == 'string') {
			options.textShadow = CSS.textShadow(options.textShadow);
		}
		if (typeof options.color == 'string' && /^-/.test(options.color)) {
			options.textGradient = CSS.gradient(options.color);
		}
		else delete options.textGradient;
		if (typeof elements == 'string') {
			if (!ignoreHistory) replaceHistory.add(elements, arguments);
			elements = [ elements ];
		}
		else if (elements.nodeType) elements = [ elements ];
		CSS.ready(function() {
			for (var i = 0, l = elements.length; i < l; ++i) {
				var el = elements[i];
				if (typeof el == 'string') api.replace(options.selector(el), options, true);
				else replaceElement(el, options);
			}
		});
		return api;
	};

	api.set = function(option, value) {
		defaultOptions[option] = value;
		return api;
	};

	return api;

})();

Cufon.registerEngine('vml', (function() {

	var ns = document.namespaces;
	if (!ns) return;
	ns.add('cvml', 'urn:schemas-microsoft-com:vml');
	ns = null;

	var check = document.createElement('cvml:shape');
	check.style.behavior = 'url(#default#VML)';
	if (!check.coordsize) return; // VML isn't supported
	check = null;

	var HAS_BROKEN_LINEHEIGHT = (document.documentMode || 0) < 8;

	document.write(('<style type="text/css">' +
		'cufoncanvas{text-indent:0;}' +
		'@media screen{' +
			'cvml\\:shape,cvml\\:rect,cvml\\:fill,cvml\\:shadow{behavior:url(#default#VML);display:block;antialias:true;position:absolute;}' +
			'cufoncanvas{position:absolute;text-align:left;}' +
			'cufon{display:inline-block;position:relative;vertical-align:' +
			(HAS_BROKEN_LINEHEIGHT
				? 'middle'
				: 'text-bottom') +
			';}' +
			'cufon cufontext{position:absolute;left:-10000in;font-size:1px;text-align:left;}' +
			'cufonshy.cufon-shy-disabled,.cufon-viewport-resizing cufonshy{display:none;}' +
			'cufonglue{white-space:nowrap;display:inline-block;}' +
			'.cufon-viewport-resizing cufonglue{white-space:normal;}' +
			'a cufon{cursor:pointer}' + // ignore !important here
		'}' +
		'@media print{' +
			'cufon cufoncanvas{display:none;}' +
		'}' +
	'</style>').replace(/;/g, '!important;'));

	function getFontSizeInPixels(el, value) {
		return getSizeInPixels(el, /(?:em|ex|%)$|^[a-z-]+$/i.test(value) ? '1em' : value);
	}

	// Original by Dead Edwards.
	// Combined with getFontSizeInPixels it also works with relative units.
	function getSizeInPixels(el, value) {
		if (!isNaN(value) || /px$/i.test(value)) return parseFloat(value);
		var style = el.style.left, runtimeStyle = el.runtimeStyle.left;
		el.runtimeStyle.left = el.currentStyle.left;
		el.style.left = value.replace('%', 'em');
		var result = el.style.pixelLeft;
		el.style.left = style;
		el.runtimeStyle.left = runtimeStyle;
		return result;
	}

	function getSpacingValue(el, style, size, property) {
		var key = 'computed' + property, value = style[key];
		if (isNaN(value)) {
			value = style.get(property);
			style[key] = value = (value == 'normal') ? 0 : ~~size.convertFrom(getSizeInPixels(el, value));
		}
		return value;
	}

	var fills = {};

	function gradientFill(gradient) {
		var id = gradient.id;
		if (!fills[id]) {
			var stops = gradient.stops, fill = document.createElement('cvml:fill'), colors = [];
			fill.type = 'gradient';
			fill.angle = 180;
			fill.focus = '0';
			fill.method = 'none';
			fill.color = stops[0][1];
			for (var j = 1, k = stops.length - 1; j < k; ++j) {
				colors.push(stops[j][0] * 100 + '% ' + stops[j][1]);
			}
			fill.colors = colors.join(',');
			fill.color2 = stops[k][1];
			fills[id] = fill;
		}
		return fills[id];
	}

	return function(font, text, style, options, node, el, hasNext) {

		var redraw = (text === null);

		if (redraw) text = node.alt;

		var viewBox = font.viewBox;

		var size = style.computedFontSize || (style.computedFontSize = new Cufon.CSS.Size(getFontSizeInPixels(el, style.get('fontSize')) + 'px', font.baseSize));

		var wrapper, canvas;

		if (redraw) {
			wrapper = node;
			canvas = node.firstChild;
		}
		else {
			wrapper = document.createElement('cufon');
			wrapper.className = 'cufon cufon-vml';
			wrapper.alt = text;

			canvas = document.createElement('cufoncanvas');
			wrapper.appendChild(canvas);

			if (options.printable) {
				var print = document.createElement('cufontext');
				print.appendChild(document.createTextNode(text));
				wrapper.appendChild(print);
			}

			// ie6, for some reason, has trouble rendering the last VML element in the document.
			// we can work around this by injecting a dummy element where needed.
			// @todo find a better solution
			if (!hasNext) wrapper.appendChild(document.createElement('cvml:shape'));
		}

		var wStyle = wrapper.style;
		var cStyle = canvas.style;

		var height = size.convert(viewBox.height), roundedHeight = Math.ceil(height);
		var roundingFactor = roundedHeight / height;
		var stretchFactor = roundingFactor * Cufon.CSS.fontStretch(style.get('fontStretch'));
		var minX = viewBox.minX, minY = viewBox.minY;

		cStyle.height = roundedHeight;
		cStyle.top = Math.round(size.convert(minY - font.ascent));
		cStyle.left = Math.round(size.convert(minX));

		wStyle.height = size.convert(font.height) + 'px';

		var color = style.get('color');
		var chars = Cufon.CSS.textTransform(text, style).split('');

		var jumps = font.spacing(chars,
			getSpacingValue(el, style, size, 'letterSpacing'),
			getSpacingValue(el, style, size, 'wordSpacing')
		);

		if (!jumps.length) return null;

		var width = jumps.total;
		var fullWidth = -minX + width + (viewBox.width - jumps[jumps.length - 1]);

		var shapeWidth = size.convert(fullWidth * stretchFactor), roundedShapeWidth = Math.round(shapeWidth);

		var coordSize = fullWidth + ',' + viewBox.height, coordOrigin;
		var stretch = 'r' + coordSize + 'ns';

		var fill = options.textGradient && gradientFill(options.textGradient);

		var glyphs = font.glyphs, offsetX = 0;
		var shadows = options.textShadow;
		var i = -1, j = 0, chr;

		while (chr = chars[++i]) {

			var glyph = glyphs[chars[i]] || font.missingGlyph, shape;
			if (!glyph) continue;

			if (redraw) {
				// some glyphs may be missing so we can't use i
				shape = canvas.childNodes[j];
				while (shape.firstChild) shape.removeChild(shape.firstChild); // shadow, fill
			}
			else {
				shape = document.createElement('cvml:shape');
				canvas.appendChild(shape);
			}

			shape.stroked = 'f';
			shape.coordsize = coordSize;
			shape.coordorigin = coordOrigin = (minX - offsetX) + ',' + minY;
			shape.path = (glyph.d ? 'm' + glyph.d + 'xe' : '') + 'm' + coordOrigin + stretch;
			shape.fillcolor = color;

			if (fill) shape.appendChild(fill.cloneNode(false));

			// it's important to not set top/left or IE8 will grind to a halt
			var sStyle = shape.style;
			sStyle.width = roundedShapeWidth;
			sStyle.height = roundedHeight;

			if (shadows) {
				// due to the limitations of the VML shadow element there
				// can only be two visible shadows. opacity is shared
				// for all shadows.
				var shadow1 = shadows[0], shadow2 = shadows[1];
				var color1 = Cufon.CSS.color(shadow1.color), color2;
				var shadow = document.createElement('cvml:shadow');
				shadow.on = 't';
				shadow.color = color1.color;
				shadow.offset = shadow1.offX + ',' + shadow1.offY;
				if (shadow2) {
					color2 = Cufon.CSS.color(shadow2.color);
					shadow.type = 'double';
					shadow.color2 = color2.color;
					shadow.offset2 = shadow2.offX + ',' + shadow2.offY;
				}
				shadow.opacity = color1.opacity || (color2 && color2.opacity) || 1;
				shape.appendChild(shadow);
			}

			offsetX += jumps[j++];
		}

		// addresses flickering issues on :hover

		var cover = shape.nextSibling, coverFill, vStyle;

		if (options.forceHitArea) {

			if (!cover) {
				cover = document.createElement('cvml:rect');
				cover.stroked = 'f';
				cover.className = 'cufon-vml-cover';
				coverFill = document.createElement('cvml:fill');
				coverFill.opacity = 0;
				cover.appendChild(coverFill);
				canvas.appendChild(cover);
			}

			vStyle = cover.style;

			vStyle.width = roundedShapeWidth;
			vStyle.height = roundedHeight;

		}
		else if (cover) canvas.removeChild(cover);

		wStyle.width = Math.max(Math.ceil(size.convert(width * stretchFactor)), 0);

		if (HAS_BROKEN_LINEHEIGHT) {

			var yAdjust = style.computedYAdjust;

			if (yAdjust === undefined) {
				var lineHeight = style.get('lineHeight');
				if (lineHeight == 'normal') lineHeight = '1em';
				else if (!isNaN(lineHeight)) lineHeight += 'em'; // no unit
				style.computedYAdjust = yAdjust = 0.5 * (getSizeInPixels(el, lineHeight) - parseFloat(wStyle.height));
			}

			if (yAdjust) {
				wStyle.marginTop = Math.ceil(yAdjust) + 'px';
				wStyle.marginBottom = yAdjust + 'px';
			}

		}

		return wrapper;

	};

})());

Cufon.registerEngine('canvas', (function() {

	// Safari 2 doesn't support .apply() on native methods

	var check = document.createElement('canvas');
	if (!check || !check.getContext || !check.getContext.apply) return;
	check = null;

	var HAS_INLINE_BLOCK = Cufon.CSS.supports('display', 'inline-block');

	// Firefox 2 w/ non-strict doctype (almost standards mode)
	var HAS_BROKEN_LINEHEIGHT = !HAS_INLINE_BLOCK && (document.compatMode == 'BackCompat' || /frameset|transitional/i.test(document.doctype.publicId));

	var styleSheet = document.createElement('style');
	styleSheet.type = 'text/css';
	styleSheet.appendChild(document.createTextNode((
		'cufon{text-indent:0;}' +
		'@media screen,projection{' +
			'cufon{display:inline;display:inline-block;position:relative;vertical-align:middle;' +
			(HAS_BROKEN_LINEHEIGHT
				? ''
				: 'font-size:1px;line-height:1px;') +
			'}cufon cufontext{display:-moz-inline-box;display:inline-block;width:0;height:0;text-align:left;text-indent:-10000in;}' +
			(HAS_INLINE_BLOCK
				? 'cufon canvas{position:relative;}'
				: 'cufon canvas{position:absolute;}') +
			'cufonshy.cufon-shy-disabled,.cufon-viewport-resizing cufonshy{display:none;}' +
			'cufonglue{white-space:nowrap;display:inline-block;}' +
			'.cufon-viewport-resizing cufonglue{white-space:normal;}' +
		'}' +
		'@media print{' +
			'cufon{padding:0;}' + // Firefox 2
			'cufon canvas{display:none;}' +
		'}'
	).replace(/;/g, '!important;')));
	document.getElementsByTagName('head')[0].appendChild(styleSheet);

	function generateFromVML(path, context) {
		var atX = 0, atY = 0;
		var code = [], re = /([mrvxe])([^a-z]*)/g, match;
		generate: for (var i = 0; match = re.exec(path); ++i) {
			var c = match[2].split(',');
			switch (match[1]) {
				case 'v':
					code[i] = { m: 'bezierCurveTo', a: [ atX + ~~c[0], atY + ~~c[1], atX + ~~c[2], atY + ~~c[3], atX += ~~c[4], atY += ~~c[5] ] };
					break;
				case 'r':
					code[i] = { m: 'lineTo', a: [ atX += ~~c[0], atY += ~~c[1] ] };
					break;
				case 'm':
					code[i] = { m: 'moveTo', a: [ atX = ~~c[0], atY = ~~c[1] ] };
					break;
				case 'x':
					code[i] = { m: 'closePath' };
					break;
				case 'e':
					break generate;
			}
			context[code[i].m].apply(context, code[i].a);
		}
		return code;
	}

	function interpret(code, context) {
		for (var i = 0, l = code.length; i < l; ++i) {
			var line = code[i];
			context[line.m].apply(context, line.a);
		}
	}

	return function(font, text, style, options, node, el) {

		var redraw = (text === null);

		if (redraw) text = node.getAttribute('alt');

		var viewBox = font.viewBox;

		var size = style.getSize('fontSize', font.baseSize);

		var expandTop = 0, expandRight = 0, expandBottom = 0, expandLeft = 0;
		var shadows = options.textShadow, shadowOffsets = [];
		if (shadows) {
			for (var i = shadows.length; i--;) {
				var shadow = shadows[i];
				var x = size.convertFrom(parseFloat(shadow.offX));
				var y = size.convertFrom(parseFloat(shadow.offY));
				shadowOffsets[i] = [ x, y ];
				if (y < expandTop) expandTop = y;
				if (x > expandRight) expandRight = x;
				if (y > expandBottom) expandBottom = y;
				if (x < expandLeft) expandLeft = x;
			}
		}

		var chars = Cufon.CSS.textTransform(text, style).split('');

		var jumps = font.spacing(chars,
			~~size.convertFrom(parseFloat(style.get('letterSpacing')) || 0),
			~~size.convertFrom(parseFloat(style.get('wordSpacing')) || 0)
		);

		if (!jumps.length) return null; // there's nothing to render

		var width = jumps.total;

		expandRight += viewBox.width - jumps[jumps.length - 1];
		expandLeft += viewBox.minX;

		var wrapper, canvas;

		if (redraw) {
			wrapper = node;
			canvas = node.firstChild;
		}
		else {
			wrapper = document.createElement('cufon');
			wrapper.className = 'cufon cufon-canvas';
			wrapper.setAttribute('alt', text);

			canvas = document.createElement('canvas');
			wrapper.appendChild(canvas);

			if (options.printable) {
				var print = document.createElement('cufontext');
				print.appendChild(document.createTextNode(text));
				wrapper.appendChild(print);
			}
		}

		var wStyle = wrapper.style;
		var cStyle = canvas.style;

		var height = size.convert(viewBox.height);
		var roundedHeight = Math.ceil(height);
		var roundingFactor = roundedHeight / height;
		var stretchFactor = roundingFactor * Cufon.CSS.fontStretch(style.get('fontStretch'));
		var stretchedWidth = width * stretchFactor;

		var canvasWidth = Math.ceil(size.convert(stretchedWidth + expandRight - expandLeft));
		var canvasHeight = Math.ceil(size.convert(viewBox.height - expandTop + expandBottom));

		canvas.width = canvasWidth;
		canvas.height = canvasHeight;

		// needed for WebKit and full page zoom
		cStyle.width = canvasWidth + 'px';
		cStyle.height = canvasHeight + 'px';

		// minY has no part in canvas.height
		expandTop += viewBox.minY;

		cStyle.top = Math.round(size.convert(expandTop - font.ascent)) + 'px';
		cStyle.left = Math.round(size.convert(expandLeft)) + 'px';

		var wrapperWidth = Math.max(Math.ceil(size.convert(stretchedWidth)), 0) + 'px';

		if (HAS_INLINE_BLOCK) {
			wStyle.width = wrapperWidth;
			wStyle.height = size.convert(font.height) + 'px';
		}
		else {
			wStyle.paddingLeft = wrapperWidth;
			wStyle.paddingBottom = (size.convert(font.height) - 1) + 'px';
		}

		var g = canvas.getContext('2d'), scale = height / viewBox.height;

		// proper horizontal scaling is performed later
		g.scale(scale, scale * roundingFactor);
		g.translate(-expandLeft, -expandTop);
		g.save();

		function renderText() {
			var glyphs = font.glyphs, glyph, i = -1, j = -1, chr;
			g.scale(stretchFactor, 1);
			while (chr = chars[++i]) {
				var glyph = glyphs[chars[i]] || font.missingGlyph;
				if (!glyph) continue;
				if (glyph.d) {
					g.beginPath();
					if (glyph.code) interpret(glyph.code, g);
					else glyph.code = generateFromVML('m' + glyph.d, g);
					g.fill();
				}
				g.translate(jumps[++j], 0);
			}
			g.restore();
		}

		if (shadows) {
			for (var i = shadows.length; i--;) {
				var shadow = shadows[i];
				g.save();
				g.fillStyle = shadow.color;
				g.translate.apply(g, shadowOffsets[i]);
				renderText();
			}
		}

		var gradient = options.textGradient;
		if (gradient) {
			var stops = gradient.stops, fill = g.createLinearGradient(0, viewBox.minY, 0, viewBox.maxY);
			for (var i = 0, l = stops.length; i < l; ++i) {
				fill.addColorStop.apply(fill, stops[i]);
			}
			g.fillStyle = fill;
		}
		else g.fillStyle = style.get('color');

		renderText();

		return wrapper;

	};

})());

/*!
 * The following copyright notice may not be removed under any circumstances.
 * 
 * Copyright:
 * 2005 Albert-Jan Pool published by FSI Fonts und Software GmbH
 * 
 * Trademark:
 * DIN is a trademark of FSI Fonts und Software GmbH
 * 
 * Manufacturer:
 * FSI Fonts und Software GmbH
 * 
 * Designer:
 * Albert-Jan Pool
 * 
 * Vendor URL:
 * http://www.fontfont.com
 * 
 * License information:
 * http://www.fontfont.com/eula/license.html
 */
Cufon.registerFont({"w":187,"face":{"font-family":"DINPro-Regular","font-weight":400,"font-stretch":"normal","units-per-em":"360","panose-1":"2 0 5 3 3 0 0 2 0 4","ascent":"275","descent":"-85","x-height":"2","bbox":"-5 -290 302 81.3705","underline-thickness":"18.36","underline-position":"-30.6","stemh":"24","stemv":"26","unicode-range":"U+0020-U+007E"},"glyphs":{" ":{"w":89},"!":{"d":"77,-256r-4,184r-22,0r-3,-184r29,0xm78,0r-31,0r0,-30r31,0r0,30","w":113},"\"":{"d":"121,-195r-29,0r0,-61r29,0r0,61xm60,-195r-28,0r0,-61r28,0r0,61","w":152},"#":{"d":"217,-156r-35,0r-8,51r32,0r0,23r-36,0r-13,82r-26,0r13,-82r-58,0r-13,82r-26,0r13,-82r-32,0r0,-23r36,0r8,-51r-33,0r0,-23r36,0r12,-78r27,0r-12,78r57,0r12,-78r27,0r-13,78r32,0r0,23xm156,-156r-58,0r-8,51r57,0","w":235},"$":{"d":"172,-121v46,42,16,125,-56,122r0,40r-22,0r0,-39v-34,-1,-57,-12,-79,-34r19,-18v19,19,38,26,62,27r0,-95v-43,-4,-74,-24,-74,-68v0,-41,27,-68,72,-72r0,-32r22,0r0,32v28,1,47,10,67,28r-18,17v-14,-12,-28,-20,-50,-21r0,93v24,4,46,9,57,20xm115,-23v47,2,68,-51,39,-79v-11,-11,-24,-11,-39,-13r0,92xm96,-144r0,-90v-42,0,-62,49,-36,76v9,9,24,12,36,14","w":214},"%":{"d":"277,-84v0,48,-6,87,-49,87v-43,0,-48,-39,-48,-87v0,-30,20,-48,48,-48v28,0,49,18,49,48xm121,-210v0,48,-5,86,-49,86v-43,0,-49,-38,-49,-86v0,-30,21,-49,49,-49v28,0,49,19,49,49xm221,-256r-120,256r-22,0r120,-256r22,0xm228,-15v33,1,28,-36,28,-68v0,-19,-9,-31,-28,-31v-34,-1,-28,35,-28,67v0,19,8,32,28,32xm72,-142v33,1,28,-36,28,-68v0,-19,-9,-31,-28,-31v-34,-1,-28,36,-28,68v0,19,9,31,28,31","w":299},"&":{"d":"242,0r-35,0r-23,-28v-10,10,-34,30,-75,30v-50,0,-81,-29,-81,-74v0,-39,27,-58,55,-77v-40,-29,-37,-109,29,-109v57,0,75,78,27,99r-19,13r66,79v10,-16,14,-30,14,-59r26,0v0,32,-7,59,-24,79xm169,-47r-71,-85v-22,15,-44,30,-44,59v0,59,76,67,115,26xm105,-163v17,-12,37,-19,37,-41v0,-17,-13,-31,-30,-31v-40,0,-38,43,-7,72","w":266},"'":{"d":"60,-195r-28,0r0,-61r28,0r0,61","w":91},"(":{"d":"59,-36v0,28,11,38,25,52r-17,18v-20,-18,-34,-35,-34,-68v0,-90,-26,-211,34,-256r17,17v-14,15,-25,25,-25,53r0,184","w":107},")":{"d":"41,-290v20,18,34,35,33,68r0,188v1,33,-13,50,-33,68r-19,-19v14,-14,25,-23,25,-51r0,-184v1,-28,-11,-38,-25,-52","w":107},"*":{"d":"147,-170r-11,18r-42,-26r2,49r-21,0r1,-49r-41,26r-11,-18r43,-23r-43,-24r11,-17r41,25r-1,-49r21,0r-2,49r42,-25r11,17r-44,24","w":170},"+":{"d":"169,-84r-63,0r0,63r-24,0r0,-63r-63,0r0,-24r63,0r0,-63r24,0r0,63r63,0r0,24"},",":{"d":"63,23r-31,29r0,-84r31,0r0,55","w":95},"-":{"d":"126,-85r-99,0r0,-24r99,0r0,24","w":153},".":{"d":"66,0r-34,0r0,-34r34,0r0,34","w":97},"\/":{"d":"128,-283r-102,310r-26,0r103,-310r25,0","w":127},"0":{"d":"164,-68v0,42,-30,70,-70,70v-40,0,-70,-28,-70,-70r0,-120v0,-42,30,-70,70,-70v40,0,70,28,70,70r0,120xm94,-21v67,-2,44,-102,44,-165v0,-28,-16,-49,-44,-49v-67,2,-44,102,-44,165v0,28,16,49,44,49"},"1":{"d":"119,0r-26,0r0,-228r-48,43r0,-30r48,-41r26,0r0,256"},"2":{"d":"166,0r-142,0r0,-23r102,-129v27,-30,13,-83,-31,-83v-24,0,-44,13,-44,46r-26,0v0,-40,27,-69,70,-69v65,0,87,72,50,120r-89,115r110,0r0,23"},"3":{"d":"166,-70v0,47,-34,73,-76,73v-40,0,-73,-22,-75,-68r26,0v4,63,99,56,99,-5v0,-33,-18,-52,-56,-50r0,-23v34,1,51,-15,51,-46v0,-31,-20,-47,-45,-47v-27,0,-43,17,-46,43r-26,0v3,-41,33,-66,72,-66v72,0,98,102,36,127v26,10,40,30,40,62"},"4":{"d":"174,-41r-32,0r0,41r-25,0r0,-41r-103,0r0,-23r93,-192r28,0r-93,192r75,0r0,-73r25,0r0,73r32,0r0,23"},"5":{"d":"101,-170v47,-2,65,44,65,85v0,47,-21,89,-71,88v-42,0,-68,-25,-70,-63r26,0v3,26,17,39,44,39v35,0,45,-33,45,-64v0,-31,-6,-62,-43,-62v-22,0,-37,10,-42,25r-24,0r0,-134r130,0r0,23r-106,0r0,81v10,-11,26,-18,46,-18"},"6":{"d":"166,-74v0,44,-27,76,-71,76v-68,1,-84,-72,-55,-131r63,-127r26,0r-57,115v48,-21,94,15,94,67xm140,-73v0,-28,-16,-52,-46,-52v-27,0,-45,20,-45,52v0,31,18,52,45,52v27,0,46,-21,46,-52"},"7":{"d":"170,-233r-89,233r-28,0r89,-233r-89,0r0,40r-26,0r0,-63r143,0r0,23"},"8":{"d":"170,-71v0,43,-34,73,-76,73v-42,0,-76,-30,-76,-73v0,-30,17,-50,39,-62v-58,-27,-36,-125,37,-125v72,0,95,98,37,125v22,12,39,32,39,62xm144,-71v0,-28,-22,-50,-50,-50v-28,0,-50,22,-50,50v0,28,22,50,50,50v28,0,50,-22,50,-50xm139,-189v0,-27,-19,-46,-45,-46v-26,0,-45,19,-45,46v0,27,19,45,45,45v26,0,45,-18,45,-45"},"9":{"d":"93,-258v69,-2,84,72,55,131r-63,127r-27,0r58,-115v-49,19,-94,-16,-94,-68v0,-44,27,-75,71,-75xm139,-184v0,-31,-19,-51,-46,-51v-27,0,-45,20,-45,51v0,28,15,52,45,52v27,0,46,-20,46,-52"},":":{"d":"75,-108r-34,0r0,-34r34,0r0,34xm75,0r-34,0r0,-34r34,0r0,34","w":106},";":{"d":"74,23r-32,29r0,-84r32,0r0,55xm75,-108r-34,0r0,-34r34,0r0,34","w":106},"<":{"d":"153,-24r-119,-61r0,-24r119,-60r0,28r-90,44r90,45r0,28"},"=":{"d":"169,-115r-150,0r0,-24r150,0r0,24xm169,-54r-150,0r0,-24r150,0r0,24"},">":{"d":"153,-85r-119,61r0,-28r90,-45r-90,-44r0,-28r119,60r0,24"},"?":{"d":"95,-258v57,0,87,67,51,109v-13,24,-39,38,-36,77r-26,0v-6,-59,52,-70,52,-121v0,-24,-17,-42,-41,-42v-26,0,-42,19,-42,42r-26,0v0,-37,29,-65,68,-65xm113,0r-31,0r0,-30r31,0r0,30","w":178},"@":{"d":"102,-257v74,0,129,9,129,78r0,179r-25,0r0,-20v-42,49,-127,14,-113,-66v-13,-81,69,-113,113,-65v5,-49,-9,-84,-54,-84v-55,0,-106,2,-101,56v5,58,-19,139,21,165r-18,17v-48,-28,-23,-115,-28,-182v-3,-47,28,-78,76,-78xm206,-86v0,-33,-6,-66,-44,-66v-38,0,-44,33,-44,66v0,33,6,66,44,66v38,0,44,-33,44,-66","w":256},"A":{"d":"216,0r-30,0r-20,-58r-112,0r-21,58r-29,0r95,-256r23,0xm158,-82r-47,-135r-49,135r96,0","w":219,"k":{"y":6,"v":6,"Y":13,"W":5,"V":13,"T":22,"Q":4,"O":4,"J":-4,"G":4,"C":4}},"B":{"d":"213,-71v2,84,-94,71,-176,71r0,-256v79,-1,175,-12,172,68v0,27,-16,48,-38,56v24,9,42,30,42,61xm186,-72v0,-55,-67,-46,-122,-46r0,94v56,1,122,8,122,-48xm182,-188v0,-56,-65,-43,-118,-44r0,89v54,-1,118,11,118,-45","w":240,"k":{"J":10}},"C":{"d":"55,-128v0,79,9,106,62,106v32,0,55,-21,62,-52r27,0v-8,48,-43,76,-89,76v-66,0,-90,-44,-90,-130v0,-86,23,-130,90,-130v46,0,80,28,89,76r-28,0v-7,-31,-29,-52,-61,-52v-53,0,-62,28,-62,106","w":229,"k":{"Y":4,"X":4,"W":4,"V":4,"T":7,"J":12,"A":4}},"D":{"d":"125,-256v70,-5,90,63,90,125v0,36,1,79,-25,107v-30,32,-95,22,-153,24r0,-256r88,0xm188,-131v0,-55,-14,-101,-68,-101r-56,0r0,208v43,-1,84,6,107,-19v17,-19,17,-57,17,-88","w":242,"k":{"Y":4,"X":4,"W":4,"V":4,"T":7,"J":13,"A":4}},"E":{"d":"196,0r-159,0r0,-256r159,0r0,24r-132,0r0,91r113,0r0,24r-113,0r0,93r132,0r0,24","w":216,"k":{"J":3}},"F":{"d":"196,-232r-132,0r0,94r113,0r0,25r-113,0r0,113r-27,0r0,-256r159,0r0,24","w":208,"k":{"z":11,"x":11,"u":11,"r":11,"p":11,"o":14,"n":11,"m":11,"e":14,"c":14,"a":14,"S":4,"Q":7,"O":7,"J":49,"G":7,"C":7,"A":22,".":35}},"G":{"d":"117,-22v43,0,70,-35,63,-88r-63,0r0,-24r90,0v10,81,-24,136,-90,136v-66,0,-90,-44,-90,-130v0,-86,22,-130,90,-130v49,0,82,31,90,76r-28,0v-7,-32,-30,-52,-62,-52v-53,0,-62,28,-62,106v0,79,9,106,62,106","w":234,"k":{"Y":4,"X":4,"W":4,"V":4,"T":7,"J":14,"A":4}},"H":{"d":"213,0r-27,0r0,-117r-122,0r0,117r-27,0r0,-256r27,0r0,115r122,0r0,-115r27,0r0,256","w":250},"I":{"d":"64,0r-27,0r0,-256r27,0r0,256","w":101},"J":{"d":"147,-78v6,75,-92,104,-139,57r19,-18v27,32,93,17,93,-42r0,-175r27,0r0,178","w":180,"k":{"A":4}},"K":{"d":"229,0r-32,0r-79,-136r-54,64r0,72r-27,0r0,-256r27,0r0,147r120,-147r33,0r-80,99","w":234,"k":{"y":11,"Q":4,"O":4,"J":-4,"G":4,"C":4}},"L":{"d":"195,0r-158,0r0,-256r27,0r0,232r131,0r0,24","w":206,"k":{"y":22,"Y":29,"W":14,"V":25,"U":12,"T":29,"Q":13,"O":13,"J":-4,"G":13,"C":13}},"M":{"d":"257,0r-28,0r0,-195r-70,155r-23,0r-72,-155r0,195r-27,0r0,-256r27,0r84,181r81,-181r28,0r0,256","w":293},"N":{"d":"226,0r-25,0r-137,-206r0,206r-27,0r0,-256r26,0r136,205r0,-205r27,0r0,256","w":263},"O":{"d":"117,-258v67,0,90,44,90,130v0,86,-22,130,-90,130v-67,0,-90,-44,-90,-130v0,-86,22,-130,90,-130xm117,-22v51,-9,62,-28,62,-106v0,-79,-9,-97,-62,-106v-52,8,-62,28,-62,106v0,79,11,96,62,106","w":234,"k":{"Y":4,"X":4,"W":4,"V":4,"T":7,"J":14,"A":4}},"P":{"d":"212,-181v1,72,-70,82,-148,76r0,105r-27,0r0,-256r95,0v47,0,80,29,80,75xm184,-181v0,-60,-63,-51,-120,-51r0,102v57,0,120,9,120,-51","w":226,"k":{"s":4,"q":4,"o":4,"g":4,"e":4,"d":4,"c":4,"a":4,"J":43,"A":18,".":40}},"Q":{"d":"117,-258v67,0,90,44,90,130v0,49,0,74,-18,96r28,28r-16,17r-29,-29v-75,47,-165,-4,-145,-112v-7,-86,22,-130,90,-130xm55,-128v0,79,10,106,62,106v14,0,26,-5,36,-13r-32,-32r17,-17r31,32v9,-15,10,-35,10,-76v0,-79,-9,-97,-62,-106v-52,8,-62,28,-62,106","w":233},"R":{"d":"216,0r-32,0r-58,-114r-62,0r0,114r-27,0r0,-256r98,0v45,0,76,27,76,71v0,37,-22,62,-55,69xm184,-185v0,-57,-65,-47,-120,-47r0,94v55,0,120,11,120,-47","w":236,"k":{"J":9}},"S":{"d":"170,-121v47,47,11,123,-67,123v-39,0,-64,-10,-88,-34r19,-18v32,42,130,39,130,-20v-1,-80,-142,-15,-142,-116v0,-77,114,-93,158,-44r-17,17v-28,-34,-114,-30,-114,26v0,60,93,38,121,66","w":211,"k":{"Y":7,"S":6,"J":7}},"T":{"d":"186,-232r-74,0r0,232r-27,0r0,-232r-74,0r0,-24r175,0r0,24","w":197,"k":{"z":19,"y":19,"x":19,"w":19,"v":19,"u":19,"s":27,"r":19,"q":27,"p":19,"o":27,"n":19,"m":19,"g":27,"e":27,"d":27,"c":27,"a":27,"Q":7,"O":7,"J":29,"G":7,"C":7,"A":22,".":29}},"U":{"d":"212,-85v0,51,-37,87,-89,87v-52,0,-90,-36,-90,-87r0,-171r28,0r0,169v0,39,25,65,62,65v37,0,62,-26,62,-65r0,-169r27,0r0,171","w":245,"k":{"J":12}},"V":{"d":"194,-256r-85,256r-22,0r-84,-256r29,0r66,207r67,-207r29,0","w":196,"k":{"z":7,"y":4,"x":7,"u":7,"s":14,"r":7,"q":14,"p":7,"o":14,"n":7,"m":7,"g":14,"e":14,"d":14,"c":14,"a":14,"Q":4,"O":4,"G":4,"C":4,"A":13,".":29}},"W":{"d":"302,-256r-66,256r-25,0r-57,-205r-57,205r-26,0r-65,-256r29,0r50,206r56,-206r25,0r56,206r51,-206r29,0","w":307,"k":{"s":14,"q":14,"o":14,"g":14,"e":14,"d":14,"c":14,"a":14,"Q":4,"O":4,"G":4,"C":4,"A":4,".":18}},"X":{"d":"193,0r-32,0r-62,-108r-63,108r-31,0r79,-131r-74,-125r32,0r57,101r57,-101r32,0r-74,125","w":198,"k":{"y":7,"Q":4,"O":4,"J":-4,"G":4,"C":4}},"Y":{"d":"182,-256r-75,150r0,106r-28,0r0,-106r-76,-150r29,0r61,122r60,-122r29,0","w":185,"k":{"z":14,"x":14,"u":14,"s":29,"r":14,"q":29,"p":14,"o":29,"n":14,"m":14,"g":29,"e":29,"d":29,"c":29,"a":29,"Q":4,"O":4,"J":14,"G":4,"C":4,"A":14,".":29}},"Z":{"d":"180,0r-159,0r0,-26r128,-206r-123,0r0,-24r154,0r0,23r-130,209r130,0r0,24","w":200},"[":{"d":"97,27r-64,0r0,-310r64,0r0,23r-38,0r0,264r38,0r0,23","w":112},"\\":{"d":"128,27r-26,0r-102,-309r26,0","w":127},"]":{"d":"80,27r-64,0r0,-23r39,0r0,-265r-39,0r0,-22r64,0r0,310","w":112},"^":{"d":"167,-149r-26,0r-44,-82r-44,82r-27,0r59,-109r24,0","w":193},"_":{"d":"193,59r-193,0r0,-18r193,0r0,18","w":193},"`":{"d":"108,-214r-24,0r-39,-55r31,0","w":180},"a":{"d":"133,-17v-32,35,-115,23,-115,-33v0,-50,59,-55,115,-51v3,-37,-7,-56,-46,-56v-23,0,-34,5,-44,20r-18,-16v31,-46,134,-32,134,33r0,120r-26,0r0,-17xm84,-20v35,0,55,-19,49,-62v-38,0,-89,-7,-89,32v0,21,12,30,40,30","w":189},"b":{"d":"108,-179v51,-2,65,44,65,90v0,46,-13,93,-65,91v-19,0,-36,-4,-50,-23r0,21r-26,0r0,-256r26,0r0,99v14,-18,31,-22,50,-22xm147,-89v0,-35,-5,-67,-44,-67v-39,0,-45,32,-45,67v0,35,6,68,45,68v39,0,44,-33,44,-68","w":196},"c":{"d":"49,-89v-8,62,58,90,93,48r17,17v-49,54,-136,23,-136,-65v0,-88,87,-117,136,-64r-17,17v-34,-42,-101,-14,-93,47","w":176,"k":{"w":7,"o":5,"e":5,"d":4,"c":5,"a":4}},"d":{"d":"23,-89v0,-45,14,-92,65,-90v19,0,36,4,50,22r0,-99r26,0r0,256r-26,0r0,-21v-14,19,-31,23,-50,23v-51,2,-65,-45,-65,-91xm138,-89v0,-35,-5,-67,-44,-67v-39,0,-45,32,-45,67v0,35,6,68,45,68v39,0,44,-33,44,-68","w":196},"e":{"d":"168,-82r-119,0v-6,62,66,79,98,41r18,16v-48,50,-142,33,-142,-64v0,-57,27,-90,72,-90v50,0,76,38,73,97xm142,-101v8,-58,-69,-75,-88,-30v-4,10,-4,16,-5,30r93,0","w":190,"k":{"y":4,"x":6,"w":2,"v":4}},"f":{"d":"102,-156r-38,0r0,156r-26,0r0,-156r-23,0r0,-20r23,0v-5,-52,7,-88,64,-81r0,22v-39,-7,-40,22,-38,59r38,0r0,20","w":113,"k":{"o":7,"e":7,"c":7,"a":7,".":18}},"g":{"d":"23,-90v0,-46,15,-90,65,-89v19,0,36,4,50,23r0,-21r25,0r0,182v7,71,-90,101,-134,53r17,-17v29,35,99,15,91,-37r0,-27v-14,18,-31,23,-50,23v-49,0,-64,-44,-64,-90xm137,-90v0,-33,-5,-66,-44,-66v-39,0,-44,33,-44,66v0,33,5,66,44,66v39,0,44,-33,44,-66","w":195},"h":{"d":"172,0r-26,0v-5,-59,22,-156,-43,-156v-66,0,-40,96,-45,156r-26,0r0,-256r26,0r0,98v36,-42,114,-19,114,44r0,114","w":202},"i":{"d":"58,0r-26,0r0,-177r26,0r0,177xm60,-228r-29,0r0,-29r29,0r0,29","w":91},"j":{"d":"58,32v1,33,-22,53,-63,48r0,-23v24,2,37,-3,37,-26r0,-207r26,0r0,208xm60,-228r-29,0r0,-29r29,0r0,29","w":91},"k":{"d":"181,0r-32,0r-56,-91r-35,40r0,51r-26,0r0,-256r26,0r0,171r80,-92r33,0r-60,68","w":192,"k":{"q":7,"o":7,"g":7,"e":7,"d":7,"c":7}},"l":{"d":"95,0v-40,4,-63,-13,-63,-47r0,-209r26,0r0,208v-2,23,13,28,37,26r0,22","w":106,"k":{"y":8,"w":7,"v":14,"o":7,"e":9,"c":9}},"m":{"d":"163,-150v31,-50,123,-32,123,37r0,113r-26,0v-5,-60,21,-156,-44,-156v-66,0,-39,96,-44,156r-26,0v-5,-59,22,-156,-43,-156v-66,0,-40,96,-45,156r-26,0r0,-177r26,0r0,19v26,-31,86,-27,105,8","w":316},"n":{"d":"58,-158v37,-42,114,-18,114,45r0,113r-26,0v-5,-60,21,-156,-44,-156v-65,0,-39,96,-44,156r-26,0r0,-177r26,0r0,19","w":202},"o":{"d":"95,-179v50,0,73,42,73,90v0,48,-22,91,-73,91v-50,0,-72,-43,-72,-91v0,-48,22,-90,72,-90xm95,-21v35,0,47,-33,47,-68v0,-34,-12,-67,-47,-67v-34,0,-46,33,-46,67v0,34,11,68,46,68","w":190,"k":{"y":4,"x":7,"w":2,"v":4}},"p":{"d":"108,-179v51,-2,65,44,65,90v0,46,-13,93,-65,91v-19,0,-36,-5,-50,-23r0,100r-26,0r0,-256r26,0r0,21v14,-19,31,-23,50,-23xm147,-89v0,-35,-5,-67,-44,-67v-39,0,-45,32,-45,67v0,35,6,68,45,68v39,0,44,-33,44,-68","w":196},"q":{"d":"23,-89v0,-45,14,-92,65,-90v19,0,36,4,50,23r0,-21r26,0r0,256r-26,0r0,-100v-14,18,-31,23,-50,23v-51,2,-65,-45,-65,-91xm138,-89v0,-35,-5,-67,-44,-67v-39,0,-45,32,-45,67v0,35,6,68,45,68v39,0,44,-33,44,-68","w":196},"r":{"d":"150,-163r-19,20v-26,-29,-73,-6,-73,34r0,109r-26,0r0,-177r26,0r0,21v18,-26,67,-33,92,-7","w":151,"k":{"s":4,"q":12,"o":12,"g":12,"e":12,"d":12,"c":12,"a":4,".":43,",":43}},"s":{"d":"160,-52v0,62,-110,70,-145,29r18,-18v21,29,100,31,102,-10v1,-25,-34,-27,-59,-29v-35,-3,-53,-18,-53,-47v0,-57,93,-65,129,-33r-17,17v-22,-20,-88,-21,-86,15v-3,25,33,26,59,28v31,2,52,15,52,48","w":178,"k":{"v":4,"t":4,"s":6}},"t":{"d":"100,0v-40,5,-64,-15,-63,-48r0,-108r-23,0r0,-20r23,0r0,-55r26,0r0,55r37,0r0,20r-37,0r0,108v-1,21,14,28,37,26r0,22","w":119,"k":{"o":3,"e":3,"c":3,"a":3}},"u":{"d":"144,-20v-36,43,-113,20,-113,-44r0,-113r26,0v5,59,-22,156,43,156v65,0,39,-96,44,-156r26,0r0,177r-26,0r0,-20","w":202},"v":{"d":"157,-177r-65,177r-23,0r-65,-177r28,0r48,142r49,-142r28,0","w":160,"k":{"s":4,"o":4,"e":4,"c":4,"a":4,".":24}},"w":{"d":"257,-177r-56,177r-24,0r-47,-138r-46,138r-24,0r-56,-177r28,0r41,142r46,-142r22,0r47,142r41,-142r28,0","w":260,"k":{"o":2,"e":2,"c":2,".":19}},"x":{"d":"160,0r-31,0r-43,-69r-43,69r-31,0r60,-90r-58,-87r32,0r40,65r40,-65r32,0r-58,87","w":172,"k":{"o":7,"e":7,"c":7}},"y":{"d":"157,-177r-81,220v-8,25,-27,35,-58,33r0,-23v39,6,38,-33,50,-57r-64,-173r28,0r49,142r48,-142r28,0","w":160,"k":{"o":4,"e":4,"c":4,"a":4,".":24,",":29}},"z":{"d":"147,0r-129,0r0,-22r99,-132r-94,0r0,-23r124,0r0,22r-99,132r99,0r0,23","w":165},"{":{"d":"53,-128v58,22,-22,143,57,132r0,23v-40,2,-61,-6,-61,-47v0,-38,19,-103,-32,-97r0,-23v80,10,-27,-161,93,-143r0,23v-75,-15,-1,108,-57,132","w":127},"|":{"d":"72,27r-26,0r0,-310r26,0r0,310","w":117},"}":{"d":"17,-283v119,-19,10,142,93,143r0,23v-79,-7,26,162,-93,144r0,-23v75,15,0,-109,58,-132v-33,-8,-23,-64,-23,-104v0,-28,-9,-28,-35,-28r0,-23","w":127},"~":{"d":"18,-95v44,-66,96,27,142,-21r16,16v-45,65,-96,-28,-143,21","w":194},"\u00a0":{"w":89}}});





// jQuery Alert Dialogs Plugin
//
// Version 1.1
//
// Cory S.N. LaViska
// A Beautiful Site (http://abeautifulsite.net/)
// 14 May 2009
//
// Visit http://abeautifulsite.net/notebook/87 for more information
//
// Usage:
//		jAlert( message, [title, callback] )
//		jConfirm( message, [title, callback] )
//		jPrompt( message, [value, title, callback] )
// 
// History:
//
//		1.00 - Released (29 December 2008)
//
//		1.01 - Fixed bug where unbinding would destroy all resize events
//
// License:
// 
// This plugin is dual-licensed under the GNU General Public License and the MIT License and
// is copyright 2008 A Beautiful Site, LLC. 
//
(function($) {
	
	$.alerts = {
		
		// These properties can be read/written by accessing $.alerts.propertyName from your scripts at any time
		
		verticalOffset: -75,                // vertical offset of the dialog from center screen, in pixels
		horizontalOffset: 0,                // horizontal offset of the dialog from center screen, in pixels/
		repositionOnResize: true,           // re-centers the dialog on window resize
		overlayOpacity: .01,                // transparency level of overlay
		overlayColor: '#FFF',               // base color of overlay
		draggable: true,                    // make the dialogs draggable (requires UI Draggables plugin)
		okButton: '&nbsp;OK&nbsp;',         // text for the OK button
		cancelButton: '&nbsp;Cancel&nbsp;', // text for the Cancel button
		dialogClass: null,                  // if specified, this class will be applied to all dialogs
		
		// Public methods
		
		alert: function(message, title, callback) {
			if( title == null ) title = 'Alert';
			$.alerts._show(title, message, null, 'alert', function(result) {
				if( callback ) callback(result);
			});
		},
		
		confirm: function(message, title, callback) {
			if( title == null ) title = 'Confirm';
			$.alerts._show(title, message, null, 'confirm', function(result) {
				if( callback ) callback(result);
			});
		},
			
		prompt: function(message, value, title, callback) {
			if( title == null ) title = 'Prompt';
			$.alerts._show(title, message, value, 'prompt', function(result) {
				if( callback ) callback(result);
			});
		},
		
		// Private methods
		
		_show: function(title, msg, value, type, callback) {
			
			$.alerts._hide();
			$.alerts._overlay('show');
			
			$("BODY").append(
			  '<div id="popup_container">' +
			    '<h1 id="popup_title"></h1>' +
			    '<div id="popup_content">' +
			      '<div id="popup_message"></div>' +
				  '</div>' +
			  '</div>');
			
			if( $.alerts.dialogClass ) $("#popup_container").addClass($.alerts.dialogClass);
			
			// IE6 Fix
			var pos = ($.browser.msie && parseInt($.browser.version) <= 6 ) ? 'absolute' : 'fixed'; 
			
			$("#popup_container").css({
				position: pos,
				zIndex: 99999,
				padding: 20,
				margin: 0
			});
			
			$("#popup_title").text(title);
			$("#popup_content").addClass(type);
			$("#popup_message").text(msg);
			$("#popup_message").html( $("#popup_message").text().replace(/\n/g, '<br />') );
			
			$("#popup_container").css({
				minWidth: $("#popup_container").outerWidth(),
				maxWidth: $("#popup_container").outerWidth()
			});
			
			$.alerts._reposition();
			$.alerts._maintainPosition(true);
			
			switch( type ) {
				case 'alert':
					$("#popup_message").after('<div id="popup_panel"><input type="button" value="' + $.alerts.okButton + '" id="popup_ok" /></div>');
					$("#popup_ok").click( function() {
						$.alerts._hide();
						callback(true);
					});
					$("#popup_ok").focus().keypress( function(e) {
						if( e.keyCode == 13 || e.keyCode == 27 ) $("#popup_ok").trigger('click');
					});
				break;
				case 'confirm':
					$("#popup_message").after('<div id="popup_panel"><input type="button" value="' + $.alerts.okButton + '" id="popup_ok" /> <input type="button" value="' + $.alerts.cancelButton + '" id="popup_cancel" /></div>');
					$("#popup_ok").click( function() {
						$.alerts._hide();
						if( callback ) callback(true);
					});
					$("#popup_cancel").click( function() {
						$.alerts._hide();
						if( callback ) callback(false);
					});
					$("#popup_ok").focus();
					$("#popup_ok, #popup_cancel").keypress( function(e) {
						if( e.keyCode == 13 ) $("#popup_ok").trigger('click');
						if( e.keyCode == 27 ) $("#popup_cancel").trigger('click');
					});
				break;
				case 'prompt':
					$("#popup_message").append('<br /><input type="text" size="30" id="popup_prompt" />').after('<div id="popup_panel"><input type="button" value="' + $.alerts.okButton + '" id="popup_ok" /> <input type="button" value="' + $.alerts.cancelButton + '" id="popup_cancel" /></div>');
					$("#popup_prompt").width( $("#popup_message").width() );
					$("#popup_ok").click( function() {
						var val = $("#popup_prompt").val();
						$.alerts._hide();
						if( callback ) callback( val );
					});
					$("#popup_cancel").click( function() {
						$.alerts._hide();
						if( callback ) callback( null );
					});
					$("#popup_prompt, #popup_ok, #popup_cancel").keypress( function(e) {
						if( e.keyCode == 13 ) $("#popup_ok").trigger('click');
						if( e.keyCode == 27 ) $("#popup_cancel").trigger('click');
					});
					if( value ) $("#popup_prompt").val(value);
					$("#popup_prompt").focus().select();
				break;
			}
			
			// Make draggable
			if( $.alerts.draggable ) {
				try {
					$("#popup_container").draggable({ handle: $("#popup_title") });
					$("#popup_title").css({ cursor: 'move' });
				} catch(e) { /* requires jQuery UI draggables */ }
			}
		},
		
		_hide: function() {
			$("#popup_container").remove();
			$.alerts._overlay('hide');
			$.alerts._maintainPosition(false);
		},
		
		_overlay: function(status) {
			switch( status ) {
				case 'show':
					$.alerts._overlay('hide');
					$("BODY").append('<div id="popup_overlay"></div>');
					$("#popup_overlay").css({
						position: 'absolute',
						zIndex: 99998,
						top: '0px',
						left: '0px',
						width: '100%',
						height: $(document).height(),
						background: $.alerts.overlayColor,
						opacity: $.alerts.overlayOpacity
					});
				break;
				case 'hide':
					$("#popup_overlay").remove();
				break;
			}
		},
		
		_reposition: function() {
			var top = (($(window).height() / 2) - ($("#popup_container").outerHeight() / 2)) + $.alerts.verticalOffset;
			var left = (($(window).width() / 2) - ($("#popup_container").outerWidth() / 2)) + $.alerts.horizontalOffset;
			if( top < 0 ) top = 0;
			if( left < 0 ) left = 0;
			
			// IE6 fix
			if( $.browser.msie && parseInt($.browser.version) <= 6 ) top = top + $(window).scrollTop();
			
			$("#popup_container").css({
				top: top + 'px',
				left: left + 'px'
			});
			$("#popup_overlay").height( $(document).height() );
			// IE8 fix - Added by Head
			if( $.browser.msie && parseInt($.browser.version) <= 8 ) $("#popup_overlay").height( $(document).height() - 5 ); 
		},
		
		_maintainPosition: function(status) {
			if( $.alerts.repositionOnResize ) {
				switch(status) {
					case true:
						$(window).bind('resize', $.alerts._reposition);
					break;
					case false:
						$(window).unbind('resize', $.alerts._reposition);
					break;
				}
			}
		}
	}
	// Shortuct functions
	jAlert = function(message, title, callback) {
		$.alerts.alert(message, title, callback);
	}
	jConfirm = function(message, title, callback) {
		$.alerts.confirm(message, title, callback);
	};
	jPrompt = function(message, value, title, callback) {
		$.alerts.prompt(message, value, title, callback);
	};
})(jQuery);

