<commit_before>//Hard code map bounds
var bounds = {
  l_lat: 37.306399999999996,
  h_lat: 38.316994299999998,
  l_lng: -123.02877599999999,
  h_lng: -121.637
}

var map;
var showTips = true; // Show Tooltips by default
var routes = new Array();
var errorAlert=0;

google.maps.Polyline.prototype.getBounds = function() {
  //Extends google maps API v3 to allow getting bounds of a polyline
  var bounds = new google.maps.LatLngBounds();
  this.getPath().forEach(function(e) {
    bounds.extend(e);
  });
  return bounds;
};

google.maps.LatLng.prototype.miTo = function(a){
  //Extends google maps API V3 to allow getting the length of a polyline
  var e = Math, ra = e.PI/180;
  var b = this.lat() * ra, c = a.lat() * ra, d = b - c;
  var g = this.lng() * ra - a.lng() * ra;
  var f = 2 * e.asin(e.sqrt(e.pow(e.sin(d/2), 2) + e.cos(b) * e.cos
(c) * e.pow(e.sin(g/2), 2)));
  return f * 3963.1676;
}
google.maps.Polyline.prototype.inMiles = function(n){
  var a = this.getPath(n), len = a.getLength(), dist = 0;
  for(var i=0; i<len-1; i++){
    dist += a.getAt(i).miTo(a.getAt(i+1));
  }
  return dist;
}

$.extend({
  //Extends jQuery to get parameters from URL
  getUrlVars: function(){
    var vars = [], hash;
    var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
    for(var i = 0; i < hashes.length; i++)
    {
      hash = hashes[i].split('=');
      vars.push(hash[0]);
      vars[hash[0]] = hash[1];
    }
    return vars;
  },
  getUrlVar: function(name){
    return $.getUrlVars()[name];
  }
});

function formatTime(minutes1, minutes2){
  return (minutes1<60 && minutes2<60) ? Math.round(minutes1) + ' to ' + Math.round(minutes2) + ' min' : Math.round((minutes1/60)*10)/10 + ' to ' + Math.round((minutes2/60)*10)/10 + ' hours';
}

function dist(lat1,lat2,lon1,lon2) {
    var R = 3963.1676; // mi
    var dLat = (lat2-lat1)*3.14/180;
    var dLon = (lon2-lon1)*3.14/180;
    var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(lat1*3.14/180) * Math.cos(lat2*3.14/180) * Math.sin(dLon/2) * Math.sin(dLon/2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    var d = R * c;
    return d;
}

function proper(str){
    return str.replace(/\w\S*/, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
}

function checkBounds(lat1, lng1, lat2, lng2){
  return (lat1>bounds.h_lat || lat2>bounds.h_lat || lat1<bounds.l_lat || lat2<bounds.l_lat || lng1>bounds.h_lng || lng2>bounds.h_lng || lng1<bounds.l_lng || lng2<bounds.l_lng) ? false : true;
}

function launchMap(){
  map = new google.maps.Map(document.getElementById("map_canvas"), {
    zoom: 10,
    center: new google.maps.LatLng(37.880002, -122.189941),
    mapTypeId: google.maps.MapTypeId.ROADMAP
  });

  var bikeLayer = new google.maps.BicyclingLayer();
  bikeLayer.setMap(map);

  //Setup route lines
  for(i=0;i<3;i++){
    routes[i] = {
      routeline: new google.maps.Polyline()
    }
    // Add listener to route lines
    new google.maps.event.addListener(routes[i].routeline, "mouseover", function() { showRoute(i); });
  }
}

function submitForm() {
  // Redraws map based on info in the form
  if(mobile){
    $('#inputs input').blur();
    $.mobile.pageLoading();
  }
  start = $('#startbox').val();
  end = $('#finishbox').val();
  hill = $('#hills').val();

  //Validate inputs
  if(start==''){
    $('#startbox').addClass('error');
    return false;
  } else {$('#startbox').removeClass('error');}
  if(end==''){
    $('#finishbox').addClass('error');
    return false;
  } else {$('#finishbox').removeClass('error');}

  //Search for Richmond, if found add usa to end to avoid confusion with Canada
  if (start.search(/richmond/i) != -1) {
    start = start + ", usa";
  }
  if (end.search(/richmond/i) != -1) {
    end = end + ", usa";
  }

  geocoder = new google.maps.Geocoder();
  var lat1;
  var lng1;
  var lat2;
  var lng2;
  geocoder.geocode({address:start}, function(results, status){
    if (status == google.maps.GeocoderStatus.OK) {
      lat1 = results[0].geometry.location.lat();
      lng1 = results[0].geometry.location.lng();
      //Now geocode end address
      geocoder.geocode({address:end}, function(results, status){
        if (status == google.maps.GeocoderStatus.OK) {
          lat2 = results[0].geometry.location.lat();
          lng2 = results[0].geometry.location.lng();
          //Now move along
          if(checkBounds(lat1,lng1,lat2,lng2)){
            // Draw 3 paths, one for each safety level
            drawpath(lat1, lng1, lat2, lng2, hill, "low", true);
            drawpath(lat1, lng1, lat2, lng2, hill, "medium", true);
            drawpath(lat1, lng1, lat2, lng2, hill, "high", true);

            map.panTo(new google.maps.LatLng((lat1+lat2)/2,(lng1+lng2)/2));

            if(mobile){
              $.mobile.pageLoading( true );
              $.mobile.changePage($('#map'),"slide");
            }

          } else {
            alert("Bikemapper currently only works in the Bay Area.  Try making your addresses more specific by adding city and state names.");
          }
        } else {
          alert(end + " not found");
          return false;
        }
      });
    } else {
      alert(start + " not found");
      return false;
    }
  });
return false;
}

function drawpath(lat1, lng1, lat2, lng2, hill, safety, redraw){
  $('#welcome_screen').fadeOut(); // hide welcome screen if its still up
  $('#loading_image').show(); // show loading image, as request is about to start

  //Hide lines
  for(i in routes){
    routes[i].routeline.setMap(null);
  }
  // Define Route Server
  var routeserver = "http://api.bikesy.com";

  $.jsonp({
    "url": routeserver+"?lat1="+lat1+"&lng1="+lng1+"&lat2="+lat2+"&lng2="+lng2+"&hill="+hill+"&safety="+safety+"&format=json&jsoncallback=?",
    "success": function(json) {processpath(json, redraw, safety);},
    "error": function(){
      //On error, try again
      $.jsonp({
        "url": routeserver+"?lat1="+lat1+"&lng1="+lng1+"&lat2="+lat2+"&lng2="+lng2+"&hill="+hill+"&safety="+safety+"&format=json&jsoncallback=?",
        "success": function(json) {processpath(json, redraw, safety);},
        "error": function(){
          $('#loading_image').hide(); // hide loading image
          if(errorAlert==0){
            alert("There was an error retrieving the route data.  Please refresh the page and try again.");
          }
          errorAlert = 1;
        }
      });
    }
  });
}

function addMarker(latlng, type){
  if(type=="start"){

    if (typeof(start_marker) == "undefined"){
      shadow = new google.maps.MarkerImage(
        "images/shadow.png",
        new google.maps.Size(32, 32)
      );
      startIcon = new google.maps.MarkerImage(
        "images/green.png",
        new google.maps.Size(32, 32)
      );
      start_marker = new google.maps.Marker({
        map:map,
        shadow:shadow,
        draggable:true,
        icon:startIcon
      });
      google.maps.event.addListener(start_marker,'dragend',function(position){
        showTips = false;
        $("#dragtext").fadeOut();
        recalc('start');
      });
    }

    start_marker.setOptions({ position: latlng });
  } else if (type=="end"){
    if (typeof(end_marker) == "undefined"){
      shadow = new google.maps.MarkerImage(
        "images/shadow.png",
        new google.maps.Size(32, 32)
      );
      endIcon = new google.maps.MarkerImage(
        "images/red.png",
        new google.maps.Size(32, 32)
      );
      end_marker = new google.maps.Marker({
        map:map,
        shadow:shadow,
        draggable:true,
        icon:endIcon
      });
      google.maps.event.addListener(end_marker,'dragend',function(position){
        showTips = false;
        $("#dragtext").fadeOut();
        recalc('end');
      });
    }

    end_marker.setOptions({ position: latlng });
  }
}

function recalc(marker_name) {
  if(mobile){
    $.mobile.pageLoading();
  }
  if (typeof(start_marker) != "undefined"){
    lat1 = start_marker.getPosition().lat();
    lng1 = start_marker.getPosition().lng();
    lat2 = end_marker.getPosition().lat();
    lng2 = end_marker.getPosition().lng();
    distance = dist(lat1,lat2,lng1,lng2);
    var hill = $('#hills').val();

    if(checkBounds(lat1,lng1,lat2,lng2)){

      sCoords = new google.maps.LatLng(lat1,lng1);
      eCoords = new google.maps.LatLng(lat2,lng2);

      //Reverse Geocode
      switch(marker_name){
        case 'start':
          this.getAddress(sCoords, 'start');
          break;
        case 'end':
          this.getAddress(eCoords, 'end');
          break;
        case 'both':
          this.getAddress(sCoords, 'start');
          this.getAddress(eCoords, 'end');
          break;
      }

      //Remove old overlay
      if (typeof(routeoverlay) != "undefined"){routeoverlay.setMap(null);}

      // Draw 3 paths, one for each safety level
      drawpath(lat1, lng1, lat2, lng2, hill, "low", true);
      drawpath(lat1, lng1, lat2, lng2, hill, "medium", true);
      drawpath(lat1, lng1, lat2, lng2, hill, "high", true);
    }
    else{alert("Bikemapper currently only works in the Bay Area.");}
  }
}

function gviz(profile, width, height){
  if (typeof(table) == "undefined"){
    table = new google.visualization.DataTable();
    chart = new google.visualization.ScatterChart(document.getElementById('profile'));
  } else {
    table.removeColumn(0);
    table.removeColumn(0);
  }

  table.addColumn('number', 'Distance');
  table.addColumn('number', 'Elevation');
  // Round profile values
  for (i in profile){
    profile[i][0] = Math.round(profile[i][0]*100)/100;
    profile[i][1] = Math.round(profile[i][1]);
  }

  //Determine appropriate chart padding
  var area = (width>400) ? {left: 80, width:(width-90)} : {left: 40, width:(width-50)};

  table.addRows(profile);
  chart.draw(table, {width: width, height: height, legend: 'none', lineWidth: 2, pointSize: 0, title: 'Elevation Profile', titleTextStyle: {fontSize: '16'}, vAxis:{title:'Elevation (ft)', textStyle:{fontSize: '12'}}, hAxis:{title:'Distance along route (mi)', textStyle:{fontSize: '12'}}, chartArea:area});
}

function getElevGain(profile) {
  var totalElevGain = 0;
  for (i=0;i<(profile.length-1);i++){
    if (profile[i][1] < profile[i+1][1]) {
      totalElevGain += profile[i+1][1]-profile[i][1];
    }
  }
  //Convert to Feet
  return totalElevGain*3.2808399;
}

function getElevChange(profile) {
  var totalElevChange = profile[profile.length-1][1] - profile[0][1];
  //Convert to Feet
  return totalElevChange*3.2808399;
}

function getAddress(latlng, marker_name) {
  geocoder = new google.maps.Geocoder();
  geocoder.geocode({'latLng': latlng}, function(results, status) {
    if (status == google.maps.GeocoderStatus.OK) {
      if(marker_name=='start') {
        $('#startbox').val(results[0].formatted_address);
      } else if(marker_name=='end') {
        $('#finishbox').val(results[0].formatted_address);
      }
    }
  });
}

function getStartGeoLocator(position) {
  sCoords = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
  geocoder = new google.maps.Geocoder();
  geocoder.geocode({'latLng': sCoords}, function(results, status) {
    if (status == google.maps.GeocoderStatus.OK) {
      $('#startbox').val(results[0].formatted_address).replace(/, CA, USA/g, "");;
    }
    $('.geolocationwaiting').fadeOut();
  });
}

function getEndGeoLocator(position) {
  eCoords = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
  geocoder = new google.maps.Geocoder();
  geocoder.geocode({'latLng': eCoords}, function(results, status) {
    if (status == google.maps.GeocoderStatus.OK) {
      $('#finishbox').val(results[0].formatted_address).replace(/, CA, USA/g, "");;
    }
    $('.geolocationwaiting').fadeOut();
  });
}

function showGeoLocatorError(error){
  $('#geolocationwaiting').fadeOut();
  if(error.code==1){
    alert("To determine your current location you must click \"Share Location\" in the top bar in your browser.");
  } else if (error.code==2 || error.code==3 || error.code==0){
    alert("Your current location couldn't be determined.  Please enter the start and end locations manually.");
  }
}

function detectRouteFromURL(){
  //Detect saved route from URL
  if($.getUrlVar('start')!=undefined && $.getUrlVar('end')!=undefined){
    $('#startbox').val($.getUrlVar('start').replace(/\+/g,' '));
    $('#finishbox').val($.getUrlVar('end').replace(/\+/g,' '));
    // Strip off trailing #
    if($.getUrlVar('hill')!=undefined) {
     $('#hills').val($.getUrlVar('hill').replace(/#/g,''));
    }
    submitForm();
  }
}<commit_msg>Fix for form validation<commit_after>//Hard code map bounds
var bounds = {
  l_lat: 37.306399999999996,
  h_lat: 38.316994299999998,
  l_lng: -123.02877599999999,
  h_lng: -121.637
}

var map;
var showTips = true; // Show Tooltips by default
var routes = new Array();
var errorAlert=0;

google.maps.Polyline.prototype.getBounds = function() {
  //Extends google maps API v3 to allow getting bounds of a polyline
  var bounds = new google.maps.LatLngBounds();
  this.getPath().forEach(function(e) {
    bounds.extend(e);
  });
  return bounds;
};

google.maps.LatLng.prototype.miTo = function(a){
  //Extends google maps API V3 to allow getting the length of a polyline
  var e = Math, ra = e.PI/180;
  var b = this.lat() * ra, c = a.lat() * ra, d = b - c;
  var g = this.lng() * ra - a.lng() * ra;
  var f = 2 * e.asin(e.sqrt(e.pow(e.sin(d/2), 2) + e.cos(b) * e.cos
(c) * e.pow(e.sin(g/2), 2)));
  return f * 3963.1676;
}
google.maps.Polyline.prototype.inMiles = function(n){
  var a = this.getPath(n), len = a.getLength(), dist = 0;
  for(var i=0; i<len-1; i++){
    dist += a.getAt(i).miTo(a.getAt(i+1));
  }
  return dist;
}

$.extend({
  //Extends jQuery to get parameters from URL
  getUrlVars: function(){
    var vars = [], hash;
    var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
    for(var i = 0; i < hashes.length; i++)
    {
      hash = hashes[i].split('=');
      vars.push(hash[0]);
      vars[hash[0]] = hash[1];
    }
    return vars;
  },
  getUrlVar: function(name){
    return $.getUrlVars()[name];
  }
});

function formatTime(minutes1, minutes2){
  return (minutes1<60 && minutes2<60) ? Math.round(minutes1) + ' to ' + Math.round(minutes2) + ' min' : Math.round((minutes1/60)*10)/10 + ' to ' + Math.round((minutes2/60)*10)/10 + ' hours';
}

function dist(lat1,lat2,lon1,lon2) {
    var R = 3963.1676; // mi
    var dLat = (lat2-lat1)*3.14/180;
    var dLon = (lon2-lon1)*3.14/180;
    var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(lat1*3.14/180) * Math.cos(lat2*3.14/180) * Math.sin(dLon/2) * Math.sin(dLon/2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    var d = R * c;
    return d;
}

function proper(str){
    return str.replace(/\w\S*/, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
}

function checkBounds(lat1, lng1, lat2, lng2){
  return (lat1>bounds.h_lat || lat2>bounds.h_lat || lat1<bounds.l_lat || lat2<bounds.l_lat || lng1>bounds.h_lng || lng2>bounds.h_lng || lng1<bounds.l_lng || lng2<bounds.l_lng) ? false : true;
}

function launchMap(){
  map = new google.maps.Map(document.getElementById("map_canvas"), {
    zoom: 10,
    center: new google.maps.LatLng(37.880002, -122.189941),
    mapTypeId: google.maps.MapTypeId.ROADMAP
  });

  var bikeLayer = new google.maps.BicyclingLayer();
  bikeLayer.setMap(map);

  //Setup route lines
  for(i=0;i<3;i++){
    routes[i] = {
      routeline: new google.maps.Polyline()
    }
    // Add listener to route lines
    new google.maps.event.addListener(routes[i].routeline, "mouseover", function() { showRoute(i); });
  }
}

function submitForm() {
  // Redraws map based on info in the form
  if(mobile){
    $('#inputs input').blur();
    $.mobile.pageLoading();
  }
  start = $('#startbox').val();
  end = $('#finishbox').val();
  hill = $('#hills').val();

  //Validate inputs
  if(start==''){
    $('#startbox').addClass('error');
    if(mobile){
      $('#startbox').focus();
      $.mobile.pageLoading(true);
    }
    return false;
  } else {$('#startbox').removeClass('error');}
  if(end==''){
    $('#finishbox').addClass('error');
    if(mobile){
      $('#finishbox').focus();
      $.mobile.pageLoading(true);
    }
    return false;
  } else {$('#finishbox').removeClass('error');}

  //Search for Richmond, if found add usa to end to avoid confusion with Canada
  if (start.search(/richmond/i) != -1) {
    start = start + ", usa";
  }
  if (end.search(/richmond/i) != -1) {
    end = end + ", usa";
  }

  geocoder = new google.maps.Geocoder();
  var lat1;
  var lng1;
  var lat2;
  var lng2;
  geocoder.geocode({address:start}, function(results, status){
    if (status == google.maps.GeocoderStatus.OK) {
      lat1 = results[0].geometry.location.lat();
      lng1 = results[0].geometry.location.lng();
      //Now geocode end address
      geocoder.geocode({address:end}, function(results, status){
        if (status == google.maps.GeocoderStatus.OK) {
          lat2 = results[0].geometry.location.lat();
          lng2 = results[0].geometry.location.lng();
          //Now move along
          if(checkBounds(lat1,lng1,lat2,lng2)){
            // Draw 3 paths, one for each safety level
            drawpath(lat1, lng1, lat2, lng2, hill, "low", true);
            drawpath(lat1, lng1, lat2, lng2, hill, "medium", true);
            drawpath(lat1, lng1, lat2, lng2, hill, "high", true);

            map.panTo(new google.maps.LatLng((lat1+lat2)/2,(lng1+lng2)/2));

            if(mobile){
              $.mobile.pageLoading( true );
              $.mobile.changePage($('#map'),"slide");
            }

          } else {
            alert("Bikemapper currently only works in the Bay Area.  Try making your addresses more specific by adding city and state names.");
          }
        } else {
          alert(end + " not found");
          return false;
        }
      });
    } else {
      alert(start + " not found");
      return false;
    }
  });
return false;
}

function drawpath(lat1, lng1, lat2, lng2, hill, safety, redraw){
  $('#welcome_screen').fadeOut(); // hide welcome screen if its still up
  $('#loading_image').show(); // show loading image, as request is about to start

  //Hide lines
  for(i in routes){
    routes[i].routeline.setMap(null);
  }
  // Define Route Server
  var routeserver = "http://api.bikesy.com";

  $.jsonp({
    "url": routeserver+"?lat1="+lat1+"&lng1="+lng1+"&lat2="+lat2+"&lng2="+lng2+"&hill="+hill+"&safety="+safety+"&format=json&jsoncallback=?",
    "success": function(json) {processpath(json, redraw, safety);},
    "error": function(){
      //On error, try again
      $.jsonp({
        "url": routeserver+"?lat1="+lat1+"&lng1="+lng1+"&lat2="+lat2+"&lng2="+lng2+"&hill="+hill+"&safety="+safety+"&format=json&jsoncallback=?",
        "success": function(json) {processpath(json, redraw, safety);},
        "error": function(){
          $('#loading_image').hide(); // hide loading image
          if(errorAlert==0){
            alert("There was an error retrieving the route data.  Please refresh the page and try again.");
          }
          errorAlert = 1;
        }
      });
    }
  });
}

function addMarker(latlng, type){
  if(type=="start"){

    if (typeof(start_marker) == "undefined"){
      shadow = new google.maps.MarkerImage(
        "images/shadow.png",
        new google.maps.Size(32, 32)
      );
      startIcon = new google.maps.MarkerImage(
        "images/green.png",
        new google.maps.Size(32, 32)
      );
      start_marker = new google.maps.Marker({
        map:map,
        shadow:shadow,
        draggable:true,
        icon:startIcon
      });
      google.maps.event.addListener(start_marker,'dragend',function(position){
        showTips = false;
        $("#dragtext").fadeOut();
        recalc('start');
      });
    }

    start_marker.setOptions({ position: latlng });
  } else if (type=="end"){
    if (typeof(end_marker) == "undefined"){
      shadow = new google.maps.MarkerImage(
        "images/shadow.png",
        new google.maps.Size(32, 32)
      );
      endIcon = new google.maps.MarkerImage(
        "images/red.png",
        new google.maps.Size(32, 32)
      );
      end_marker = new google.maps.Marker({
        map:map,
        shadow:shadow,
        draggable:true,
        icon:endIcon
      });
      google.maps.event.addListener(end_marker,'dragend',function(position){
        showTips = false;
        $("#dragtext").fadeOut();
        recalc('end');
      });
    }

    end_marker.setOptions({ position: latlng });
  }
}

function recalc(marker_name) {
  if(mobile){
    $.mobile.pageLoading();
  }
  if (typeof(start_marker) != "undefined"){
    lat1 = start_marker.getPosition().lat();
    lng1 = start_marker.getPosition().lng();
    lat2 = end_marker.getPosition().lat();
    lng2 = end_marker.getPosition().lng();
    distance = dist(lat1,lat2,lng1,lng2);
    var hill = $('#hills').val();

    if(checkBounds(lat1,lng1,lat2,lng2)){

      sCoords = new google.maps.LatLng(lat1,lng1);
      eCoords = new google.maps.LatLng(lat2,lng2);

      //Reverse Geocode
      switch(marker_name){
        case 'start':
          this.getAddress(sCoords, 'start');
          break;
        case 'end':
          this.getAddress(eCoords, 'end');
          break;
        case 'both':
          this.getAddress(sCoords, 'start');
          this.getAddress(eCoords, 'end');
          break;
      }

      //Remove old overlay
      if (typeof(routeoverlay) != "undefined"){routeoverlay.setMap(null);}

      // Draw 3 paths, one for each safety level
      drawpath(lat1, lng1, lat2, lng2, hill, "low", true);
      drawpath(lat1, lng1, lat2, lng2, hill, "medium", true);
      drawpath(lat1, lng1, lat2, lng2, hill, "high", true);
    }
    else{alert("Bikemapper currently only works in the Bay Area.");}
  }
}

function gviz(profile, width, height){
  if (typeof(table) == "undefined"){
    table = new google.visualization.DataTable();
    chart = new google.visualization.ScatterChart(document.getElementById('profile'));
  } else {
    table.removeColumn(0);
    table.removeColumn(0);
  }

  table.addColumn('number', 'Distance');
  table.addColumn('number', 'Elevation');
  // Round profile values
  for (i in profile){
    profile[i][0] = Math.round(profile[i][0]*100)/100;
    profile[i][1] = Math.round(profile[i][1]);
  }

  //Determine appropriate chart padding
  var area = (width>400) ? {left: 80, width:(width-90)} : {left: 40, width:(width-50)};

  table.addRows(profile);
  chart.draw(table, {width: width, height: height, legend: 'none', lineWidth: 2, pointSize: 0, title: 'Elevation Profile', titleTextStyle: {fontSize: '16'}, vAxis:{title:'Elevation (ft)', textStyle:{fontSize: '12'}}, hAxis:{title:'Distance along route (mi)', textStyle:{fontSize: '12'}}, chartArea:area});
}

function getElevGain(profile) {
  var totalElevGain = 0;
  for (i=0;i<(profile.length-1);i++){
    if (profile[i][1] < profile[i+1][1]) {
      totalElevGain += profile[i+1][1]-profile[i][1];
    }
  }
  //Convert to Feet
  return totalElevGain*3.2808399;
}

function getElevChange(profile) {
  var totalElevChange = profile[profile.length-1][1] - profile[0][1];
  //Convert to Feet
  return totalElevChange*3.2808399;
}

function getAddress(latlng, marker_name) {
  geocoder = new google.maps.Geocoder();
  geocoder.geocode({'latLng': latlng}, function(results, status) {
    if (status == google.maps.GeocoderStatus.OK) {
      if(marker_name=='start') {
        $('#startbox').val(results[0].formatted_address);
      } else if(marker_name=='end') {
        $('#finishbox').val(results[0].formatted_address);
      }
    }
  });
}

function getStartGeoLocator(position) {
  sCoords = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
  geocoder = new google.maps.Geocoder();
  geocoder.geocode({'latLng': sCoords}, function(results, status) {
    if (status == google.maps.GeocoderStatus.OK) {
      $('#startbox').val(results[0].formatted_address).replace(/, CA, USA/g, "");;
    }
    $('.geolocationwaiting').fadeOut();
  });
}

function getEndGeoLocator(position) {
  eCoords = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
  geocoder = new google.maps.Geocoder();
  geocoder.geocode({'latLng': eCoords}, function(results, status) {
    if (status == google.maps.GeocoderStatus.OK) {
      $('#finishbox').val(results[0].formatted_address).replace(/, CA, USA/g, "");;
    }
    $('.geolocationwaiting').fadeOut();
  });
}

function showGeoLocatorError(error){
  $('#geolocationwaiting').fadeOut();
  if(error.code==1){
    alert("To determine your current location you must click \"Share Location\" in the top bar in your browser.");
  } else if (error.code==2 || error.code==3 || error.code==0){
    alert("Your current location couldn't be determined.  Please enter the start and end locations manually.");
  }
}

function detectRouteFromURL(){
  //Detect saved route from URL
  if($.getUrlVar('start')!=undefined && $.getUrlVar('end')!=undefined){
    $('#startbox').val($.getUrlVar('start').replace(/\+/g,' '));
    $('#finishbox').val($.getUrlVar('end').replace(/\+/g,' '));
    // Strip off trailing #
    if($.getUrlVar('hill')!=undefined) {
     $('#hills').val($.getUrlVar('hill').replace(/#/g,''));
    }
    submitForm();
  }
}<|endoftext|>


<commit_before>/*
 * Laconica - a distributed open-source microblogging tool
 * Copyright (C) 2008, Controlez-Vous, Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

$(document).ready(function(){
	// count character on keyup
	function counter(event){
		var maxLength = 140;
		var currentLength = $("#status_textarea").val().length;
		var remaining = maxLength - currentLength;
		var counter = $("#counter");
		counter.text(remaining);

		if (remaining <= 0) {
			counter.addClass("toomuch");
		} else {
			counter.removeClass("toomuch");
		}
	}

	function submitonreturn(event) {
		if (event.keyCode == 13) {
			$("#status_form").submit();
			event.preventDefault();
			event.stopPropagation();
			return false;
		}
		return true;
	}

	if ($("#status_textarea").length) {
		$("#status_textarea").bind("keyup", counter);
		$("#status_textarea").bind("keydown", submitonreturn);

		// run once in case there's something in there
		counter();

		// set the focus
		$("#status_textarea").focus();
	}

	// XXX: refactor this code

	var favoptions = { dataType: 'xml',
					   success: function(xml) { var new_form = document._importNode($('form', xml).get(0), true);
												var dis = new_form.id;
												var fav = dis.replace('disfavor', 'favor');
												$('form#'+fav).replaceWith(new_form);
												$('form#'+dis).ajaxForm(disoptions).each(addAjaxHidden);
											  }
					 };

	var disoptions = { dataType: 'xml',
					   success: function(xml) { var new_form = document._importNode($('form', xml).get(0), true);
												var fav = new_form.id;
												var dis = fav.replace('favor', 'disfavor');
												$('form#'+dis).replaceWith(new_form);
												$('form#'+fav).ajaxForm(favoptions).each(addAjaxHidden);
											  }
					 };

	function addAjaxHidden() {
		var ajax = document.createElement('input');
		ajax.setAttribute('type', 'hidden');
		ajax.setAttribute('name', 'ajax');
		ajax.setAttribute('value', 1);
		this.appendChild(ajax);
	}

	$("form.favor").ajaxForm(favoptions);
	$("form.disfavor").ajaxForm(disoptions);
	$("form.favor").each(addAjaxHidden);
	$("form.disfavor").each(addAjaxHidden);

	$("#nudge").ajaxForm ({ dataType: 'xml',
							success: function(xml) { $("#nudge").replaceWith(document._importNode($("#nudge_response", xml).get(0),true)); }
						 });
	$("#nudge").each(addAjaxHidden);
	$("#nudge .submit").bind('click', function(e) {	$(this).addClass("processing"); });

	var Subscribe = { dataType: 'xml',
					  success: function(xml) { var form_unsubscribe = document._importNode($('form', xml).get(0), true);
										  	   var form_unsubscribe_id = form_unsubscribe.id;
											   var form_subscribe_id = form_unsubscribe_id.replace('unsubscribe', 'subscribe');
											   $("form#"+form_subscribe_id).replaceWith(form_unsubscribe);
											   $("form#"+form_unsubscribe_id).ajaxForm(UnSubscribe).each(addAjaxHidden);
											   $("#profile_actions").append(document._importNode($('#profile_send_a_new_message', xml).get(0), true));
											   $("#profile_actions").append(document._importNode($('#profile_nudge', xml).get(0), true));
										     }
					};

	var UnSubscribe = { dataType: 'xml',
					    success: function(xml) { var form_subscribe = document._importNode($('form', xml).get(0), true);
										  		 var form_subscribe_id = form_subscribe.id;
												 var form_unsubscribe_id = form_subscribe_id.replace('subscribe', 'unsubscribe');
												 $("form#"+form_unsubscribe_id).replaceWith(form_subscribe);
												 $("form#"+form_subscribe_id).ajaxForm(Subscribe).each(addAjaxHidden);
												 $("#profile_send_a_new_message").remove();
												 $("#profile_nudge").remove();
											   }
					  };

	$("form.subscribe").ajaxForm(Subscribe);
	$("form.unsubscribe").ajaxForm(UnSubscribe);
	$("form.subscribe").each(addAjaxHidden);
	$("form.unsubscribe").each(addAjaxHidden);
});

function doreply(nick,id) {
	rgx_username = /^[0-9a-zA-Z\-_.]*$/;
	if (nick.match(rgx_username)) {
		replyto = "@" + nick + " ";
		if ($("#status_textarea").length) {
			$("#status_textarea").val(replyto);
			$("form#status_form input#inreplyto").val(id);
			$("#status_textarea").focus();
			return false;
		}
	}
	return true;
}
<commit_msg>importNode bugfix for undefined node<commit_after>/*
 * Laconica - a distributed open-source microblogging tool
 * Copyright (C) 2008, Controlez-Vous, Inc.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

$(document).ready(function(){
	// count character on keyup
	function counter(event){
		var maxLength = 140;
		var currentLength = $("#status_textarea").val().length;
		var remaining = maxLength - currentLength;
		var counter = $("#counter");
		counter.text(remaining);

		if (remaining <= 0) {
			counter.addClass("toomuch");
		} else {
			counter.removeClass("toomuch");
		}
	}

	function submitonreturn(event) {
		if (event.keyCode == 13) {
			$("#status_form").submit();
			event.preventDefault();
			event.stopPropagation();
			return false;
		}
		return true;
	}

	if ($("#status_textarea").length) {
		$("#status_textarea").bind("keyup", counter);
		$("#status_textarea").bind("keydown", submitonreturn);

		// run once in case there's something in there
		counter();

		// set the focus
		$("#status_textarea").focus();
	}

	// XXX: refactor this code

	var favoptions = { dataType: 'xml',
					   success: function(xml) { var new_form = document._importNode($('form', xml).get(0), true);
												var dis = new_form.id;
												var fav = dis.replace('disfavor', 'favor');
												$('form#'+fav).replaceWith(new_form);
												$('form#'+dis).ajaxForm(disoptions).each(addAjaxHidden);
											  }
					 };

	var disoptions = { dataType: 'xml',
					   success: function(xml) { var new_form = document._importNode($('form', xml).get(0), true);
												var fav = new_form.id;
												var dis = fav.replace('favor', 'disfavor');
												$('form#'+dis).replaceWith(new_form);
												$('form#'+fav).ajaxForm(favoptions).each(addAjaxHidden);
											  }
					 };

	function addAjaxHidden() {
		var ajax = document.createElement('input');
		ajax.setAttribute('type', 'hidden');
		ajax.setAttribute('name', 'ajax');
		ajax.setAttribute('value', 1);
		this.appendChild(ajax);
	}

	$("form.favor").ajaxForm(favoptions);
	$("form.disfavor").ajaxForm(disoptions);
	$("form.favor").each(addAjaxHidden);
	$("form.disfavor").each(addAjaxHidden);

	$("#nudge").ajaxForm ({ dataType: 'xml',
							success: function(xml) { $("#nudge").replaceWith(document._importNode($("#nudge_response", xml).get(0),true)); }
						 });
	$("#nudge").each(addAjaxHidden);
	$("#nudge .submit").bind('click', function(e) {	$(this).addClass("processing"); });

	var Subscribe = { dataType: 'xml',
					  success: function(xml) { var form_unsubscribe = document._importNode($('form', xml).get(0), true);
										  	   var form_unsubscribe_id = form_unsubscribe.id;
											   var form_subscribe_id = form_unsubscribe_id.replace('unsubscribe', 'subscribe');
											   $("form#"+form_subscribe_id).replaceWith(form_unsubscribe);
											   $("form#"+form_unsubscribe_id).ajaxForm(UnSubscribe).each(addAjaxHidden);
											   var p_sanm = $('#profile_send_a_new_message', xml).get(0);
											   if (p_sanm) {
											   	$("#profile_actions").append(document._importNode(p_sanm, true));
											   }
											   var p_n = $('#profile_nudge', xml).get(0);
											   if (p_n) {
												   $("#profile_actions").append(document._importNode(p_n, true));
											   }
										     }
					};

	var UnSubscribe = { dataType: 'xml',
					    success: function(xml) { var form_subscribe = document._importNode($('form', xml).get(0), true);
										  		 var form_subscribe_id = form_subscribe.id;
												 var form_unsubscribe_id = form_subscribe_id.replace('subscribe', 'unsubscribe');
												 $("form#"+form_unsubscribe_id).replaceWith(form_subscribe);
												 $("form#"+form_subscribe_id).ajaxForm(Subscribe).each(addAjaxHidden);
												 $("#profile_send_a_new_message").remove();
												 $("#profile_nudge").remove();
											   }
					  };

	$("form.subscribe").ajaxForm(Subscribe);
	$("form.unsubscribe").ajaxForm(UnSubscribe);
	$("form.subscribe").each(addAjaxHidden);
	$("form.unsubscribe").each(addAjaxHidden);
});

function doreply(nick,id) {
	rgx_username = /^[0-9a-zA-Z\-_.]*$/;
	if (nick.match(rgx_username)) {
		replyto = "@" + nick + " ";
		if ($("#status_textarea").length) {
			$("#status_textarea").val(replyto);
			$("form#status_form input#inreplyto").val(id);
			$("#status_textarea").focus();
			return false;
		}
	}
	return true;
}
<|endoftext|>


<commit_before>/* global SolidUtils, TweeFiUtils, $rdf, GraphNode */

$(function () {
    function drawReview (review) {
        var reviewObject = {};
        reviewObject.tweet = review.out(SolidUtils.vocab.schema("itemReviewed")).value;
        reviewObject.claim = review.out(SolidUtils.vocab.schema("claimReviewed")).value;
        reviewObject.review = review.out(SolidUtils.vocab.schema("reviewBody")).value;
        reviewObject.rating = review.out(SolidUtils.vocab.schema("reviewRating")).out(SolidUtils.vocab.schema("ratingValue")).value;
        reviewObject.uri = review.value;
        //console.log(reviewObject);

        reviewObject.stars = "";
        for (var r = 0; r < reviewObject.rating; r++) {
            reviewObject.stars += '';
        }
        for (r; r < 5; r++) {
            reviewObject.stars += '';
        }

        return $.ajax({
            url: "https://publish.twitter.com/oembed?url=" + reviewObject.tweet,
            dataType: 'jsonp'
        }).then(
            function (tweet) {
                reviewObject.tweetBlockquote = tweet.html;

                return $.ajax("./template/view.html").then(function(template) {
                    //var template = document.getElementById('reviewTemplates').innerHTML;
                    var output = Mustache.render(template, reviewObject);
                    $("#tweets").append(output).fadeIn(2000);
                });
            });

    }

    TweeFiUtils.updateLoginInfo();
    SolidUtils.getStorageRootContainer().then(function (root) {
        var rootURI = root.value + "public/twee-fi/";
        var tweefiRoot = $rdf.sym(rootURI);
        return GraphNode(tweefiRoot).fetch().then(folder =>
        {
            return folder.out($rdf.sym("http://www.w3.org/ns/ldp#contains")).each(twitterUser =>
            {
                return twitterUser.fetch().then(twitterUser => {
                    return twitterUser.out($rdf.sym("http://www.w3.org/ns/ldp#contains")).each(tweet => {
                        return tweet.fetch().then(tweet => {
                            return tweet.out($rdf.sym("http://www.w3.org/ns/ldp#contains")).each(review => {
                                return review.fetch().then(review => {
                                    //console.log(twitterUser.value, tweet.value, review.value);
                                    return drawReview(review);
                                });
                            });
                        });
                    });
                });
                /*return SolidAuthClient.fetch(contained.value, {
                    method: 'delete'
                }).then(response => console.log(response));*/
            });
        });
    }).catch(function (error) {
        console.log("Couldn't get storage root: " + error);
    }).then(() => {
        console.log("adding event listner to "+$(".delete").length+" elements");
        $(".delete").click(e => {
            var review = $(e.target).closest(".review");
            var origBG = review.css("background-color");
            review.css( "background-color", "red" )
            setTimeout(() => {
                    if (confirm("Delete "+ e.target.value+"?")) {
                        return SolidAuthClient.fetch(e.target.value, {
                                method: 'delete'
                            }).then(response => {
                                console.log(response);
                                if (response.OK) {
                                    review.remove();
                                } else {
                                    alert(response.body);
                                }

                            });
                    } else {
                        review.css( "background-color", origBG)
                    }
                }, 1);
        });
    });

});
<commit_msg>removing review from view after deletion<commit_after>/* global SolidUtils, TweeFiUtils, $rdf, GraphNode */

$(function () {
    function drawReview (review) {
        var reviewObject = {};
        reviewObject.tweet = review.out(SolidUtils.vocab.schema("itemReviewed")).value;
        reviewObject.claim = review.out(SolidUtils.vocab.schema("claimReviewed")).value;
        reviewObject.review = review.out(SolidUtils.vocab.schema("reviewBody")).value;
        reviewObject.rating = review.out(SolidUtils.vocab.schema("reviewRating")).out(SolidUtils.vocab.schema("ratingValue")).value;
        reviewObject.uri = review.value;
        //console.log(reviewObject);

        reviewObject.stars = "";
        for (var r = 0; r < reviewObject.rating; r++) {
            reviewObject.stars += '';
        }
        for (r; r < 5; r++) {
            reviewObject.stars += '';
        }

        return $.ajax({
            url: "https://publish.twitter.com/oembed?url=" + reviewObject.tweet,
            dataType: 'jsonp'
        }).then(
            function (tweet) {
                reviewObject.tweetBlockquote = tweet.html;

                return $.ajax("./template/view.html").then(function(template) {
                    //var template = document.getElementById('reviewTemplates').innerHTML;
                    var output = Mustache.render(template, reviewObject);
                    $("#tweets").append(output).fadeIn(2000);
                });
            });

    }

    TweeFiUtils.updateLoginInfo();
    SolidUtils.getStorageRootContainer().then(function (root) {
        var rootURI = root.value + "public/twee-fi/";
        var tweefiRoot = $rdf.sym(rootURI);
        return GraphNode(tweefiRoot).fetch().then(folder =>
        {
            return folder.out($rdf.sym("http://www.w3.org/ns/ldp#contains")).each(twitterUser =>
            {
                return twitterUser.fetch().then(twitterUser => {
                    return twitterUser.out($rdf.sym("http://www.w3.org/ns/ldp#contains")).each(tweet => {
                        return tweet.fetch().then(tweet => {
                            return tweet.out($rdf.sym("http://www.w3.org/ns/ldp#contains")).each(review => {
                                return review.fetch().then(review => {
                                    //console.log(twitterUser.value, tweet.value, review.value);
                                    return drawReview(review);
                                });
                            });
                        });
                    });
                });
                /*return SolidAuthClient.fetch(contained.value, {
                    method: 'delete'
                }).then(response => console.log(response));*/
            });
        });
    }).catch(function (error) {
        console.log("Couldn't get storage root: " + error);
    }).then(() => {
        console.log("adding event listner to "+$(".delete").length+" elements");
        $(".delete").click(e => {
            var review = $(e.target).closest(".review");
            var origBG = review.css("background-color");
            review.css( "background-color", "red" )
            setTimeout(() => {
                    if (confirm("Delete "+ e.target.value+"?")) {
                        return SolidAuthClient.fetch(e.target.value, {
                                method: 'delete'
                            }).then(response => {
                                console.log(response);
                                if (response.ok) {
                                    review.remove();
                                } else {
                                    alert(response.body);
                                }

                            });
                    } else {
                        review.css( "background-color", origBG)
                    }
                }, 1);
        });
    });

});
<|endoftext|>


<commit_before>var assert = require('assert');

var unitNode = {}

unitNode.verbose = false;

var total = 0,
	fails = 0,
	passes = 0;

unitNode.describe = function(description, func) {
	console.log(description);
	func();
	console.log("Total: " + total + " tests. " + passes +
		" tests have passed and " +
		fails + " tests have failed.");
};

unitNode.it = function(description, func) {
	total += 1;
	try {
		func();
		console.log("\t* " + description + " - passed");
		passes += 1;

	} catch (err) {
		if (unitNode.verbose) {
			console.log(err);
		}
		console.log("\t* " + description + " - failed");
		fails += 1
	}
};

unitNode.assert = assert;

module.exports = unitNode;<commit_msg>adding color in messages<commit_after>var assert = require('assert');

var unitNode = {};

unitNode.verbose = false;

var total = 0,
	fails = 0,
	passes = 0;

unitNode.describe = function(description, func) {
	console.log(description);
	func();
	console.log("\x1b[0m", "Total: " + total + " tests. " + passes +
		" tests have passed and " +
		fails + " tests have failed.");
};

unitNode.it = function(description, func) {
	total += 1;
	try {
		func();
		console.log("\x1b[32m", "\t* " + description + " - passed");
		passes += 1;

	} catch (err) {
		if (unitNode.verbose) {
			console.log(err);
		}
		console.log("\x1b[31m", "\t* " + description + " - failed");
		fails += 1
	}
};

unitNode.assert = assert;

module.exports = unitNode;<|endoftext|>


<commit_before>// For University Theme Color
function getColorByUnivName(univ) {
  if (univ == "UCB" || univ.toLowerCase().replace(/\s+/g, '').includes("berkeley")) return "#fdb515";
  if (univ == "KYU" || univ.includes("가야대")) return "#114fa1";
  if (univ == "GCHU" || univ.includes("가천대")) return "#00458c";
  if (univ == "CUK" || univ.includes("가톨릭대")) return "#003594";
  if (univ == "CKU" || univ.includes("가톨릭관동대")) return "#006276";
  if (univ == "MTU" || univ.includes("감리교신학대")) return "#800080";
  if (univ == "KANGNAM" || univ.includes("강남대")) return "#0091FF";
  if (univ == "GWNU" || univ.includes("강릉원주대")) return "#a90056";
  if (univ == "KNU" || univ.includes("강원대")) return "#1851a5";
  if (univ == "KU" || univ.includes("건국대") || univ == "건대") return "#036b3f";
  if (univ == "KONYANG" || univ.includes("건양대")) return "#006940";
  if (univ == "KGU" || univ.includes("경기대")) return "#004889";
  if (univ == "GNTECH" || univ.includes("경남과학기술대")) return "#2956a6";
  if (univ == "KYUNGNAM" || univ.includes("경남대")) return "#003A56";
  if (univ == "KDU" || univ.includes("경동대")) return "#0C4DA2";
  if (univ == "KPNU" || univ.includes("경북대")) return "#da2127";
  if (univ == "GNU" || univ.includes("경상대")) return "#242b90";
  if (univ == "KS" || univ.includes("경성대")) return "#0057b8";
  if (univ == "IKW" || univ.includes("경운대")) return "#23438e";
  if (univ == "KIU" || univ.includes("경일대")) return "#98012e";
  if (univ == "GJU" || univ.includes("경주대")) return "#df0013";
  if (univ == "KHU" || univ.includes("경희대")) return "#9d2235";
  if (univ == "KEIMYUNG" || univ.includes("계명대")) return "#024da0";
  if (univ == "KMCU" || univ.includes("계명문화대")) return "#eb2d2f";
  if (univ == "KRU" || univ.includes("고려대") || univ == "고대") return "#862633";
  if (univ == "KOSIN" || univ.includes("고신대")) return "#003f91";
  if (univ == "KJNU" || univ.includes("공주대")) return "#01499a";
  if (univ == "KSU" || univ.includes("광신대")) return "#1d2881";
  if (univ == "KWU" || univ.includes("광운대")) return "#8a1601";
  if (univ == "GWJCU" || univ.includes("광주가톨릭대")) return "#ed1c24";
  if (univ == "GWJU" || univ.includes("광주대")) return "#144112";
  if (univ == "GWJWU" || univ.includes("광주여자대")) return "#008b9c";
  if (univ == "KMU" || univ.includes("국민대")) return "#2864ae";
  if (univ == "KSNU" || univ.includes("군산대")) return "#437fc1";
  if (univ == "FEU" || univ.includes("극동대")) return "#221f1f";
  if (univ == "GGU" || univ.includes("금강대")) return "#005aab";
  if (univ == "KIT" || univ.includes("금오공과대") || univ == "금오공대") return "#1e90ff";
  if (univ == "GCU" || univ.includes("김천대")) return "#57444e";
  if (univ == "KKOT" || univ.includes("꽃동네대")) return "#cf171f";

  if (univ == "NAZARENE" || univ.includes("나사렛대")) return "#b32f20";
  if (univ == "NBU" || univ.includes("남부대")) return "#13007d";
  if (univ == "NSU" || univ.includes("남서울대")) return "#1f519b";

  if (univ == "DKU" || univ.includes("단국대")) return "#245ca1";
  if (univ == "CU" || univ.includes("대구가톨릭대")) return "#0742a4";
  if (univ == "DAEGU" || univ.includes("대구대")) return "#00806e";
  if (univ == "DGAU" || univ.includes("대구예술대")) return "#df569e";
  if (univ == "DHU" || univ.includes("대구한의대")) return "#50ad95";
  if (univ == "DSU" || univ.includes("대신대")) return "#3680bd";
  if (univ == "DCU" || univ.includes("대전가톨릭대")) return "#7a42a0";
  if (univ == "DJU" || univ.includes("대전대")) return "#347c4d";
  if (univ == "DTU" || univ.includes("대전신학대")) return "#2d70b5";
  if (univ == "DJNU" || univ.includes("대진대")) return "#184490";
  if (univ == "DSWU" || univ.includes("덕성여자대") || univ.includes("덕성여대")) return "#ac145a";
  if (univ == "DGU" || univ.includes("동국대")) return "#cb6015";
  if (univ == "DDWU" || univ.includes("동덕여자대") || univ.includes("동덕여대")) return "#8b2842";
  if (univ == "TU" || univ.includes("동명대")) return "#53aa48";
  if (univ == "DSU" || univ.includes("동서대")) return "#d43645";
  if (univ == "DSNU" || univ.includes("동신대")) return "#255ea9";
  if (univ == "DAU" || univ.includes("동아대")) return "#29166f";
  if (univ == "DYU" || univ.includes("동양대")) return "#143b82";
  if (univ == "DEU" || univ.includes("동의대")) return "#0b3d91";

  if (univ == "LTU" || univ.includes("루터대")) return "#2457a6";

  if (univ == "MJU" || univ.includes("명지대")) return "#10336c";
  if (univ == "MWU" || univ.includes("목원대")) return "#8b0000";
  if (univ == "MCU" || univ.includes("목포가톨릭대")) return "#353a97";
  if (univ == "MPNU" || univ.includes("목포대")) return "#20b2aa";
  if (univ == "MPNMU" || univ.includes("목포해양대")) return "#1f5a92";

  if (univ == "PCU" || univ.includes("배재대")) return "#071d8e";
  if (univ == "BU" || univ.includes("백석대")) return "#12319b";
  if (univ == "PKNU" || univ.includes("부경대")) return "#13007c";
  if (univ == "CUP" || univ.includes("부산가톨릭대")) return "#9a2183";
  if (univ == "PNU" || univ.includes("부산대") || univ == "부대") return "#005baa";
  if (univ == "BUFS" || univ.includes("부산외국어대") || univ == "부산외대") return "#ffd000";
  if (univ == "BPU" || univ.includes("부산장신대")) return "#2d6fa8";

  if (univ == "SYU" || univ.includes("삼육대")) return "#5389c6";
  if (univ == "SMU" || univ.includes("상명대")) return "#1f519b";
  if (univ == "SGU" || univ.includes("서강대")) return "#B0232A";
  if (univ == "SKU" || univ.includes("서경대")) return "#71bf44";
  if (univ == "SNU" || univ.includes("서울대")) return "#20408e";
  if (univ == "SeoulTech" || univ.includes("서울과학기술대") || univ == "서울과기대") return "#00205b";
  if (univ == "UOS" || univ.includes("서울시립대")) return "#151f6d";
  if (univ == "SKHU" || univ.includes("성공회대")) return "#006BB1";
  if (univ == "SKKU" || univ.includes("성균관대")) return "#8DC63F";
  if (univ == "SJU" || univ.includes("세종대")) return "#ba0c2f";
  if (univ == "SSU" || univ.includes("숭실대")) return "#4badcd";
  if (univ == "SWC" || univ.includes("숭의여대")) return "#062d8f";

  if (univ == "AJU" || univ.includes("아주대")) return "#0072ce";
  if (univ == "YSU" || univ.includes("연세대")) return "#16407d";
  if (univ == "YU" || univ.includes("영남대")) return "#003e7d";
  if (univ == "JNU" || univ.includes("전남대")) return "#00913F";
  if (univ == "JBNU" || univ.includes("전북대")) return "#56296f";
  if (univ == "JJU" || univ.includes("전주대")) return "#006ba6";
  if (univ == "CAU" || univ.includes("중앙대")) return "#004c97";

  if (univ == "CNU" || univ.includes("충남대")) return "#003f98";
  if (univ == "CBNU" ||univ.includes("충북대")) return "#9B1F4E";

  if (univ == "KAIST" || univ.includes("카이스트")) return "#004191";

  if (univ == "PTU" || univ.includes("평택대")) return "#003e15";

  if (univ == "HUFS" || univ.includes("한국외국어대")) return "#00677F";
  if (univ == "KAU" || univ.includes("한국항공대")) return "#302475";
  if (univ == "HGU" || univ.includes("한동대")) return "#13eac9";
  if (univ == "HSU" || univ.includes("한성대")) return "#62b5e5";
  if (univ == "HYU" || univ.includes("한양대")) return "#003c71";
  if (univ == "HOSEO" || univ.includes("호서대")) return "#08449a";
  if (univ == "HIU" || univ.includes("홍익대")) return "#002c62";

  return "Not Found";
}
<commit_msg>Add Adelphi Univerisity<commit_after>// For University Theme Color
function getColorByUnivName(univ) {
  if (univ == "AU" || univ.includes("Adelphi University")) return "#FDB813";
  if (univ == "UCB" || univ.toLowerCase().replace(/\s+/g, '').includes("berkeley")) return "#fdb515";
  if (univ == "KYU" || univ.includes("가야대")) return "#114fa1";
  if (univ == "GCHU" || univ.includes("가천대")) return "#00458c";
  if (univ == "CUK" || univ.includes("가톨릭대")) return "#003594";
  if (univ == "CKU" || univ.includes("가톨릭관동대")) return "#006276";
  if (univ == "MTU" || univ.includes("감리교신학대")) return "#800080";
  if (univ == "KANGNAM" || univ.includes("강남대")) return "#0091FF";
  if (univ == "GWNU" || univ.includes("강릉원주대")) return "#a90056";
  if (univ == "KNU" || univ.includes("강원대")) return "#1851a5";
  if (univ == "KU" || univ.includes("건국대") || univ == "건대") return "#036b3f";
  if (univ == "KONYANG" || univ.includes("건양대")) return "#006940";
  if (univ == "KGU" || univ.includes("경기대")) return "#004889";
  if (univ == "GNTECH" || univ.includes("경남과학기술대")) return "#2956a6";
  if (univ == "KYUNGNAM" || univ.includes("경남대")) return "#003A56";
  if (univ == "KDU" || univ.includes("경동대")) return "#0C4DA2";
  if (univ == "KPNU" || univ.includes("경북대")) return "#da2127";
  if (univ == "GNU" || univ.includes("경상대")) return "#242b90";
  if (univ == "KS" || univ.includes("경성대")) return "#0057b8";
  if (univ == "IKW" || univ.includes("경운대")) return "#23438e";
  if (univ == "KIU" || univ.includes("경일대")) return "#98012e";
  if (univ == "GJU" || univ.includes("경주대")) return "#df0013";
  if (univ == "KHU" || univ.includes("경희대")) return "#9d2235";
  if (univ == "KEIMYUNG" || univ.includes("계명대")) return "#024da0";
  if (univ == "KMCU" || univ.includes("계명문화대")) return "#eb2d2f";
  if (univ == "KRU" || univ.includes("고려대") || univ == "고대") return "#862633";
  if (univ == "KOSIN" || univ.includes("고신대")) return "#003f91";
  if (univ == "KJNU" || univ.includes("공주대")) return "#01499a";
  if (univ == "KSU" || univ.includes("광신대")) return "#1d2881";
  if (univ == "KWU" || univ.includes("광운대")) return "#8a1601";
  if (univ == "GWJCU" || univ.includes("광주가톨릭대")) return "#ed1c24";
  if (univ == "GWJU" || univ.includes("광주대")) return "#144112";
  if (univ == "GWJWU" || univ.includes("광주여자대")) return "#008b9c";
  if (univ == "KMU" || univ.includes("국민대")) return "#2864ae";
  if (univ == "KSNU" || univ.includes("군산대")) return "#437fc1";
  if (univ == "FEU" || univ.includes("극동대")) return "#221f1f";
  if (univ == "GGU" || univ.includes("금강대")) return "#005aab";
  if (univ == "KIT" || univ.includes("금오공과대") || univ == "금오공대") return "#1e90ff";
  if (univ == "GCU" || univ.includes("김천대")) return "#57444e";
  if (univ == "KKOT" || univ.includes("꽃동네대")) return "#cf171f";

  if (univ == "NAZARENE" || univ.includes("나사렛대")) return "#b32f20";
  if (univ == "NBU" || univ.includes("남부대")) return "#13007d";
  if (univ == "NSU" || univ.includes("남서울대")) return "#1f519b";

  if (univ == "DKU" || univ.includes("단국대")) return "#245ca1";
  if (univ == "CU" || univ.includes("대구가톨릭대")) return "#0742a4";
  if (univ == "DAEGU" || univ.includes("대구대")) return "#00806e";
  if (univ == "DGAU" || univ.includes("대구예술대")) return "#df569e";
  if (univ == "DHU" || univ.includes("대구한의대")) return "#50ad95";
  if (univ == "DSU" || univ.includes("대신대")) return "#3680bd";
  if (univ == "DCU" || univ.includes("대전가톨릭대")) return "#7a42a0";
  if (univ == "DJU" || univ.includes("대전대")) return "#347c4d";
  if (univ == "DTU" || univ.includes("대전신학대")) return "#2d70b5";
  if (univ == "DJNU" || univ.includes("대진대")) return "#184490";
  if (univ == "DSWU" || univ.includes("덕성여자대") || univ.includes("덕성여대")) return "#ac145a";
  if (univ == "DGU" || univ.includes("동국대")) return "#cb6015";
  if (univ == "DDWU" || univ.includes("동덕여자대") || univ.includes("동덕여대")) return "#8b2842";
  if (univ == "TU" || univ.includes("동명대")) return "#53aa48";
  if (univ == "DSU" || univ.includes("동서대")) return "#d43645";
  if (univ == "DSNU" || univ.includes("동신대")) return "#255ea9";
  if (univ == "DAU" || univ.includes("동아대")) return "#29166f";
  if (univ == "DYU" || univ.includes("동양대")) return "#143b82";
  if (univ == "DEU" || univ.includes("동의대")) return "#0b3d91";

  if (univ == "LTU" || univ.includes("루터대")) return "#2457a6";

  if (univ == "MJU" || univ.includes("명지대")) return "#10336c";
  if (univ == "MWU" || univ.includes("목원대")) return "#8b0000";
  if (univ == "MCU" || univ.includes("목포가톨릭대")) return "#353a97";
  if (univ == "MPNU" || univ.includes("목포대")) return "#20b2aa";
  if (univ == "MPNMU" || univ.includes("목포해양대")) return "#1f5a92";

  if (univ == "PCU" || univ.includes("배재대")) return "#071d8e";
  if (univ == "BU" || univ.includes("백석대")) return "#12319b";
  if (univ == "PKNU" || univ.includes("부경대")) return "#13007c";
  if (univ == "CUP" || univ.includes("부산가톨릭대")) return "#9a2183";
  if (univ == "PNU" || univ.includes("부산대") || univ == "부대") return "#005baa";
  if (univ == "BUFS" || univ.includes("부산외국어대") || univ == "부산외대") return "#ffd000";
  if (univ == "BPU" || univ.includes("부산장신대")) return "#2d6fa8";

  if (univ == "SYU" || univ.includes("삼육대")) return "#5389c6";
  if (univ == "SMU" || univ.includes("상명대")) return "#1f519b";
  if (univ == "SGU" || univ.includes("서강대")) return "#B0232A";
  if (univ == "SKU" || univ.includes("서경대")) return "#71bf44";
  if (univ == "SNU" || univ.includes("서울대")) return "#20408e";
  if (univ == "SeoulTech" || univ.includes("서울과학기술대") || univ == "서울과기대") return "#00205b";
  if (univ == "UOS" || univ.includes("서울시립대")) return "#151f6d";
  if (univ == "SKHU" || univ.includes("성공회대")) return "#006BB1";
  if (univ == "SKKU" || univ.includes("성균관대")) return "#8DC63F";
  if (univ == "SJU" || univ.includes("세종대")) return "#ba0c2f";
  if (univ == "SSU" || univ.includes("숭실대")) return "#4badcd";
  if (univ == "SWC" || univ.includes("숭의여대")) return "#062d8f";

  if (univ == "AJU" || univ.includes("아주대")) return "#0072ce";
  if (univ == "YSU" || univ.includes("연세대")) return "#16407d";
  if (univ == "YU" || univ.includes("영남대")) return "#003e7d";
  if (univ == "JNU" || univ.includes("전남대")) return "#00913F";
  if (univ == "JBNU" || univ.includes("전북대")) return "#56296f";
  if (univ == "JJU" || univ.includes("전주대")) return "#006ba6";
  if (univ == "CAU" || univ.includes("중앙대")) return "#004c97";

  if (univ == "CNU" || univ.includes("충남대")) return "#003f98";
  if (univ == "CBNU" ||univ.includes("충북대")) return "#9B1F4E";

  if (univ == "KAIST" || univ.includes("카이스트")) return "#004191";

  if (univ == "PTU" || univ.includes("평택대")) return "#003e15";

  if (univ == "HUFS" || univ.includes("한국외국어대")) return "#00677F";
  if (univ == "KAU" || univ.includes("한국항공대")) return "#302475";
  if (univ == "HGU" || univ.includes("한동대")) return "#13eac9";
  if (univ == "HSU" || univ.includes("한성대")) return "#62b5e5";
  if (univ == "HYU" || univ.includes("한양대")) return "#003c71";
  if (univ == "HOSEO" || univ.includes("호서대")) return "#08449a";
  if (univ == "HIU" || univ.includes("홍익대")) return "#002c62";

  return "Not Found";
}
<|endoftext|>


<commit_before>(function() {

function getMaxZoomLevel(config) {
	var w = config.w;
	var h = config.h;
	var max = 0;
	while (true) {
		if ((w <= config.tw) && (h <= config.th)) {
			break;
		}
		w = Math.ceil(w/2);
		h = Math.ceil(h/2);
		max++;
	}
	return max;
}

function setupEventHandler(kasuari) {
	kasuari.canvas.mousedown(function(e) {
		kasuari.mousedown(e);
	});
	kasuari.canvas.mousemove(function(e) {
		kasuari.mousemove(e);
	});
	kasuari.canvas.mouseup(function(e) {
		kasuari.mouseup(e);
	});
	kasuari.canvas.dblclick(function(e) {
		kasuari.zoom(e.clientX, e.clientY, 1.5);
	});
	kasuari.canvas.mousewheel(function(e, d) {
		if (d > 0) {
			kasuari.zoom(e.clientX, e.clientY, 1.5);
		}
		else {
			kasuari.zoom(e.clientX, e.clientY, 2/3.0);
		}
		return false;
	});
}

var KasuariImage = function(url, kasuari) {
	this.kasuari = kasuari;
	var self = this;
	this.loaded = false;
	this.url = url;
	this.img = new Image();
	this.img.onload = function() {
		self.loaded = true;
		updateImageGeometry(self.kasuari);
		drawCanvas(self.kasuari);
	}
}

KasuariImage.prototype = {
	init: function() {
		this.img.src = this.url;
	},

	draw: function() {
		if (!this.loaded) { return; }
		var ctx = this.kasuari.ctx;
		ctx.save();
		ctx.translate(this.x, this.y);
		ctx.drawImage(this.img, 0, 0, this.w, this.h);
		ctx.restore();
	},
};

function addImage(kasuari, zoomLevel, ix, iy) {
	var url = kasuari.config.imgdir + '/img-z' + zoomLevel + '.x' + ix + '.y' + iy + kasuari.config.ext;
	var img = new KasuariImage(url, kasuari);

	var scale = kasuari.scale;
	var w = Math.ceil(kasuari.tw * scale);
	var h = Math.ceil(kasuari.th * scale);

	img.id = zoomLevel+'-'+ix+'-'+iy;
	img.ix = ix;
	img.iy = iy;

	kasuari.images.push(img);

	img.init();
}

function updateImages(kasuari) {
	var x0 = -kasuari.px;
	var y0 = -kasuari.py;
	var x1 = x0 + kasuari.cw;
	var y1 = y0 + kasuari.ch;

	var ix0 = Math.floor(x0/(kasuari.tw*kasuari.scale))-1;
	var iy0 = Math.floor(y0/(kasuari.th*kasuari.scale))-1;
	var ix1 = Math.ceil(kasuari.cw/(kasuari.tw*kasuari.scale))+2 + ix0;
	var iy1 = Math.ceil(kasuari.ch/(kasuari.th*kasuari.scale))+2 + iy0;

	var add = {};
	var del = [];

	var x, y;
	for (y=iy0; y<iy1; y++) {
		for (x=ix0; x<ix1; x++) {
			if ((x < 0) || (y < 0)) { continue; }
			var ix = Math.floor(x * kasuari.step * kasuari.tw);
			var iy = Math.floor(y * kasuari.step * kasuari.th);
			if ((ix > kasuari.iw) || (iy > kasuari.ih)) { continue; }

			add[kasuari.zoomLevel+'-'+x+'-'+y] = [ x, y ];
		}
	}

	var images = [];

	var i, size = kasuari.images.length;
	for (i=0; i<size; i++) {
		var o = kasuari.images[i];
		if (add[o.id] != undefined) {
			images.push(o);
			delete add[o.id];
		}

	};

	kasuari.images = images;

	for (var k in add) {
		var d = add[k];
		addImage(kasuari, kasuari.zoomLevel, d[0], d[1]);
	}
}

function updateImageGeometry(kasuari) {
	var w = Math.ceil(kasuari.tw * kasuari.scale);
	var h = Math.ceil(kasuari.th * kasuari.scale);
	var i, size = kasuari.images.length;
	for (i=0; i<size; i++) {
		var img = kasuari.images[i];
		img.x = img.ix * w;
		img.y = img.iy * h;
		img.w = Math.ceil(img.img.width * kasuari.scale);
		img.h = Math.ceil(img.img.height * kasuari.scale);
	}
}

function drawCanvas(kasuari) {
	var ctx = kasuari.ctx;
	ctx.clearRect(0, 0, kasuari.cw, kasuari.ch);
	ctx.save();
	ctx.translate(kasuari.px, kasuari.py);

	var i, size = kasuari.images.length;
	for (i=0; i<size; i++) {
		var img = kasuari.images[i];
		img.draw();
	}

	ctx.restore();
}

function smoothMove(kasuari) {
	var dx = kasuari.drag.x + kasuari.drag.dx - kasuari.px;
	var dy = kasuari.drag.y + kasuari.drag.dy - kasuari.py;
	dx = Math.ceil(dx * 0.2);
	dy = Math.ceil(dy * 0.2);
	kasuari.px += dx;
	kasuari.py += dy;

	updateImages(kasuari);
	drawCanvas(kasuari);

	if ((dx != 0) || (dy != 0)) {
		kasuari.timer = setTimeout(function() {
			smoothMove(kasuari)
		}, 20);
	}
	else {
		clearTimeout(kasuari.timer);
		kasuari.timer = undefined;
	}
}

var Kasuari = function(canvas, config) {
	// default configuration
	this.config = {
		tw: 256,
		th: 256,
		x: 0,
		y: 0,
		zoomLevel: -1,
		zoomStep: 2,
		ext: '.jpg'
	}

	// override configuration
	for (var k in config) {
		this.config[k] = config[k];
	}

	this.canvas = canvas;
	this.ctx = this.canvas.get(0).getContext('2d');

	this.maxZoomLevel = getMaxZoomLevel(this.config);

	if (this.config.zoomLevel == -1) { this.zoomLevel = this.maxZoomLevel; }
	else { this.zoomLevel = this.config.zoomLevel; }

	this.tw = this.config.tw;
	this.th = this.config.th;
	this.iw = this.config.w;
	this.ih = this.config.h;
	this.zoomStep = this.config.zoomStep;

	this.cw = this.canvas.width();
	this.ch = this.canvas.height();
	canvas.get(0).width = this.cw;
	canvas.get(0).height = this.ch;

	this.step = Math.pow(this.zoomStep, this.zoomLevel);
	this.scale = 1;
	this.zoomInLimit = 1.25;
	this.zoomOutLimit = 1.0/this.zoomStep;
	this.timer = undefined;

	this.px = Math.ceil(this.config.x / this.step);
	this.py = Math.ceil(this.config.y / this.step);

	this.drag = {
		enabled: false,
		x: 0,
		y: 0
	};

	this.images = [];

	this.timer = undefined;
};

Kasuari.prototype = {
	start: function() {
		setupEventHandler(this);
		this.updateCanvas();
	},

	updateCanvas: function() {
		updateImages(this);
		updateImageGeometry(this);
		drawCanvas(this);
	},

	mousedown: function(e) {
		this.drag.x = e.clientX;
		this.drag.y = e.clientY;
		this.drag.dx = this.px - this.drag.x;
		this.drag.dy = this.py - this.drag.y;
		this.drag.enabled = true;
	},

	mousemove: function(e) {
		if (this.drag.enabled) {
			this.drag.x0 = this.drag.x;
			this.drag.y0 = this.drag.y;
			this.drag.x = e.clientX;
			this.drag.y = e.clientY;

			if (!this.timer) {
				var self = this;
				this.timer = setTimeout(function() {
					smoothMove(self);
				}, 20);
			}

		}
	},

	mouseup: function(e) {
		var dx = this.drag.x - this.drag.x0;
		var dy = this.drag.y - this.drag.y0;
		if (Math.abs(dx) >= 5) { if (dx > 30) { dx = 30; }; this.drag.x += dx * 10; }
		if (Math.abs(dy) >= 5) { if (dy > 30) { dy = 30; }; this.drag.y += dy * 10; }
		this.drag.enabled = false;
	},

	zoom: function(x, y, zoom) {
		clearTimeout(this.timer);
		this.timer = undefined;

		var zoomLevel = this.zoomLevel;
		var scale = this.scale * zoom;
		if ((zoomLevel > 0) && (scale > this.zoomInLimit)) {
			while (scale > this.zoomInLimit) {
				zoomLevel--;
				scale = scale / this.zoomStep;
			}
			if (zoomLevel < 0) {
				zoomLevel = 0;
			}
		}
		else if ((zoomLevel < this.maxZoomLevel) && (scale < this.zoomOutLimit)) {
			while (scale < this.zoomOutLimit) {
				zoomLevel++;
				scale = scale * this.zoomStep;
			}
			if (zoomLevel > this.maxZoomLevel) {
				zoomLevel = this.maxZoomLevel;
			}
		}

		this.scale = scale;

		if (zoomLevel != this.zoomLevel) {
			this.zoomLevel = zoomLevel;
			this.step = Math.pow(this.zoomStep, this.zoomLevel);
		}

		this.px = Math.floor(x - (x - this.px) * zoom);
		this.py = Math.floor(y - (y - this.py) * zoom);
		this.updateCanvas();
	}
};

this.Kasuari = Kasuari;

})();
<commit_msg>Store Kasuari object in the canvas jquery object<commit_after>(function() {

function getMaxZoomLevel(config) {
	var w = config.w;
	var h = config.h;
	var max = 0;
	while (true) {
		if ((w <= config.tw) && (h <= config.th)) {
			break;
		}
		w = Math.ceil(w/2);
		h = Math.ceil(h/2);
		max++;
	}
	return max;
}

function setupEventHandler(kasuari) {
	kasuari.canvas.mousedown(function(e) {
		kasuari.mousedown(e);
	});
	kasuari.canvas.mousemove(function(e) {
		kasuari.mousemove(e);
	});
	kasuari.canvas.mouseup(function(e) {
		kasuari.mouseup(e);
	});
	kasuari.canvas.dblclick(function(e) {
		kasuari.zoom(e.clientX, e.clientY, 1.5);
	});
	kasuari.canvas.mousewheel(function(e, d) {
		if (d > 0) {
			kasuari.zoom(e.clientX, e.clientY, 1.5);
		}
		else {
			kasuari.zoom(e.clientX, e.clientY, 2/3.0);
		}
		return false;
	});
}

var KasuariImage = function(url, kasuari) {
	this.kasuari = kasuari;
	var self = this;
	this.loaded = false;
	this.url = url;
	this.img = new Image();
	this.img.onload = function() {
		self.loaded = true;
		updateImageGeometry(self.kasuari);
		drawCanvas(self.kasuari);
	}
}

KasuariImage.prototype = {
	init: function() {
		this.img.src = this.url;
	},

	draw: function() {
		if (!this.loaded) { return; }
		var ctx = this.kasuari.ctx;
		ctx.save();
		ctx.translate(this.x, this.y);
		ctx.drawImage(this.img, 0, 0, this.w, this.h);
		ctx.restore();
	},
};

function addImage(kasuari, zoomLevel, ix, iy) {
	var url = kasuari.config.imgdir + '/img-z' + zoomLevel + '.x' + ix + '.y' + iy + kasuari.config.ext;
	var img = new KasuariImage(url, kasuari);

	var scale = kasuari.scale;
	var w = Math.ceil(kasuari.tw * scale);
	var h = Math.ceil(kasuari.th * scale);

	img.id = zoomLevel+'-'+ix+'-'+iy;
	img.ix = ix;
	img.iy = iy;

	kasuari.images.push(img);

	img.init();
}

function updateImages(kasuari) {
	var x0 = -kasuari.px;
	var y0 = -kasuari.py;
	var x1 = x0 + kasuari.cw;
	var y1 = y0 + kasuari.ch;

	var ix0 = Math.floor(x0/(kasuari.tw*kasuari.scale))-1;
	var iy0 = Math.floor(y0/(kasuari.th*kasuari.scale))-1;
	var ix1 = Math.ceil(kasuari.cw/(kasuari.tw*kasuari.scale))+2 + ix0;
	var iy1 = Math.ceil(kasuari.ch/(kasuari.th*kasuari.scale))+2 + iy0;

	var add = {};
	var del = [];

	var x, y;
	for (y=iy0; y<iy1; y++) {
		for (x=ix0; x<ix1; x++) {
			if ((x < 0) || (y < 0)) { continue; }
			var ix = Math.floor(x * kasuari.step * kasuari.tw);
			var iy = Math.floor(y * kasuari.step * kasuari.th);
			if ((ix > kasuari.iw) || (iy > kasuari.ih)) { continue; }

			add[kasuari.zoomLevel+'-'+x+'-'+y] = [ x, y ];
		}
	}

	var images = [];

	var i, size = kasuari.images.length;
	for (i=0; i<size; i++) {
		var o = kasuari.images[i];
		if (add[o.id] != undefined) {
			images.push(o);
			delete add[o.id];
		}

	};

	kasuari.images = images;

	for (var k in add) {
		var d = add[k];
		addImage(kasuari, kasuari.zoomLevel, d[0], d[1]);
	}
}

function updateImageGeometry(kasuari) {
	var w = Math.ceil(kasuari.tw * kasuari.scale);
	var h = Math.ceil(kasuari.th * kasuari.scale);
	var i, size = kasuari.images.length;
	for (i=0; i<size; i++) {
		var img = kasuari.images[i];
		img.x = img.ix * w;
		img.y = img.iy * h;
		img.w = Math.ceil(img.img.width * kasuari.scale);
		img.h = Math.ceil(img.img.height * kasuari.scale);
	}
}

function drawCanvas(kasuari) {
	var ctx = kasuari.ctx;
	ctx.clearRect(0, 0, kasuari.cw, kasuari.ch);
	ctx.save();
	ctx.translate(kasuari.px, kasuari.py);

	var i, size = kasuari.images.length;
	for (i=0; i<size; i++) {
		var img = kasuari.images[i];
		img.draw();
	}

	ctx.restore();
}

function smoothMove(kasuari) {
	var dx = kasuari.drag.x + kasuari.drag.dx - kasuari.px;
	var dy = kasuari.drag.y + kasuari.drag.dy - kasuari.py;
	dx = Math.ceil(dx * 0.2);
	dy = Math.ceil(dy * 0.2);
	kasuari.px += dx;
	kasuari.py += dy;

	updateImages(kasuari);
	drawCanvas(kasuari);

	if ((dx != 0) || (dy != 0)) {
		kasuari.timer = setTimeout(function() {
			smoothMove(kasuari)
		}, 20);
	}
	else {
		clearTimeout(kasuari.timer);
		kasuari.timer = undefined;
	}
}

var Kasuari = function(canvas, config) {
	// default configuration
	this.config = {
		tw: 256,
		th: 256,
		x: 0,
		y: 0,
		zoomLevel: -1,
		zoomStep: 2,
		ext: '.jpg'
	}

	// override configuration
	for (var k in config) {
		this.config[k] = config[k];
	}

	this.canvas = canvas;
	this.ctx = this.canvas.get(0).getContext('2d');

	this.canvas.data('kasuari', this);

	this.maxZoomLevel = getMaxZoomLevel(this.config);

	if (this.config.zoomLevel == -1) { this.zoomLevel = this.maxZoomLevel; }
	else { this.zoomLevel = this.config.zoomLevel; }

	this.tw = this.config.tw;
	this.th = this.config.th;
	this.iw = this.config.w;
	this.ih = this.config.h;
	this.zoomStep = this.config.zoomStep;

	this.cw = this.canvas.width();
	this.ch = this.canvas.height();
	canvas.get(0).width = this.cw;
	canvas.get(0).height = this.ch;

	this.step = Math.pow(this.zoomStep, this.zoomLevel);
	this.scale = 1;
	this.zoomInLimit = 1.25;
	this.zoomOutLimit = 1.0/this.zoomStep;
	this.timer = undefined;

	this.px = Math.ceil(this.config.x / this.step);
	this.py = Math.ceil(this.config.y / this.step);

	this.drag = {
		enabled: false,
		x: 0,
		y: 0
	};

	this.images = [];

	this.timer = undefined;
};

Kasuari.prototype = {
	start: function() {
		setupEventHandler(this);
		this.updateCanvas();
	},

	updateCanvas: function() {
		updateImages(this);
		updateImageGeometry(this);
		drawCanvas(this);
	},

	mousedown: function(e) {
		this.drag.x = e.clientX;
		this.drag.y = e.clientY;
		this.drag.dx = this.px - this.drag.x;
		this.drag.dy = this.py - this.drag.y;
		this.drag.enabled = true;
	},

	mousemove: function(e) {
		if (this.drag.enabled) {
			this.drag.x0 = this.drag.x;
			this.drag.y0 = this.drag.y;
			this.drag.x = e.clientX;
			this.drag.y = e.clientY;

			if (!this.timer) {
				var self = this;
				this.timer = setTimeout(function() {
					smoothMove(self);
				}, 20);
			}

		}
	},

	mouseup: function(e) {
		var dx = this.drag.x - this.drag.x0;
		var dy = this.drag.y - this.drag.y0;
		if (Math.abs(dx) >= 5) { if (dx > 30) { dx = 30; }; this.drag.x += dx * 10; }
		if (Math.abs(dy) >= 5) { if (dy > 30) { dy = 30; }; this.drag.y += dy * 10; }
		this.drag.enabled = false;
	},

	zoom: function(x, y, zoom) {
		clearTimeout(this.timer);
		this.timer = undefined;

		var zoomLevel = this.zoomLevel;
		var scale = this.scale * zoom;
		if ((zoomLevel > 0) && (scale > this.zoomInLimit)) {
			while (scale > this.zoomInLimit) {
				zoomLevel--;
				scale = scale / this.zoomStep;
			}
			if (zoomLevel < 0) {
				zoomLevel = 0;
			}
		}
		else if ((zoomLevel < this.maxZoomLevel) && (scale < this.zoomOutLimit)) {
			while (scale < this.zoomOutLimit) {
				zoomLevel++;
				scale = scale * this.zoomStep;
			}
			if (zoomLevel > this.maxZoomLevel) {
				zoomLevel = this.maxZoomLevel;
			}
		}

		this.scale = scale;

		if (zoomLevel != this.zoomLevel) {
			this.zoomLevel = zoomLevel;
			this.step = Math.pow(this.zoomStep, this.zoomLevel);
		}

		this.px = Math.floor(x - (x - this.px) * zoom);
		this.py = Math.floor(y - (y - this.py) * zoom);
		this.updateCanvas();
	}
};

this.Kasuari = Kasuari;

})();
<|endoftext|>


<commit_before>can = {};
if (window.STEALDOJO){
	steal('can/util/dojo')
} else if( window.STEALMOO) {
	steal('can/util/mootools')
} else if(window.STEALYUI){
	steal('can/util/yui');
} else if(window.STEALZEPTO){
	steal('can/util/zepto');
} else {
	steal('can/util/jquery')
}

/**
@function can.trim
@parent can.util
Removes leading and trailing whitespace

    Can.trim( " foo " ) // -> "foo"

@param {String} str the string to trim
@return {String} the value of the string
 */
//
/**
@function can.makeArray
@parent can.util
Converts array like data into arrays.

    Can.makeArray({0 : "zero", 1: "one", length: 2})
       // -> ["zero","one"]
 */
//
/**
@function can.isArray
@parent can.util
Returns if the object is an Array

    can.isArray([]) //-> true
    can.isArray(false)

@param {Array} arr any JS object
@return {Boolean} true if an array
*/
//
/**
@function can.each
@parent can.util
Iterates through an array or object like
like [http://api.jquery.com/jQuery.each/ jQuery.each].

    can.each([{prop: "val1"}, {prop: "val2"}], function( index, value ) {
      // function called with
      //  index=0 value={prop: "val1"}
      //  index=1 value={prop: "val2"}
    })

@param {Object} arr any JS object or array
@return {Object} the function passed to can.each
*/
//
/**
@function can.extend
@parent can.util
Extends an object like
like [http://api.jquery.com/jQuery.extend/ jQuery.extend].

    var first = {},
        second = {a: "b"},
        thrid = {c: "d"};
    can.extend(first, second, third); //-> first
    first  //-> {a: "b",c : "d"}
    second //-> {a: "b"}
    thrid  //-> {c: "d"}
*/
//
/**
@function can.param
@parent can.util
Parameterizes an object into a query string
like [http://api.jquery.com/jQuery.param/ jQuery.param].

    can.param({a: "b", c: "d"}) //-> "a=b&c=d"
*/
//
/**
@function can.isEmptyObject
@parent can.util
Returns if an object is empty like
[http://api.jquery.com/jQuery.isEmptyObject/ jQuery.isEmptyObject].

    can.isEmptyObject({})      //-> true
    can.isEmptyObject({a:"b"}) //-> false

*/
//
/**
@function can.proxy
@parent can.util
Returns if an object is empty like
[http://api.jquery.com/jQuery.proxy/ jQuery.proxy].

     var func = can.proxy(function(one){
       return this.a + one
     }, {a: "b"});
     func("two") //-> "btwo"

*/
//
/**
@function can.proxy
@parent can.util
Returns if an object is empty like
[http://api.jquery.com/jQuery.proxy/ jQuery.proxy].

     var func = can.proxy(function(one){
       return this.a + one
     }, {a: "b"});
     func("two") //-> "btwo"

*/
//
/**
@function can.isFunction
@parent can.util
Returns if an object is a function like
[http://api.jquery.com/jQuery.isFunction/ jQuery.isFunction].

     can.isFunction({})           //-> false
     can.isFunction(function(){}) //-> true

*/
//
/**
@function can.bind
@parent can.bind

`can.bind(obj, eventName, handler)` binds a callback handler
on an object for a given event.  It works on:

  - HTML elements and the window
  - Nodelists of the underlying library
  - Objects
  - Objects with bind / unbind methods

The idea is that bind can be used on anything that produces events
and it will figure out the appropriate way to
bind to it.  Typically, `can.bind` is only used internally to
CanJS; however, if you are making libraries or extensions, use
`can.bind` to listen to events independent of the underlying library.

__Binding to an object__

    var obj = {};
    can.bind(obj,"something", function(ev, arg1, arg){
    	arg1 // 1
    	arg2 // 2
    })
    can.trigger(obj,"something",[1,2])

__Binding to an HTMLElement__

    var el = document.getElementById('foo')
    can.bind(el, "click", function(ev){
    	this // el
    })

__Binding to a NodeList__

    can.bind( $("#foo") , "click", function(){

    })

*/
//
/**
 * @function can.unbind
 * @parent can.util
 */
//
/**
@function can.delegate
@parent can.util
*/
//
/**
@function can.undelegate
@parent can.util
*/
//
/**
@function can.trigger
@parent can.util
*/
//
/**
@function can.ajax
@parent can.util

`can.ajax( settings )` is used to make an asynchronous HTTP (Ajax) request
similar to [http://api.jquery.com/jQuery.ajax/ jQuery.ajax].

	can.ajax({
		url: 'ajax/farm/animals',
		success: function(animals) {
			can.$('.farm').html(animals);
		}
	});

*/
//
/**
@function can.$
@parent can.util

`can.$(selector|element|elements)` returns the the underlying
library's NodeList.  It can be passed
a css selector, a HTMLElement or an array of HTMLElements.

The following lists how the NodeList is created by each library:

 - __jQuery__ `jQuery( HTMLElement )`
 - __Zepto__ `Zepto( HTMLElement )`
 - __Dojo__ `new dojo.NodeList( HTMLElement )`
 - __Mootools__ `$$( HTMLElement )`
 - __YUI__ `Y.all(selector)` or `Y.NodeList`

*/
//
/**
@function can.buildFragment
@parent can.util

`can.buildFragment([html], nodes)` returns a document fragment for the HTML passed.

*/
//
/**
@function can.append
@parent can.util

`can.append( wrappedNodeList, html )` inserts content to the end of each wrapped node list item(s) passed.

	// Before

	can.append( can.$('#demo'), 'Demos are fun!' );

	// After

Demos are fun!

*/
//
/**
@function can.remove
@parent can.util
*/
//
/**
@function can.data
@parent can.util

`can.data` enables the associatation of arbitrary data with DOM nodes and JavaScript objects.

### Setting Data

	can.data( can.$('#elm'), key, value )

- __wrappedNodeList__ node list to associate data to.
- __key__ string name of the association.
- __value__ tdata value; it can be any Javascript type including Array or Object.

### Accessing Data

	can.data( can.$('#elm'), key )

- __wrappedNodeList__ node list to retrieve association data from.
- __key__ string name of the association.

Due to the way browsers security restrictions with plugins and external code,
the _data_ method cannot be used on <object> (unless it's a Flash plugin), <applet> or <embed> elements.

*/
//
/**
@function can.addClass
@parent can.util

`can.addClass( nodelist, className )` adds the specified class(es) to
nodelist's HTMLElements.  It does NOT replace any existing class(es)
already defined.

	// Before

    can.addClass(can.$("#foo"),"bar")

	// After

You can also pass multiple class(es) and it will add them to the existing
set also.

	// Before

	can.addClass(can.$("#foo"),"bar man")

	// After

This works similarly to [http://api.jquery.com/addClass/ jQuery.fn.addClass].

*/
//
/**
@function can.when
@parent can.util
*/
//
/**
@class can.Deferred
@parent can.util
*/
//
/*
 * @prototype
 */
//
/**
@function pipe
`deferred.pipe(done, fail)` is a utility to filter Deferred(s).

	var def = can.Deferred(),
		filtered = def.pipe(function(val) {
			return val + " is awesome!";
		});

	def.resolve('Can');

	filtered.done(function(value) {
		alert(value); // Alerts: 'Can is awesome!'
	});

@param {Object} doneCallbacks A function called when the Deferred is resolved.
@param {Object} failCallbacks A function called when the Deferred is rejected.
*/
//
/**
@function resolveWith
`deferred.resolveWith(context, doneCallbacks)` resolves a Deferred and calls the `doneCallbacks` give the arguments.

	var def = can.Deferred();
	def.resolveWith(this, { animals: [ 'cows', 'monkey', 'panda' ] })

@param {Object} context Context passed to the `doneCallbacks` as the `this` object.
@param {Object} args Optional array of args that are passed to the `doneCallbacks`.
*/
//
/**
@function rejectWith
`deferred.rejectWith(context, failCallbacks)` rejects a Deferred and calls the `failCallbacks` give the arguments.

	var def = can.Deferred();
	def.rejectWith(this, { error: "Animals are gone." })

@param {Object} context Context passed to the `doneCallbacks` as the `this` object.
@param {Object} args Optional array of args that are passed to the `failCallbacks`.
*/
//
/**
@function done
`deferred.done(successCallbacks)` adds handler(s) to be called when the Deferred object is resolved.

	var def = can.Deferred();
	def.done(function(){
		//- Deferred is done.
	});

@param {Object} successCallbacks function that is called when the Deferred is resolved.
 */
//
/**
@function always
`deferred.always( alwaysCallbacks )` adds handler(s) to be called when the Deferred object is either resolved or rejected.

	var def = can.Deferred();
	def.always( function(){
		//- Called whether the handler fails or is success.
	});

@param {Object} alwaysCallbacks A function called when the Deferred is resolved or rejected.
*/
//
/**
@function then
`deferred.then( doneCallbacks, failCallbacks )` adds handler(s) to be called when the Deferred object to be called after its resolved.

	var def = can.Deferred();
	def.then(function(){
		//- Called when the deferred is resolved.
	}, function(){
		//- Called when the deferred fails.
	})

@param {Object} doneCallbacks A function called when the Deferred is resolved.
@param {Object} failCallbacks A function called when the Deferred is rejected.
*/
//
/**
@function isResolved
`deferred.isResolved()` returns whether a Deferred object has been resolved.

	var def = can.Deferred();
	var resolved = def.isResolved();

*/
/**
@function isRejected
`deferred.isRejected()` returns whether a Deferred object has been rejected.

	var def = can.Deferred();
	var rejected = def.isRejected()

*/
//
/**
@function reject
`deferred.reject( args )` rejects the Deferred object and calls the fail callbacks with the given arguments.

	var def = can.Deferred();
	def.reject({ error: 'Thats not an animal.' })

@param {Object} arguments Optional arguments that are passed to the fail callbacks.
*/
//
/**
@function resolve
`deferred.resolve( args )` resolves a Deferred object and calls the done callbacks with the given arguments.

	var def = can.Deferred();
	def.resolve({ animals: [ 'pig', 'cow' ] })

@param {Object} arguments Optional arguments that are passed to the done callbacks.
*/
//<commit_msg>Updated some docs in until<commit_after>can = {};
if (window.STEALDOJO){
	steal('can/util/dojo')
} else if( window.STEALMOO) {
	steal('can/util/mootools')
} else if(window.STEALYUI){
	steal('can/util/yui');
} else if(window.STEALZEPTO){
	steal('can/util/zepto');
} else {
	steal('can/util/jquery')
}

/**
@function can.trim
@parent can.util

`can.trim(string)` removes leading and trailing whitespace from a string.  It will also
remove all newlines, spaces including non-breaking, and tabs.  If these occur in the middle
of the string, then they will be persisted.

    can.trim( " foo " ) // -> "foo"

@param {String} str the string to trim
@return {String} the value of the string
 */
//
/**
@function can.makeArray
@parent can.util
Converts array like data into arrays.

    can.makeArray({0 : "zero", 1: "one", length: 2})
       // -> ["zero","one"]
 */
//
/**
@function can.isArray
@parent can.util
Returns if the object is an Array

    can.isArray([]) //-> true
    can.isArray(false)

@param {Array} arr any JS object
@return {Boolean} true if an array
*/
//
/**
@function can.each
@parent can.util
Iterates through an array or object like
like [http://api.jquery.com/jQuery.each/ jQuery.each].

    can.each([{prop: "val1"}, {prop: "val2"}], function( index, value ) {
      // function called with
      //  index=0 value={prop: "val1"}
      //  index=1 value={prop: "val2"}
    })

@param {Object} arr any JS object or array
@return {Object} the function passed to can.each
*/
//
/**
@function can.extend
@parent can.util
Extends an object like
like [http://api.jquery.com/jQuery.extend/ jQuery.extend].

    var first = {},
        second = {a: "b"},
        thrid = {c: "d"};
    can.extend(first, second, third); //-> first
    first  //-> {a: "b",c : "d"}
    second //-> {a: "b"}
    thrid  //-> {c: "d"}
*/
//
/**
@function can.param
@parent can.util
Parameterizes an object into a query string
like [http://api.jquery.com/jQuery.param/ jQuery.param].

    can.param({a: "b", c: "d"}) //-> "a=b&c=d"
*/
//
/**
@function can.isEmptyObject
@parent can.util
Returns if an object is empty like
[http://api.jquery.com/jQuery.isEmptyObject/ jQuery.isEmptyObject].

    can.isEmptyObject({})      //-> true
    can.isEmptyObject({a:"b"}) //-> false

*/
//
/**
@function can.proxy
@parent can.util
Returns if an object is empty like
[http://api.jquery.com/jQuery.proxy/ jQuery.proxy].

     var func = can.proxy(function(one){
       return this.a + one
     }, {a: "b"});
     func("two") //-> "btwo"

*/
//
/**
@function can.proxy
@parent can.util
Returns if an object is empty like
[http://api.jquery.com/jQuery.proxy/ jQuery.proxy].

     var func = can.proxy(function(one){
       return this.a + one
     }, {a: "b"});
     func("two") //-> "btwo"

*/
//
/**
@function can.isFunction
@parent can.util
Returns if an object is a function like
[http://api.jquery.com/jQuery.isFunction/ jQuery.isFunction].

     can.isFunction({})           //-> false
     can.isFunction(function(){}) //-> true

*/
//
/**
@function can.bind
@parent can.bind

`can.bind(obj, eventName, handler)` binds a callback handler
on an object for a given event.  It works on:

  - HTML elements and the window
  - Nodelists of the underlying library
  - Objects
  - Objects with bind / unbind methods

The idea is that bind can be used on anything that produces events
and it will figure out the appropriate way to
bind to it.  Typically, `can.bind` is only used internally to
CanJS; however, if you are making libraries or extensions, use
`can.bind` to listen to events independent of the underlying library.

__Binding to an object__

    var obj = {};
    can.bind(obj,"something", function(ev, arg1, arg){
    	arg1 // 1
    	arg2 // 2
    })
    can.trigger(obj,"something",[1,2])

__Binding to an HTMLElement__

    var el = document.getElementById('foo')
    can.bind(el, "click", function(ev){
    	this // el
    })

__Binding to a NodeList__

    can.bind( $("#foo") , "click", function(){

    })

*/
//
/**
 * @function can.unbind
 * @parent can.util
 */
//
/**
@function can.delegate
@parent can.util
*/
//
/**
@function can.undelegate
@parent can.util
*/
//
/**
@function can.trigger
@parent can.util
*/
//
/**
@function can.ajax
@parent can.util

`can.ajax( settings )` is used to make an asynchronous HTTP (Ajax) request
similar to [http://api.jquery.com/jQuery.ajax/ jQuery.ajax].

	can.ajax({
		url: 'ajax/farm/animals',
		success: function(animals) {
			can.$('.farm').html(animals);
		}
	});

*/
//
/**
@function can.$
@parent can.util

`can.$(selector|element|elements)` returns the the underlying
library's NodeList.  It can be passed
a css selector, a HTMLElement or an array of HTMLElements.

The following lists how the NodeList is created by each library:

 - __jQuery__ `jQuery( HTMLElement )`
 - __Zepto__ `Zepto( HTMLElement )`
 - __Dojo__ `new dojo.NodeList( HTMLElement )`
 - __Mootools__ `$$( HTMLElement )`
 - __YUI__ `Y.all(selector)` or `Y.NodeList`

*/
//
/**
@function can.buildFragment
@parent can.util

`can.buildFragment([html], nodes)` returns a document fragment for the HTML passed.

*/
//
/**
@function can.append
@parent can.util

`can.append( wrappedNodeList, html )` inserts content to the end of each wrapped node list item(s) passed.

	// Before

	can.append( can.$('#demo'), 'Demos are fun!' );

	// After

Demos are fun!

*/
//
/**
@function can.remove
@parent can.util
*/
//
/**
@function can.data
@parent can.util

`can.data` enables the associatation of arbitrary data with DOM nodes and JavaScript objects.

### Setting Data

	can.data( can.$('#elm'), key, value )

- __wrappedNodeList__ node list to associate data to.
- __key__ string name of the association.
- __value__ tdata value; it can be any Javascript type including Array or Object.

### Accessing Data

	can.data( can.$('#elm'), key )

- __wrappedNodeList__ node list to retrieve association data from.
- __key__ string name of the association.

Due to the way browsers security restrictions with plugins and external code,
the _data_ method cannot be used on `object` (unless it's a Flash plugin), `applet` or `embed` elements.

*/
//
/**
@function can.addClass
@parent can.util

`can.addClass( nodelist, className )` adds the specified class(es) to
nodelist's HTMLElements.  It does NOT replace any existing class(es)
already defined.

	// Before

    can.addClass(can.$("#foo"),"bar")

	// After

You can also pass multiple class(es) and it will add them to the existing
set also.

	// Before

	can.addClass(can.$("#foo"),"bar man")

	// After

This works similarly to [http://api.jquery.com/addClass/ jQuery.fn.addClass].

*/
//
/**
@function can.when
@parent can.util

`can.when(args)` provides the ability to execute callback function(s)
typically based on a Deferred or AJAX object.

	can.when( can.ajax('api/farm/animals') ).then(function(animals){
     	alert(animals); //-> alerts the ajax response
	});

You can also use this for regular JavaScript objects.

	$.when( { animals: [ 'cat' ] } ).done(function(animals){
		alert(animals[0]); //-> alerts 'cat'
	});

@param {Object} deferreds ajax or JavaScript objects
*/
//
/**
@class can.Deferred
@parent can.util

`can.Deferred` is a object that allows users to assign and chain callback
function(s) for the success or failure state of both asynchronous and synchronous function(s).

*/
//
/*
 * @prototype
 */
//
/**
@function pipe
`deferred.pipe(done, fail)` is a utility to filter Deferred(s).

	var def = can.Deferred(),
		filtered = def.pipe(function(val) {
			return val + " is awesome!";
		});

	def.resolve('Can');

	filtered.done(function(value) {
		alert(value); // Alerts: 'Can is awesome!'
	});

@param {Object} doneCallbacks A function called when the Deferred is resolved.
@param {Object} failCallbacks A function called when the Deferred is rejected.
*/
//
/**
@function resolveWith
`deferred.resolveWith(context, doneCallbacks)` resolves a Deferred and calls the `doneCallbacks` give the arguments.

	var def = can.Deferred();
	def.resolveWith(this, { animals: [ 'cows', 'monkey', 'panda' ] })

@param {Object} context Context passed to the `doneCallbacks` as the `this` object.
@param {Object} args Optional array of args that are passed to the `doneCallbacks`.
*/
//
/**
@function rejectWith
`deferred.rejectWith(context, failCallbacks)` rejects a Deferred and calls the `failCallbacks` give the arguments.

	var def = can.Deferred();
	def.rejectWith(this, { error: "Animals are gone." })

@param {Object} context Context passed to the `doneCallbacks` as the `this` object.
@param {Object} args Optional array of args that are passed to the `failCallbacks`.
*/
//
/**
@function done
`deferred.done(successCallbacks)` adds handler(s) to be called when the Deferred object is resolved.

	var def = can.Deferred();
	def.done(function(){
		//- Deferred is done.
	});

@param {Object} successCallbacks function that is called when the Deferred is resolved.
 */
//
/**
@function always
`deferred.always( alwaysCallbacks )` adds handler(s) to be called when the Deferred object is either resolved or rejected.

	var def = can.Deferred();
	def.always( function(){
		//- Called whether the handler fails or is success.
	});

@param {Object} alwaysCallbacks A function called when the Deferred is resolved or rejected.
*/
//
/**
@function then
`deferred.then( doneCallbacks, failCallbacks )` adds handler(s) to be called when the Deferred object to be called after its resolved.

	var def = can.Deferred();
	def.then(function(){
		//- Called when the deferred is resolved.
	}, function(){
		//- Called when the deferred fails.
	})

@param {Object} doneCallbacks A function called when the Deferred is resolved.
@param {Object} failCallbacks A function called when the Deferred is rejected.
*/
//
/**
@function isResolved
`deferred.isResolved()` returns whether a Deferred object has been resolved.

	var def = can.Deferred();
	var resolved = def.isResolved();

*/
/**
@function isRejected
`deferred.isRejected()` returns whether a Deferred object has been rejected.

	var def = can.Deferred();
	var rejected = def.isRejected()

*/
//
/**
@function reject
`deferred.reject( args )` rejects the Deferred object and calls the fail callbacks with the given arguments.

	var def = can.Deferred();
	def.reject({ error: 'Thats not an animal.' })

@param {Object} arguments Optional arguments that are passed to the fail callbacks.
*/
//
/**
@function resolve
`deferred.resolve( args )` resolves a Deferred object and calls the done callbacks with the given arguments.

	var def = can.Deferred();
	def.resolve({ animals: [ 'pig', 'cow' ] })

@param {Object} arguments Optional arguments that are passed to the done callbacks.
*/
//<|endoftext|>