<commit_before>var Game = function() {
  this.finalScore = 0;
  this.bowlsLeftInFrame = 2;
  this.framesLeft = 10;
  this.frame = 1;
  this.strike = null;
};

Game.prototype.bowl = function(numberOfPinsKnockedDown) {
  if(this.frame === 10 && this.bowlsLeftInFrame === 2 && numberOfPinsKnockedDown === 10) {
    this.strike = true;
    this.bowlsLeftInFrame = 2;
    this.finalScore += 10;
    this.frame = 11
    return;
  }

  if(this.frame === 10 && this.bowlsLeftInFrame === 1 && this.finalScore + numberOfPinsKnockedDown === 10) {
    this.frame = 11;
    this.bowlsLeftInFrame = 1;
    this.finalScore += numberOfPinsKnockedDown;
    return
  }

  if(this.frame === 11 && this.bowlsLeftInFrame > 0) {
    this.finalScore += numberOfPinsKnockedDown;
    this.bowlsLeftInFrame -= 1;

    if(this.strike === true) {
      this.finalScore += numberOfPinsKnockedDown;
    }
  }

  if(this.bowlsLeftInFrame > 0 && this.frame != 11) {
    this.finalScore += numberOfPinsKnockedDown;
    this.bowlsLeftInFrame -= 1;
    if(this.bowlsLeftInFrame === 0) {
      this.framesLeft -= 1;
    }
  }
};<commit_msg>refactor<commit_after>var Game = function() {
  this.finalScore = 0;
  this.bowlsLeftInFrame = 2;
  this.framesLeft = 10;
  this.frame = 1;
  this.strike = null;
};

Game.prototype.bowl = function(numberOfPinsKnockedDown) {

  if(this.frame === 10 && this.bowlsLeftInFrame === 2 && numberOfPinsKnockedDown === 10) {
    this.strike = true;
    this.bowlsLeftInFrame = 2;
    this.finalScore += 10;
    this.frame = 11
    return;
  }

  if(this.isSpareInTenthFrame(numberOfPinsKnockedDown)) {
    this.frame = 11;
    this.bowlsLeftInFrame = 1;
    this.finalScore += numberOfPinsKnockedDown;
    return
  }

  if(this.frame === 11 && this.bowlsLeftInFrame > 0) {
    this.finalScore += numberOfPinsKnockedDown;
    this.bowlsLeftInFrame -= 1;

    if(this.strike === true) {
      this.finalScore += numberOfPinsKnockedDown;
    }
  }

  if(this.bowlsLeftInFrame > 0 && this.frame != 11) {
    this.finalScore += numberOfPinsKnockedDown;
    this.bowlsLeftInFrame -= 1;
    if(this.bowlsLeftInFrame === 0) {
      this.framesLeft -= 1;
    }
  }
};

Game.prototype.isSpareInTenthFrame = function(numberOfPinsKnockedDown) {
  if(this.frame === 10 && this.bowlsLeftInFrame === 1 && this.finalScore + numberOfPinsKnockedDown === 10) {
    return true;
  }
};<|endoftext|>


<commit_before>import { Controller } from "stimulus"

export default class extends Controller {
  static targets = [ "cardElement", "cardErrors", "expMonth", "expYear", "brand", "last4", "pmId" ];
  static styles = {
    base: {
      fontFamily: "Roboto, Arial, sans-serif",
      fontSize: "16px",
      color: "#5c5c5c",
      "::placeholder": {
        color: "#6c6c6c"
      }
    }
  };

  connect() {
    this.parentForm = this.pmIdTarget.form;

    // Initialize Stripe JS
    this.stripe = Stripe(this.data.get("key"));
    this.stripeElement = this.stripe.elements().create("card", {
      style: this.constructor.styles,
      hidePostalCode: true
    });

    // Mount Stripe Elements JS to the form field
    this.stripeElement.mount(this.cardElementTarget);

    this.parentForm.addEventListener("submit", this.stripeSubmit);
    this.stripeElement.addEventListener("change", this.updateErrors);
  }

  // Before the form is submitted we send the card details directly to Stripe (via StripeJS),
  // and receive a token which represents the card object, and add that token into the form.
  stripeSubmit = (event) => {
    if(!this.stripeSelected()) { return }

    event.preventDefault();
    event.stopPropagation();

    this.stripe.createPaymentMethod({type: "card", card: this.stripeElement}).then(response => {
      if (response.error) {
        this.updateErrors(response);
      } else {
        this.pmIdTarget.setAttribute("value", response.paymentMethod.id);
        this.expMonthTarget.setAttribute("value", response.paymentMethod.card.exp_month);
        this.expYearTarget.setAttribute("value", response.paymentMethod.card.exp_year);
        this.brandTarget.setAttribute("value", response.paymentMethod.card.brand);
        this.last4Target.setAttribute("value", response.paymentMethod.card.last4);

        this.parentForm.submit();
      }
    });
  }

  // Update validation messages from Stripe shown in the form
  updateErrors = (data) => {
    if (data.error) {
      this.cardErrorsTarget.textContent = data.error.message;
    } else {
      this.cardErrorsTarget.textContent = "";
    }
  }

  // Boolean; true if Stripe is shown / currently selected
  stripeSelected() {
    return !!this.cardElementTarget.offsetParent
  }
}
<commit_msg>Move initialization to initialize()<commit_after>import { Controller } from "stimulus"

export default class extends Controller {
  static targets = [ "cardElement", "cardErrors", "expMonth", "expYear", "brand", "last4", "pmId" ];
  static styles = {
    base: {
      fontFamily: "Roboto, Arial, sans-serif",
      fontSize: "16px",
      color: "#5c5c5c",
      "::placeholder": {
        color: "#6c6c6c"
      }
    }
  };

  initialize() {
    this.parentForm = this.pmIdTarget.form;

    // Initialize Stripe JS
    this.stripe = Stripe(this.data.get("key"));
    this.stripeElement = this.stripe.elements().create("card", {
      style: this.constructor.styles,
      hidePostalCode: true
    });

    // Mount Stripe Elements JS to the form field
    this.stripeElement.mount(this.cardElementTarget);
  }

  connect() {
    this.parentForm.addEventListener("submit", this.stripeSubmit);
    this.stripeElement.addEventListener("change", this.updateErrors);
  }

  // Before the form is submitted we send the card details directly to Stripe (via StripeJS),
  // and receive a token which represents the card object, and add that token into the form.
  stripeSubmit = (event) => {
    if(!this.stripeSelected()) { return }

    event.preventDefault();
    event.stopPropagation();

    this.stripe.createPaymentMethod({type: "card", card: this.stripeElement}).then(response => {
      if (response.error) {
        this.updateErrors(response);
      } else {
        this.pmIdTarget.setAttribute("value", response.paymentMethod.id);
        this.expMonthTarget.setAttribute("value", response.paymentMethod.card.exp_month);
        this.expYearTarget.setAttribute("value", response.paymentMethod.card.exp_year);
        this.brandTarget.setAttribute("value", response.paymentMethod.card.brand);
        this.last4Target.setAttribute("value", response.paymentMethod.card.last4);

        this.parentForm.submit();
      }
    });
  }

  // Update validation messages from Stripe shown in the form
  updateErrors = (data) => {
    if (data.error) {
      this.cardErrorsTarget.textContent = data.error.message;
    } else {
      this.cardErrorsTarget.textContent = "";
    }
  }

  // Boolean; true if Stripe is shown / currently selected
  stripeSelected() {
    return !!this.cardElementTarget.offsetParent
  }
}
<|endoftext|>


<commit_before>var info = function(game){}

info.prototype = {
  	create: function(){
                this.game.physics.startSystem(Phaser.Physics.ARCADE);
		var gameTitle = this.game.add.sprite(this.game.world.width * 0.5,this.game.world.height * .1,"game_title");
		gameTitle.anchor.setTo(0.5,0.5);
		var exitButton = this.game.add.button(this.game.world.width * 0.5,this.game.world.height * .2,"exit",this.menu,this);
		exitButton.anchor.setTo(0.5,0.5);

                this.create_simon();
                this.get_info();

                //go full screen on click
                this.game.input.onDown.add(this.fullscreen, this);
	},
        update: function(){
        },
        simonWeb: function(){
            window.open("http://multi8it.blogspot.com", "_blank");
        },
	menu: function(){
                click.play();
		this.game.state.start("GameTitle");
	},
        fullscreen: function(){
            this.game.scale.fullScreenScaleMode = Phaser.ScaleManager.SHOW_ALL;
            this.game.scale.startFullScreen();
        },

        create_simon: function(){
		simon = this.game.add.sprite(this.game.world.width * 0.5,this.game.world.height * .9,"simon");
                simon.inputEnabled = true;
                simon.events.onInputDown.add(this.simonWeb,this);
                simon.anchor.setTo(0.5,0.5);
                this.game.physics.arcade.enable(simon);
                simon.body.immovable = true;
        },
        get_info: function(){
            $.getJSON( "info.json", function( data ) {
                console.log("data");
                var items = [];
                for(var i = 0;i<data.length;i++){
                    var text=data[i].text;
                    var url=data[i].url;
                    console.log(text +":"+ url);
                }

            });
        }
}
<commit_msg>Added clickable text to info screen<commit_after>var info = function(game){}

info.prototype = {
  	create: function(){
                this.game.physics.startSystem(Phaser.Physics.ARCADE);
		var gameTitle = this.game.add.sprite(this.game.world.width * 0.5,this.game.world.height * .1,"game_title");
		gameTitle.anchor.setTo(0.5,0.5);
		var exitButton = this.game.add.button(this.game.world.width * 0.5,this.game.world.height * .2,"exit",this.menu,this);
		exitButton.anchor.setTo(0.5,0.5);

                this.create_simon();
                this.get_info();

                //go full screen on click
                this.game.input.onDown.add(this.fullscreen, this);
	},
        update: function(){
        },
        simonWeb: function(){
            window.open("http://multi8it.blogspot.com", "_blank");
        },
	menu: function(){
                click.play();
		this.game.state.start("GameTitle");
	},
        fullscreen: function(){
            this.game.scale.fullScreenScaleMode = Phaser.ScaleManager.SHOW_ALL;
            this.game.scale.startFullScreen();
        },

        create_simon: function(){
		simon = this.game.add.sprite(this.game.world.width * 0.5,this.game.world.height * .9,"simon");
                simon.inputEnabled = true;
                simon.events.onInputDown.add(this.simonWeb,this);
                simon.anchor.setTo(0.5,0.5);
                this.game.physics.arcade.enable(simon);
                simon.body.immovable = true;
        },
        get_info: function(){
            _this = this;
            $.getJSON( "info.json", function( data ) {
                var y = _this.game.world.height * 0.3;
                for(var i = 0;i<data.length;i++){
                    var text=data[i].text;
                    var url=data[i].url;

                    var style = { font: "32px Arial", fill: "#ff0044", align: "center" };
                    var t = _this.game.add.text(_this.game.world.centerX,64*i+y, text, style);
                    t.url = url;
                    t.inputEnabled = true;
                    t.events.onInputDown.add(_this.goto_url,this);
                    t.anchor.setTo(0.5,0.5);
                    console.log(text +":"+ url);
                }

            });
        },
        goto_url: function(text){
            click.play();
            window.open(text.url, "_blank");
        }
}
<|endoftext|>


<commit_before>(function(){

var HTTPResponse = function() {
    this._output = false;
    this._ct = false; /* Content-type - the only header which must be present */
}

HTTPResponse.prototype.write = function(str) {
    if (!this._output) {
	this._output = true;
	if (!this._ct) { this.header({"Content-type":"text/html"}); }
	System.stdout("\n");
    }
    System.stdout(str);
}

HTTPResponse.prototype.cookie = function(name, value, expires, path, domain, secure, httponly) {
    if (expires && !(expires instanceof Date)) { return false; }
    var arr = [];
    arr.push(encodeURIComponent(name)+"="+encodeURIComponent(value));
    if (expires) { arr.push("expires="+expires.toGMTString()); }
    if (path) { arr.push("path="+path); }
    if (domain) { arr.push("domain="+domain); }
    if (secure) { arr.push("secure"); }
    if (httponly) { arr.push("httponly"); }

    var str = arr.join("; ");
    this.header({"Set-Cookie":str});
    return true;
}

HTTPResponse.prototype.error = function(txt) {
    this.write("
Error: "+txt+"
");
}

HTTPResponse.prototype.header = function(h) {
    for (var p in h) {
	if (p.match(/content-type/i)) { this._ct = true; }
	var str = p+": "+h[p]+"\n";
	System.stdout(str);
    }
}

HTTPResponse.prototype.escape = function(str) {
    if (!str) { return ""; }
    return str.toString().replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'"); // "
}

HTTPResponse.prototype.dump = function(obj, depth) {
    var d = depth || 0;
    if (!d) { this.write("
\n"); }
    for (var p in obj) {
	var val = obj[p];
	for (var i=0;i<2*d;i++) { this.write(" "); }
	this.write(p+": "+this.escape(val)+"\n");
	if (typeof(val) == "object") {
	    arguments.callee.call(this, val, d+1);
	}
    }
    if (!d) { this.write("
\n"); }
}

var HTTPRequest = function() {
    this.get = {};
    this.post = {};
    this.cookie = {};
    this.files = {};

    this.method = null;
    if (System.env["REQUEST_METHOD"]) { this.method = System.env["REQUEST_METHOD"].toUpperCase(); }
    if (!this.method) { return; }

    this._parseCookie();
    this._parseQS(System.env["QUERY_STRING"], this.get);
    if (this.method == "POST") { this._parsePOST(); }
}

HTTPRequest.prototype.header = function(name) {
    var n = "HTTP_" + name.toUpperCase().replace(/-/g,"_");
    return (n in System.env ? System.env[n] : null);
}

HTTPRequest.prototype._parseCookie = function() {
    if (!("HTTP_COOKIE" in System.env)) { return; }
    var all = System.env["HTTP_COOKIE"].split("; ");
    for (var i=0;i<all.length;i++) {
	var row = all[i];
	var eq = row.indexOf("=");
	var name = row.substring(0,eq);
	var value = row.substring(eq+1);
	this.cookie[name] = unescape(value);
    }
}

HTTPRequest.prototype._decode = function(str) {
    var s = str;
    var err = false;
    try {
	s = decodeURIComponent(str);
    } catch(e) {
//	response.error("Cannot urldecode string");
    } finally {
	return s;
    }
}

HTTPRequest.prototype._parseQS = function(qs, output) {
    if (!qs) { return; }
    var parts = qs.split("&");
    for (var i=0;i<parts.length;i++) {
	var item = parts[i];
	if (!item) { continue; }
	var eq = item.indexOf("=");
	var name = "";
	var value = "";

	if (eq == -1) {
	    name = item;
	} else {
	    name = item.substring(0,eq);
	    value = item.substring(eq+1);
	}
	if (name.substring(name.length-2) == "[]") { name = name.substring(0,name.length-2); }

	name = this._decode(name);
	value = this._decode(value);

	this._addField(output, name, value);
    }
}

HTTPRequest.prototype._parsePOST = function() {
    var ct = System.env["CONTENT_TYPE"] || "";
    var length = parseInt(System.env["CONTENT_LENGTH"], 10);
    if (!length) { return false; }

    if (System.env["CONTENT_TYPE"] == "application/x-www-form-urlencoded") {
	var data = System.stdin(length);
	this._parseQS(data, this.post);
    } else if (ct.match(/boundary/)) {
	var arr = System.stdin(length, true);
	var str = String.fromCharCode.apply(this, arr); /* convert from array to string */
	this._parseMultipart(ct, str, false);
    } else {
	return false;
    }
    return true;
}

HTTPRequest.prototype._addField = function(output, name, value) {
    if (!(name in output)) {
        output[name] = value;
    } else if (output[name] instanceof Array) {
        output[name].push(value);
    } else {
	output[name] = [output[name], value];
    }
}

HTTPRequest.prototype._parseMultipart = function(header, data, name) {
    var boundary = header.match(/boundary=(.*)/); /* find boundary */
    boundary = boundary[1];
    var start = "--"+boundary+"\r\n";
    var end = "--"+boundary+"--";
    var parts = data.split(start); /* split by boundary */
    for (var i=0;i<parts.length;i++) { /* all multipart parts */
	var item = parts[i].substring(0, parts[i].length-2);
	if (item == "" || item == "--") { continue; }

	var lines = item.split("\r\n");
	var done = false;
	var obj = {
	    headers:{},
	    data:""
	};
	for (var j=0;j<lines.length;j++) {
	    if (lines[j] == end) { continue; }
	    if (done) { /* data */
		obj.data += (obj.data.length ? "\r\n" : "")+lines[j];
	    } else { /* headers */
		if (lines[j] == "") { done = true; continue; } /* headers done */
		var r = lines[j].match(/([^:]+): *(.*)/);
		var name = r[1].replace(/-/g,"_").toUpperCase();
		var value = r[2];
		obj.headers[name] = value;
	    }
	}
	this._processMultipart(obj, name); /* content parsed, decide how to handle it */
    }
}

HTTPRequest.prototype._processMultipart = function(obj, n) {
    var name = n;
    var cd = obj.headers["CONTENT_DISPOSITION"] || "";
    var ct = obj.headers["CONTENT_TYPE"] || "";
    var r = cd.match(/ name="(.*?)"/i); /* form field name */
    if (r) { name = r[1]; }
    if (ct.match(/multipart\/mixed/i)) { /* recursive processing */
	this._parseMultipart(ct, obj.data, name);
    } else { /* no recursion: either file or form field */
        var r = cd.match(/filename="(.*?)"/i);
	if (r) { /* file */
	    obj.originalName = r[1];
	    this._addField(this.files, name, obj);
	} else { /* form field */
	    var arr = [];
	    for (var i=0;i<obj.data.length;i++) {
		arr.push("%" + obj.data.charCodeAt(i).toString(16));
	    }
	    this._addField(this.post, name, decodeURI(arr.join("")));
	}
    }
}

var HTTPSession = function() {
    this._data = {};
    this._id = null;
    this._file = null;

    this._name = "V8SID";
    this._path = "/tmp";
    if (this._path.charAt(this._path.length-1) != "/") { this._path += "/"; }
    this._lifetime = 60*60;
    this._gc();

    var ok = false;
    if (request.cookie[this._name]) { /* cookie here */
	var id = request.cookie[this._name];
	var f = new File(this._fileName(id));
	if (f.exists()) { /* matching file */
	    this._id = id;
	    this._file = f;
	    this._load();
	    ok = true;
	}
    }
    if (!ok) {
	this.setId();
	this.clear();
    }

    var self = this;
    var callback = function() { self.save(); }
    onexit(callback);
}

HTTPSession.prototype.set = function(name, value) {
    this._data[name] = value;
}

HTTPSession.prototype.get = function(name) {
    return this._data[name] || null;
}

HTTPSession.prototype.clear = function() {
    this._data = {};
    if (this._file.exists()) { this._file.remove(); }
}

HTTPSession.prototype.save = function() {
    var propcnt = 0;
    for (var p in this._data) { propcnt++; }
    if (propcnt == 0) {
	if (this._file.exists()) { this._file.remove(); }
	return;
    }
    var str = Util.serialize(this._data);
    this._file.open("w").write(str).close();
}

HTTPSession.prototype.getId = function() {
    return this._id;
}

HTTPSession.prototype.setId = function(id) {
    this._id = id || this._newId();
    this._cookie();
    this._file = new File(this._fileName(this._id));
}

HTTPSession.prototype._newId = function() {
    var str = "";
    for (var i=0;i<3;i++) {
	str += Math.random().toString();
    }
    return Util.sha1(str);
}

HTTPSession.prototype._fileName = function(id) {
    return this._path + Util.sha1(id);
}

HTTPSession.prototype._gc = function() {
    var d = new Directory(this._path);
    var files = d.listFiles();
    var now = Math.round(new Date().getTime()/1000);
    for (var i=0;i<files.length;i++) {
	var file = new File(this._path + files[i]);
	var data = file.stat();
	if (now - data.atime > this._lifetime && now - data.mtime > this._lifetime) {
	    try { file.remove(); } catch(e) { }
	}
    }
}

HTTPSession.prototype._cookie = function() {
    response.cookie(this._name, this._id);
}

HTTPSession.prototype._load = function() {
    var str = this._file.open("r").read();
    this._file.close();
    this._data = Util.unserialize(str);
}

this.response = new HTTPResponse();
this.request = new HTTPRequest();
this.session = new HTTPSession();

})();
<commit_msg>'Infinite' cookie lifetime<commit_after>(function(){

var HTTPResponse = function() {
    this._output = false;
    this._ct = false; /* Content-type - the only header which must be present */
}

HTTPResponse.prototype.write = function(str) {
    if (!this._output) {
	this._output = true;
	if (!this._ct) { this.header({"Content-type":"text/html"}); }
	System.stdout("\n");
    }
    System.stdout(str);
}

HTTPResponse.prototype.cookie = function(name, value, expires, path, domain, secure, httponly) {
    if (expires && !(expires instanceof Date)) { return false; }
    var arr = [];
    arr.push(encodeURIComponent(name)+"="+encodeURIComponent(value));
    if (expires) { arr.push("expires="+expires.toGMTString()); }
    if (path) { arr.push("path="+path); }
    if (domain) { arr.push("domain="+domain); }
    if (secure) { arr.push("secure"); }
    if (httponly) { arr.push("httponly"); }

    var str = arr.join("; ");
    this.header({"Set-Cookie":str});
    return true;
}

HTTPResponse.prototype.error = function(txt) {
    this.write("
Error: "+txt+"
");
}

HTTPResponse.prototype.header = function(h) {
    for (var p in h) {
	if (p.match(/content-type/i)) { this._ct = true; }
	var str = p+": "+h[p]+"\n";
	System.stdout(str);
    }
}

HTTPResponse.prototype.escape = function(str) {
    if (!str) { return ""; }
    return str.toString().replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'"); // "
}

HTTPResponse.prototype.dump = function(obj, depth) {
    var d = depth || 0;
    if (!d) { this.write("
\n"); }
    for (var p in obj) {
	var val = obj[p];
	for (var i=0;i<2*d;i++) { this.write(" "); }
	this.write(p+": "+this.escape(val)+"\n");
	if (typeof(val) == "object") {
	    arguments.callee.call(this, val, d+1);
	}
    }
    if (!d) { this.write("
\n"); }
}

var HTTPRequest = function() {
    this.get = {};
    this.post = {};
    this.cookie = {};
    this.files = {};

    this.method = null;
    if (System.env["REQUEST_METHOD"]) { this.method = System.env["REQUEST_METHOD"].toUpperCase(); }
    if (!this.method) { return; }

    this._parseCookie();
    this._parseQS(System.env["QUERY_STRING"], this.get);
    if (this.method == "POST") { this._parsePOST(); }
}

HTTPRequest.prototype.header = function(name) {
    var n = "HTTP_" + name.toUpperCase().replace(/-/g,"_");
    return (n in System.env ? System.env[n] : null);
}

HTTPRequest.prototype._parseCookie = function() {
    if (!("HTTP_COOKIE" in System.env)) { return; }
    var all = System.env["HTTP_COOKIE"].split("; ");
    for (var i=0;i<all.length;i++) {
	var row = all[i];
	var eq = row.indexOf("=");
	var name = row.substring(0,eq);
	var value = row.substring(eq+1);
	this.cookie[name] = unescape(value);
    }
}

HTTPRequest.prototype._decode = function(str) {
    var s = str;
    var err = false;
    try {
	s = decodeURIComponent(str);
    } catch(e) {
//	response.error("Cannot urldecode string");
    } finally {
	return s;
    }
}

HTTPRequest.prototype._parseQS = function(qs, output) {
    if (!qs) { return; }
    var parts = qs.split("&");
    for (var i=0;i<parts.length;i++) {
	var item = parts[i];
	if (!item) { continue; }
	var eq = item.indexOf("=");
	var name = "";
	var value = "";

	if (eq == -1) {
	    name = item;
	} else {
	    name = item.substring(0,eq);
	    value = item.substring(eq+1);
	}
	if (name.substring(name.length-2) == "[]") { name = name.substring(0,name.length-2); }

	name = this._decode(name);
	value = this._decode(value);

	this._addField(output, name, value);
    }
}

HTTPRequest.prototype._parsePOST = function() {
    var ct = System.env["CONTENT_TYPE"] || "";
    var length = parseInt(System.env["CONTENT_LENGTH"], 10);
    if (!length) { return false; }

    if (System.env["CONTENT_TYPE"] == "application/x-www-form-urlencoded") {
	var data = System.stdin(length);
	this._parseQS(data, this.post);
    } else if (ct.match(/boundary/)) {
	var arr = System.stdin(length, true);
	var str = String.fromCharCode.apply(this, arr); /* convert from array to string */
	this._parseMultipart(ct, str, false);
    } else {
	return false;
    }
    return true;
}

HTTPRequest.prototype._addField = function(output, name, value) {
    if (!(name in output)) {
        output[name] = value;
    } else if (output[name] instanceof Array) {
        output[name].push(value);
    } else {
	output[name] = [output[name], value];
    }
}

HTTPRequest.prototype._parseMultipart = function(header, data, name) {
    var boundary = header.match(/boundary=(.*)/); /* find boundary */
    boundary = boundary[1];
    var start = "--"+boundary+"\r\n";
    var end = "--"+boundary+"--";
    var parts = data.split(start); /* split by boundary */
    for (var i=0;i<parts.length;i++) { /* all multipart parts */
	var item = parts[i].substring(0, parts[i].length-2);
	if (item == "" || item == "--") { continue; }

	var lines = item.split("\r\n");
	var done = false;
	var obj = {
	    headers:{},
	    data:""
	};
	for (var j=0;j<lines.length;j++) {
	    if (lines[j] == end) { continue; }
	    if (done) { /* data */
		obj.data += (obj.data.length ? "\r\n" : "")+lines[j];
	    } else { /* headers */
		if (lines[j] == "") { done = true; continue; } /* headers done */
		var r = lines[j].match(/([^:]+): *(.*)/);
		var name = r[1].replace(/-/g,"_").toUpperCase();
		var value = r[2];
		obj.headers[name] = value;
	    }
	}
	this._processMultipart(obj, name); /* content parsed, decide how to handle it */
    }
}

HTTPRequest.prototype._processMultipart = function(obj, n) {
    var name = n;
    var cd = obj.headers["CONTENT_DISPOSITION"] || "";
    var ct = obj.headers["CONTENT_TYPE"] || "";
    var r = cd.match(/ name="(.*?)"/i); /* form field name */
    if (r) { name = r[1]; }
    if (ct.match(/multipart\/mixed/i)) { /* recursive processing */
	this._parseMultipart(ct, obj.data, name);
    } else { /* no recursion: either file or form field */
        var r = cd.match(/filename="(.*?)"/i);
	if (r) { /* file */
	    obj.originalName = r[1];
	    this._addField(this.files, name, obj);
	} else { /* form field */
	    var arr = [];
	    for (var i=0;i<obj.data.length;i++) {
		arr.push("%" + obj.data.charCodeAt(i).toString(16));
	    }
	    this._addField(this.post, name, decodeURI(arr.join("")));
	}
    }
}

var HTTPSession = function() {
    this._data = {};
    this._id = null;
    this._file = null;

    this._name = "V8SID";
    this._path = "/tmp";
    if (this._path.charAt(this._path.length-1) != "/") { this._path += "/"; }
    this._lifetime = 60*60;
    this._gc();

    var ok = false;
    if (request.cookie[this._name]) { /* cookie here */
	var id = request.cookie[this._name];
	var f = new File(this._fileName(id));
	if (f.exists()) { /* matching file */
	    this._id = id;
	    this._file = f;
	    this._load();
	    ok = true;
	}
    }
    if (!ok) {
	this.setId();
	this.clear();
    }

    var self = this;
    var callback = function() { self.save(); }
    onexit(callback);
}

HTTPSession.prototype.set = function(name, value) {
    this._data[name] = value;
}

HTTPSession.prototype.get = function(name) {
    return this._data[name] || null;
}

HTTPSession.prototype.clear = function() {
    this._data = {};
    if (this._file.exists()) { this._file.remove(); }
}

HTTPSession.prototype.save = function() {
    var propcnt = 0;
    for (var p in this._data) { propcnt++; }
    if (propcnt == 0) {
	if (this._file.exists()) { this._file.remove(); }
	return;
    }
    var str = Util.serialize(this._data);
    this._file.open("w").write(str).close();
}

HTTPSession.prototype.getId = function() {
    return this._id;
}

HTTPSession.prototype.setId = function(id) {
    this._id = id || this._newId();
    this._cookie();
    this._file = new File(this._fileName(this._id));
}

HTTPSession.prototype._newId = function() {
    var str = "";
    for (var i=0;i<3;i++) {
	str += Math.random().toString();
    }
    return Util.sha1(str);
}

HTTPSession.prototype._fileName = function(id) {
    return this._path + Util.sha1(id);
}

HTTPSession.prototype._gc = function() {
    var d = new Directory(this._path);
    var files = d.listFiles();
    var now = Math.round(new Date().getTime()/1000);
    for (var i=0;i<files.length;i++) {
	var file = new File(this._path + files[i]);
	var data = file.stat();
	if (now - data.atime > this._lifetime && now - data.mtime > this._lifetime) {
	    try { file.remove(); } catch(e) { }
	}
    }
}

HTTPSession.prototype._cookie = function() {
    var d = new Date();
    d.setFullYear(100+d.getFullYear());
    response.cookie(this._name, this._id, d);
}

HTTPSession.prototype._load = function() {
    var str = this._file.open("r").read();
    this._file.close();
    this._data = Util.unserialize(str);
}

this.response = new HTTPResponse();
this.request = new HTTPRequest();
this.session = new HTTPSession();

})();
<|endoftext|>


<commit_before>import classNames from 'classnames';
import React, { Component, PropTypes } from 'react';
import elementType from 'react-prop-types/lib/elementType';

import { Table, Pagination, /* Checkbox */ } from 'react-bootstrap';

import GridRow from './GridRow';

/**
 * Grid组件
 *
 * Options: https://datatables.net/reference/option/
 *
 * http://adazzle.github.io/react-data-grid
 *
 */

class Grid extends Component {

  static propTypes = {
    /**
     * 表格填充数据

     * `type: boolean`，数据类型是
     * boolean literal或者是
     * Boolean类型
     * （注意和Boolean全局对象区分）

     * `type: ref`，参照的值比较特殊，是一个object:
     *
zuzhi: {
     *   id: '22EA0EB9-FABA-4224-B290-5D041A1DF773',
     *   code: '0403',
     *   name: '委外部'
     * }

     */
    tableData: PropTypes.array.isRequired,
    /**
     * 表格模型，表头每一列的名称和类型

     * 可以通过hidden来隐藏列，只有当hidden===true的时候隐藏
     */
    columnsModel: PropTypes.array.isRequired,
    /**
     * 分页
     */
    onPagination: PropTypes.func,
    /**
     * 是否启用行选择，复选框/单选框

     * 默认为null，不显示
     *
{
     *   mode: 'checkbox',
     *   onSelect: (rowIdx, rowObj, isSelected, event) => {},
     *   onSelectAll: (tableData, isSelected, event) => {}
     * }

     * mode，checkbox复选，radio单选

     * onSelect，当选择单行的时候触发，参数：
     *

     *
rowIdx
行index
     *
rowObj
行数据
     *
isSelected
复选框/单选框选中状态true/false
     *
event
Event对象
     *

     * onSelectAll，当选择所有行的时候触发，参数：
     *

     *
tableData
所有行的数据
     *
isSelected
复选框/单选框选中状态true/false
     *
event
Event对象
     *

     */
    selectRow: PropTypes.object,

    /**
     * 每一行是否显示操作按钮列

     * 默认的操作按钮在最右侧的列中，如果需要指定在左侧，可以通过
     * align参数来设置

     *
{
     *   align: 'left'
     * }

     * 注意：当操作列和选择列同时存在的时候，选择列会显示在操作列的左侧
     */
    operationColumn: PropTypes.object,
    /**
     * 自定义的操作列组件

     * 除非指定了operationColumn参数，否则操作列不会显示出来
     */
    operationColumnClass: elementType,

    /**
     * 选择一个单元格
     */
    onCellChecked: PropTypes.func,
    /**
     * 是否显示分页
     */
    paging: PropTypes.bool,
    /**
     * 页面数量
     */
    totalPage: PropTypes.number,
    /**
     * 当前页面号
     */
    activePage: PropTypes.number
  };

  static defaultProps = {
    selectRow: null,
    operationColumn: null, // 默认不显示操作列
    operationColumnClass: 'td', // 默认的操作列必须是组件
    paging: false
  };

  constructor(props) {
    super(props);
    this.state = {
      selectedRowsObj: {}
    };
  }

  handlePagination(eventKey) {
    if (this.props.onPagination) {
      this.props.onPagination(eventKey);
    }
  }

  // 在状态中选中所有行
  selectAllRows(isSelected) {
    const { tableData } = this.props;
    const selectedRowsObj = {};
    tableData.forEach((item, index) => {
      selectedRowsObj[index] = {
        selected: isSelected
      };
    });
    this.setState({
      selectedRowsObj
    });
  }

  // 选中一行
  handleSelect(rowIdx, rowObj, isSelected, event) {
    const { selectRow, selectedRowsObj } = this.state;
    selectedRowsObj[rowIdx] = {
      selected: isSelected
    };
    this.setState({
      selectedRowsObj
    });

    if (selectRow && selectRow.onSelect) {
      selectRow.onSelect(rowIdx, rowObj, isSelected, event);
    }
  }

  // 当选中所有行的时候
  handleSelectAll(event) {
    const { selectRow, tableData } = this.props;
    const isSelected = event.target.checked;

    // 在状态中选中所有行
    this.selectAllRows(isSelected);

    if (selectRow && selectRow.onSelectAll) {
      selectRow.onSelectAll(tableData, isSelected, event);
    }
  }

  handleCellChecked(rowIdx, colIdx) {
    if (this.props.onCellChecked) {
      this.props.onCellChecked(rowIdx, colIdx);
    }
  }

  render() {
    const { columnsModel, tableData,
      selectRow, operationColumn, className,
      operationColumnClass: CustomComponent
    } = this.props;

    const { selectedRowsObj } = this.state;

    // 列模型不能为空，但是表体数据可以为空。
    // 当全部为空，只显示一个空div
    // 当只有表体数据为空，只显示表头
    if (!columnsModel || columnsModel.length === 0) {
      return (

);
    }

    const renderTableHeader = () => (
      columnsModel.map((col, key) => {
        // 使用Bootstrap的alignment class来进行对齐
        let alignClass = col.align ? `text-${col.align}` : '';
        // 之前的className只能设定th的class，现在改成使用columnClassName
        // 可以设定th和td的class
        // 由于新旧接口共存，所以需要根据优先级设定好
        const th = (
          {col.label}
        );
        return col.hidden === true ? null : th;
      })
    );

    const renderCheckboxHeader = () => (
      selectRow ? (
        <input type="checkbox"
          onChange={this.handleSelectAll.bind(this)} />
      	) : null
    );

    const pagination = (
      <Pagination className="pagination"
        prev
        next
        first
        last
        ellipsis
        items={this.props.totalPage}
        maxButtons={10}
        activePage={this.props.activePage}
        onSelect={this.handlePagination.bind(this)}
      />
    );

    const self = this;

    // var onRow = this.props.onRow;
    return (

              { renderCheckboxHeader() }
              { renderTableHeader() }
              { operationColumn ? 操作	 : null }

          {
            tableData.map((row, rowIdx) => {
              let selected = false;

              // 该行是否被选中
              if (selectedRowsObj[rowIdx] && selectedRowsObj[rowIdx].selected) {
                selected = true;
              }

              return (<GridRow
                selectRow={selectRow}
                selectionMode={selectRow ? selectRow.mode : null}
                onSelect={selectRow ? self.handleSelect.bind(self) : null}
                selected={selected}
                operationColumn={operationColumn}
                operationColumnClass={CustomComponent}
                rowObj={row} key={rowIdx}
                columnsModel={columnsModel} rowIdx={rowIdx}
                onCellChecked={self.handleCellChecked.bind(self)}
              />);
            })
          }

        {this.props.paging ? pagination : null}

    );
  }
}

export default Grid;
<commit_msg>table selection interaction<commit_after>import classNames from 'classnames';
import React, { Component, PropTypes } from 'react';
import elementType from 'react-prop-types/lib/elementType';

import { Table, Pagination, /* Checkbox */ } from 'react-bootstrap';

import GridRow from './GridRow';

/**
 * Grid组件
 *
 * Options: https://datatables.net/reference/option/
 *
 * http://adazzle.github.io/react-data-grid
 *
 */

class Grid extends Component {

  static propTypes = {
    /**
     * 表格填充数据

     * `type: boolean`，数据类型是
     * boolean literal或者是
     * Boolean类型
     * （注意和Boolean全局对象区分）

     * `type: ref`，参照的值比较特殊，是一个object:
     *
zuzhi: {
     *   id: '22EA0EB9-FABA-4224-B290-5D041A1DF773',
     *   code: '0403',
     *   name: '委外部'
     * }

     */
    tableData: PropTypes.array.isRequired,
    /**
     * 表格模型，表头每一列的名称和类型

     * 可以通过hidden来隐藏列，只有当hidden===true的时候隐藏
     */
    columnsModel: PropTypes.array.isRequired,
    /**
     * 分页
     */
    onPagination: PropTypes.func,
    /**
     * 是否启用行选择，复选框/单选框

     * 默认为null，不显示
     *
{
     *   mode: 'checkbox',
     *   onSelect: (rowIdx, rowObj, isSelected, event) => {},
     *   onSelectAll: (tableData, isSelected, event) => {}
     * }

     * mode，checkbox复选，radio单选

     * onSelect，当选择单行的时候触发，参数：
     *

     *
rowIdx
行index
     *
rowObj
行数据
     *
isSelected
复选框/单选框选中状态true/false
     *
event
Event对象
     *

     * onSelectAll，当选择所有行的时候触发，参数：
     *

     *
tableData
所有行的数据
     *
isSelected
复选框/单选框选中状态true/false
     *
event
Event对象
     *

     */
    selectRow: PropTypes.object,

    /**
     * 每一行是否显示操作按钮列

     * 默认的操作按钮在最右侧的列中，如果需要指定在左侧，可以通过
     * align参数来设置

     *
{
     *   align: 'left'
     * }

     * 注意：当操作列和选择列同时存在的时候，选择列会显示在操作列的左侧
     */
    operationColumn: PropTypes.object,
    /**
     * 自定义的操作列组件

     * 除非指定了operationColumn参数，否则操作列不会显示出来
     */
    operationColumnClass: elementType,

    /**
     * 选择一个单元格
     */
    onCellChecked: PropTypes.func,
    /**
     * 是否显示分页
     */
    paging: PropTypes.bool,
    /**
     * 页面数量
     */
    totalPage: PropTypes.number,
    /**
     * 当前页面号
     */
    activePage: PropTypes.number
  };

  static defaultProps = {
    selectRow: null,
    operationColumn: null, // 默认不显示操作列
    operationColumnClass: 'td', // 默认的操作列必须是组件
    paging: false
  };

  constructor(props) {
    super(props);
    this.state = {
      /**
       * 存储所有行被选中的状态，通过key:value
       * 其中key就是row index，从0开始
       * 注意主结构为Object而不是Array
       * {
       *   0: { selected: true  }, 第一行被选中
       *   1: { selected: false }  第二行未被选中
       * }
       */
      selectedRowsObj: {},
      /**
       * 表头行（全选）被选中状态
       */
      isHeadRowSelected: false
    };

    // 初始化的时候所有行都未被选中
    this.props.tableData.forEach((item, index) => {
      this.state.selectedRowsObj[index] = {
        selected: false
      };
    });

    // TODO 使用flags和bitmasks来存储行被选中的状态，可以降低操作状态的难度
    // 初始化0，相当于00000（对于5行来说）
    this.state.selectedFlags = 0;
  }

  handlePagination(eventKey) {
    if (this.props.onPagination) {
      this.props.onPagination(eventKey);
    }
  }

  // 同时更新所有行被选中的状态
  updateAllRowsSelectedState(isSelected) {
    const { tableData } = this.props;
    const selectedRowsObj = {};
    tableData.forEach((item, index) => {
      selectedRowsObj[index] = {
        selected: isSelected
      };
    });
    this.setState({
      selectedRowsObj
    });
  }

  // 选中一行
  // 1. 改变当前行被选中的状态
  // 2. (可能)改变表头行（全选）状态
  handleSelect(rowIdx, rowObj, isSelected, event) {
    const { selectRow, selectedRowsObj } = this.state;
    selectedRowsObj[rowIdx] = {
      selected: isSelected
    };
    this.setState({
      selectedRowsObj
    });

    /**
     * 检查当前状态中是否所有行都被选中
     * @return {boolean} 如果是true说明所有行都被选中，否则有一行或者多行未被选中。
     */
    function isAllRowsSelected(obj) {
      let ret = true;
      let i;
      for (i in obj) {
        if (obj.hasOwnProperty(i)) {
          ret = ret && obj[i].selected;
        }
      }
      return ret;
    }

    this.setState({
      isHeadRowSelected: isAllRowsSelected(selectedRowsObj)
    });

    if (selectRow && selectRow.onSelect) {
      selectRow.onSelect(rowIdx, rowObj, isSelected, event);
    }
  }

  // 当选中所有行的时候
  // 1. 同时改变所有行的选中状态
  // 2. 改变表头行（全选）状态
  handleSelectAll(event) {
    const { selectRow, tableData } = this.props;
    const isSelected = event.target.checked;

    // 在状态中选中所有行
    this.updateAllRowsSelectedState(isSelected);

    // 在状态中选中table head row
    this.setState({
      isHeadRowSelected: isSelected
    });

    if (selectRow && selectRow.onSelectAll) {
      selectRow.onSelectAll(tableData, isSelected, event);
    }
  }

  handleCellChecked(rowIdx, colIdx) {
    if (this.props.onCellChecked) {
      this.props.onCellChecked(rowIdx, colIdx);
    }
  }

  render() {
    const { columnsModel, tableData,
      selectRow, operationColumn, className,
      operationColumnClass: CustomComponent
    } = this.props;

    const { selectedRowsObj } = this.state;

    // 列模型不能为空，但是表体数据可以为空。
    // 当全部为空，只显示一个空div
    // 当只有表体数据为空，只显示表头
    if (!columnsModel || columnsModel.length === 0) {
      return (

);
    }

    const renderTableHeader = () => (
      columnsModel.map((col, key) => {
        // 使用Bootstrap的alignment class来进行对齐
        let alignClass = col.align ? `text-${col.align}` : '';
        // 之前的className只能设定th的class，现在改成使用columnClassName
        // 可以设定th和td的class
        // 由于新旧接口共存，所以需要根据优先级设定好
        const th = (
          {col.label}
        );
        return col.hidden === true ? null : th;
      })
    );

    const renderCheckboxHeader = () => (
      selectRow ? (
        <input type="checkbox" checked={this.state.isHeadRowSelected}
          onChange={this.handleSelectAll.bind(this)} />
      	) : null
    );

    const pagination = (
      <Pagination className="pagination"
        prev
        next
        first
        last
        ellipsis
        items={this.props.totalPage}
        maxButtons={10}
        activePage={this.props.activePage}
        onSelect={this.handlePagination.bind(this)}
      />
    );

    const self = this;

    // var onRow = this.props.onRow;
    return (

              { renderCheckboxHeader() }
              { renderTableHeader() }
              { operationColumn ? 操作	 : null }

          {
            tableData.map((row, rowIdx) => {
              let selected = false;

              // 该行是否被选中
              if (selectedRowsObj[rowIdx] && selectedRowsObj[rowIdx].selected) {
                selected = true;
              }

              return (<GridRow
                selectRow={selectRow}
                selectionMode={selectRow ? selectRow.mode : null}
                onSelect={selectRow ? self.handleSelect.bind(self) : null}
                selected={selected}
                operationColumn={operationColumn}
                operationColumnClass={CustomComponent}
                rowObj={row} key={rowIdx}
                columnsModel={columnsModel} rowIdx={rowIdx}
                onCellChecked={self.handleCellChecked.bind(self)}
              />);
            })
          }

        {this.props.paging ? pagination : null}

    );
  }
}

export default Grid;
<|endoftext|>


<commit_before>(function($){
    $(function(){

        $('.modal-trigger').leanModal({
            complete: function() { window.location.href = './index.html'; }
        });

        $('.button-collapse').sideNav();
        $('button#form-submit').addClass('disabled').prop('disabled', true);
        $('input').change(
            function() {
                if (all_filled())
                    $('button').removeClass('disabled').prop('disabled', false);
                else
                    $('button').addClass('disabled').prop('disabled', true);
            }
        );
        $('#the_form').submit(
            function(event) {
                event.preventDefault();
                $('button').addClass('disabled').prop('disabled', true);
                $('button').html('Please, wait...');
                $.post('https://apaservices.waltermoreira.net/insert',
                       {
                           name: $('#name').val(),
                           email: $('#email').val(),
                           interests: $('div#interests input:checked ~ label').map(clean).get().join(", "),
                           "lives_with": $('div#lives_with input:checked ~ label').map(clean).get().join(", "),
                           lifestyle: $('input[name="lifestyle"]:checked').val(),
                           fostering: $('input[name="fostering"]:checked').val(),
                           _token: "apasaveslives"
                       })
                    .done(function(data) {
                        $('#trigger').click();
                        setTimeout(function() {
                            $('#modal-dismiss').click();
                        }, 5000) })
                    .fail(function(data) {
                        alert("error: "+JSON.stringify(data)); });
            }
        );

    }); // end of document ready
})(jQuery); // end of jQuery name space

function all_filled() {
    var filled = true;
    $('input[id="name"], input[id="email"]').each(
        function() {
            if ($(this).val() == '')
                filled = false;
        }
    );
    var fostering = false;
    $('input[name="fostering"]:checked').each(
        function() {
            fostering = true;
        }
    );
    var lifestyle = false;
    $('input[name="lifestyle"]:checked').each(
        function() {
            lifestyle = true;
        }
    );
    return filled && fostering && lifestyle;
}

function clean() {
    return $(this).html().replace(/\s+/g, ' ').trim();
}

<commit_msg>Dismiss keyboard on "enter" key<commit_after>(function($){
    $(function(){

        $('.modal-trigger').leanModal({
            complete: function() { window.location.href = './index.html'; }
        });

        $('.button-collapse').sideNav();
        $('button#form-submit').addClass('disabled').prop('disabled', true);
        $('input').change(
            function() {
                if (all_filled())
                    $('button').removeClass('disabled').prop('disabled', false);
                else
                    $('button').addClass('disabled').prop('disabled', true);
            }
        );
        $('#the_form').submit(
            function(event) {
                event.preventDefault();
                $('button').addClass('disabled').prop('disabled', true);
                $('button').html('Please, wait...');
                $.post('https://apaservices.waltermoreira.net/insert',
                       {
                           name: $('#name').val(),
                           email: $('#email').val(),
                           interests: $('div#interests input:checked ~ label').map(clean).get().join(", "),
                           "lives_with": $('div#lives_with input:checked ~ label').map(clean).get().join(", "),
                           lifestyle: $('input[name="lifestyle"]:checked').val(),
                           fostering: $('input[name="fostering"]:checked').val(),
                           _token: "apasaveslives"
                       })
                    .done(function(data) {
                        $('#trigger').click();
                        setTimeout(function() {
                            $('#modal-dismiss').click();
                        }, 5000) })
                    .fail(function(data) {
                        alert("error: "+JSON.stringify(data)); });
            }
        );

        $("#name, #email").keyup(function (e) {
            if (e.keyCode == 13) {
                $(this).blur();
            }
        });

    }); // end of document ready
})(jQuery); // end of jQuery name space

function all_filled() {
    var filled = true;
    $('input[id="name"], input[id="email"]').each(
        function() {
            if ($(this).val() == '')
                filled = false;
        }
    );
    var fostering = false;
    $('input[name="fostering"]:checked').each(
        function() {
            fostering = true;
        }
    );
    var lifestyle = false;
    $('input[name="lifestyle"]:checked').each(
        function() {
            lifestyle = true;
        }
    );
    return filled && fostering && lifestyle;
}

function clean() {
    return $(this).html().replace(/\s+/g, ' ').trim();
}

<|endoftext|>


<commit_before>/*
 * Copyright 2015 University of Southern California
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var ERMrest = (function (module) {

    /**
     * Mapping from convenience method name to its config argument index.
     * @private
     * @type {Object}
     */
    var _method_to_config_idx = {
        get: 1,
        delete: 1,
        head: 1,
        jsonp: 1,
        post: 2,
        put: 2,
        patch: 2
    };

    /**
     * Retriable error codes. These can sometimes indicate transient errors
     * that can be resolved simply by retrying the request, up to a limit.
     * @private
     * @type {Array<Number>}
     */
    var _retriable_error_codes = [0, 500, 503];

    /**
     * Default maximum allowable retries. This can be overridden by setting
     * the `max_retries` property on the wrapped http object.
     * @private
     * @type {Number}
     */
    var _default_max_retries = 10;

    /**
     * Initial timeout delay. This dely will be doubled each time to perform
     * an exponential backoff retry protocol. Units in mililiseconds. This
     * can be overridden by setting the `initial_dely` property on the wrapped
     * http object.
     * @private
     * @type {Number}
     */
    var _initial_delay = 100;

    /**
     * This is an experimental function for wrapping an http service.
     * @memberof ERMrest
     * @function
     * @private
     */
    module._wrap_http = function(http) {

        // wrapping function
        function wrap(method, fn, scope) {
            scope = scope || window;
            var cfg_idx = _method_to_config_idx[method];
            return function() {
                // if no default params, then just call the fn
                var args;
                if (this.params) {
                    // not allowed to alter 'arguments' so you must make a shallow
                    // copy. it is also an 'array-like' object but not an actual
                    // array, therefore arguments.slice() does not work.
                    args = [];
                    for (var i=0, len=arguments.length; i<len; i++) {
                        args[i] = arguments[i];
                    }

                    // make sure arguments has a config, and config has a params
                    args[cfg_idx] = args[cfg_idx] || {};
                    args[cfg_idx].params = args[cfg_idx].params || {};

                    // now add default params iff they do not collide
                    for (var key in this.params) {
                        if (!(key in args[cfg_idx].params)) {
                            args[cfg_idx].params[key] = this.params[key];
                        }
                    }
                }
                else {
                    args = arguments;
                }

                // now call the fn, with retry logic
                var deferred = module._q.defer();
                var max_retries = this.max_retries || _default_max_retries;
                var delay = this.initial_delay || _initial_delay;
                var count = 0;
                function asyncfn() {
                    fn.apply(scope, args).then(function(response) {
                        deferred.resolve(response);
                    },
                    function(error) {
                        if (error.status in _retriable_error_codes && count < max_retries) {
                            count += 1;
                            console.log("[debug] retry count: " + count); // TODO remove this after debug
                            setTimeout(asyncfn, delay);
                            delay *= 2;
                        } else if (count && method === 'delete' && error.status === 404) {
                            /* SPECIAL CASE: "retried delete"
                             * This indicates that a 'delete' was attempted, but
                             * failed due to a transient error. It was retried
                             * at least one more time and at some point
                             * succeeded.
                             */
                            deferred.resolve(); // TODO should this return something?
                        } else {
                            deferred.reject(error);
                        }
                    });
                }
                asyncfn();
                return deferred.promise;
            }
        }

        // now wrap over the supported methods
        var wrapper = {};
        var methods = ['get', 'put', 'post', 'delete']; // TODO might as well include all of the supported convenience methods here
        for (var i=0, len=methods.length; i<len; i++) {
            wrapper[methods[i]] = wrap(methods[i], http[methods[i]], http);
        }

        return wrapper;
    }

    return module;

}(ERMrest || {}));
<commit_msg>prefix var name with '_default'<commit_after>/*
 * Copyright 2015 University of Southern California
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var ERMrest = (function (module) {

    /**
     * Mapping from convenience method name to its config argument index.
     * @private
     * @type {Object}
     */
    var _method_to_config_idx = {
        get: 1,
        delete: 1,
        head: 1,
        jsonp: 1,
        post: 2,
        put: 2,
        patch: 2
    };

    /**
     * Retriable error codes. These can sometimes indicate transient errors
     * that can be resolved simply by retrying the request, up to a limit.
     * @private
     * @type {Array<Number>}
     */
    var _retriable_error_codes = [0, 500, 503];

    /**
     * Default maximum allowable retries. This can be overridden by setting
     * the `max_retries` property on the wrapped http object.
     * @private
     * @type {Number}
     */
    var _default_max_retries = 10;

    /**
     * Initial timeout delay. This dely will be doubled each time to perform
     * an exponential backoff retry protocol. Units in mililiseconds. This
     * can be overridden by setting the `initial_dely` property on the wrapped
     * http object.
     * @private
     * @type {Number}
     */
    var _default_initial_delay = 100;

    /**
     * This is an experimental function for wrapping an http service.
     * @memberof ERMrest
     * @function
     * @private
     */
    module._wrap_http = function(http) {

        // wrapping function
        function wrap(method, fn, scope) {
            scope = scope || window;
            var cfg_idx = _method_to_config_idx[method];
            return function() {
                // if no default params, then just call the fn
                var args;
                if (this.params) {
                    // not allowed to alter 'arguments' so you must make a shallow
                    // copy. it is also an 'array-like' object but not an actual
                    // array, therefore arguments.slice() does not work.
                    args = [];
                    for (var i=0, len=arguments.length; i<len; i++) {
                        args[i] = arguments[i];
                    }

                    // make sure arguments has a config, and config has a params
                    args[cfg_idx] = args[cfg_idx] || {};
                    args[cfg_idx].params = args[cfg_idx].params || {};

                    // now add default params iff they do not collide
                    for (var key in this.params) {
                        if (!(key in args[cfg_idx].params)) {
                            args[cfg_idx].params[key] = this.params[key];
                        }
                    }
                }
                else {
                    args = arguments;
                }

                // now call the fn, with retry logic
                var deferred = module._q.defer();
                var max_retries = this.max_retries || _default_max_retries;
                var delay = this.initial_delay || _default_initial_delay;
                var count = 0;
                function asyncfn() {
                    fn.apply(scope, args).then(function(response) {
                        deferred.resolve(response);
                    },
                    function(error) {
                        if (error.status in _retriable_error_codes && count < max_retries) {
                            count += 1;
                            console.log("[debug] retry count: " + count); // TODO remove this after debug
                            setTimeout(asyncfn, delay);
                            delay *= 2;
                        } else if (count && method === 'delete' && error.status === 404) {
                            /* SPECIAL CASE: "retried delete"
                             * This indicates that a 'delete' was attempted, but
                             * failed due to a transient error. It was retried
                             * at least one more time and at some point
                             * succeeded.
                             */
                            deferred.resolve(); // TODO should this return something?
                        } else {
                            deferred.reject(error);
                        }
                    });
                }
                asyncfn();
                return deferred.promise;
            }
        }

        // now wrap over the supported methods
        var wrapper = {};
        var methods = ['get', 'put', 'post', 'delete']; // TODO might as well include all of the supported convenience methods here
        for (var i=0, len=methods.length; i<len; i++) {
            wrapper[methods[i]] = wrap(methods[i], http[methods[i]], http);
        }

        return wrapper;
    }

    return module;

}(ERMrest || {}));
<|endoftext|>


<commit_before>'use strict';

function repo_drawlogic(){
    canvas_buffer.save();

    canvas_buffer.translate(
      canvas_properties['width-half'],
      canvas_properties['height-half']
    );

    // Rotate 90 degrees each time and draw a wall.
    let loop_counter = 3;
    do{
        canvas_buffer.rotate(rotate_math);

        canvas_draw_path({
          'vertices': [
            {
              'type': 'moveTo',
            },
            {
              'x': canvas_properties['width'],
              'y': canvas_properties['width'],
            },
            {
              'x': -canvas_properties['width'],
              'y': canvas_properties['width'],
            },
          ],
        });
    }while(loop_counter--);

    canvas_buffer.restore();
}

function repo_init(){
    core_repo_init({
      'globals': {
        'rotate_math': math_degrees_to_radians({
          'degrees': 90,
        }),
      },
      'title': 'Hallway-2D3D.htm',
    });
    canvas_init();
}

function repo_resizelogic(){
    canvas_setproperties({
      'properties': {
        'fillStyle': canvas_gradient({
          'height': canvas_properties['height'],
          'stops': [
            {},
            {
              'color': '#a99',
              'offset': 1,
            },
          ],
          'y': canvas_properties['height'] / 20,
        }),
      },
    });
}
<commit_msg>removed unnecessary comments<commit_after>'use strict';

function repo_drawlogic(){
    canvas_buffer.save();

    canvas_buffer.translate(
      canvas_properties['width-half'],
      canvas_properties['height-half']
    );

    let loop_counter = 3;
    do{
        canvas_buffer.rotate(rotate_math);

        canvas_draw_path({
          'vertices': [
            {
              'type': 'moveTo',
            },
            {
              'x': canvas_properties['width'],
              'y': canvas_properties['width'],
            },
            {
              'x': -canvas_properties['width'],
              'y': canvas_properties['width'],
            },
          ],
        });
    }while(loop_counter--);

    canvas_buffer.restore();
}

function repo_init(){
    core_repo_init({
      'globals': {
        'rotate_math': math_degrees_to_radians({
          'degrees': 90,
        }),
      },
      'title': 'Hallway-2D3D.htm',
    });
    canvas_init();
}

function repo_resizelogic(){
    canvas_setproperties({
      'properties': {
        'fillStyle': canvas_gradient({
          'height': canvas_properties['height'],
          'stops': [
            {},
            {
              'color': '#a99',
              'offset': 1,
            },
          ],
          'y': canvas_properties['height'] / 20,
        }),
      },
    });
}
<|endoftext|>


<commit_before>/*
 * jQuery File Upload Plugin JS Example 8.9.0
 * https://github.com/blueimp/jQuery-File-Upload
 *
 * Copyright 2010, Sebastian Tschan
 * https://blueimp.net
 *
 * Licensed under the MIT license:
 * http://www.opensource.org/licenses/MIT
 */

/* global $, window */

$(function () {
    'use strict';

    // Initialize the jQuery File Upload widget:
    $('#fileupload').fileupload({
        disableImageResize: false,
        // Uncomment the following to send cross-domain cookies:
        //xhrFields: {withCredentials: true},
        url: 'server/php/'
    });

    // Enable iframe cross-domain access via redirect option:
    $('#fileupload').fileupload(
        'option',
        'redirect',
        window.location.href.replace(
            /\/[^\/]*$/,
            '/cors/result.html?%s'
        )
    );

    if (window.location.hostname === 'blueimp.github.io') {
        // Demo settings:
        $('#fileupload').fileupload('option', {
            url: '//jquery-file-upload.appspot.com/',
            // Enable image resizing, except for Android and Opera,
            // which actually support image resizing, but fail to
            // send Blob objects via XHR requests:
            disableImageResize: /Android(?!.*Chrome)|Opera/
                .test(window.navigator.userAgent),
            maxFileSize: 5000000,
            acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i
        });
        // Upload server status check for browsers with CORS support:
        if ($.support.cors) {
            $.ajax({
                url: '//jquery-file-upload.appspot.com/',
                type: 'HEAD'
            }).fail(function () {
                $('
')
                    .text('Upload server currently unavailable - ' +
                            new Date())
                    .appendTo('#fileupload');
            });
        }
    } else {
        // Load existing files:
        $('#fileupload').addClass('fileupload-processing');
        $.ajax({
            // Uncomment the following to send cross-domain cookies:
            //xhrFields: {withCredentials: true},
            url: $('#fileupload').fileupload('option', 'url'),
            dataType: 'json',
            context: $('#fileupload')[0]
        }).always(function () {
            $(this).removeClass('fileupload-processing');
        }).done(function (result) {
            $(this).fileupload('option', 'done')
                .call(this, $.Event('done'), {result: result});
        });
    }

});
<commit_msg>Do not enable client-side image resizing by default.<commit_after>/*
 * jQuery File Upload Plugin JS Example 8.9.1
 * https://github.com/blueimp/jQuery-File-Upload
 *
 * Copyright 2010, Sebastian Tschan
 * https://blueimp.net
 *
 * Licensed under the MIT license:
 * http://www.opensource.org/licenses/MIT
 */

/* global $, window */

$(function () {
    'use strict';

    // Initialize the jQuery File Upload widget:
    $('#fileupload').fileupload({
        // Uncomment the following to send cross-domain cookies:
        //xhrFields: {withCredentials: true},
        url: 'server/php/'
    });

    // Enable iframe cross-domain access via redirect option:
    $('#fileupload').fileupload(
        'option',
        'redirect',
        window.location.href.replace(
            /\/[^\/]*$/,
            '/cors/result.html?%s'
        )
    );

    if (window.location.hostname === 'blueimp.github.io') {
        // Demo settings:
        $('#fileupload').fileupload('option', {
            url: '//jquery-file-upload.appspot.com/',
            // Enable image resizing, except for Android and Opera,
            // which actually support image resizing, but fail to
            // send Blob objects via XHR requests:
            disableImageResize: /Android(?!.*Chrome)|Opera/
                .test(window.navigator.userAgent),
            maxFileSize: 5000000,
            acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i
        });
        // Upload server status check for browsers with CORS support:
        if ($.support.cors) {
            $.ajax({
                url: '//jquery-file-upload.appspot.com/',
                type: 'HEAD'
            }).fail(function () {
                $('
')
                    .text('Upload server currently unavailable - ' +
                            new Date())
                    .appendTo('#fileupload');
            });
        }
    } else {
        // Load existing files:
        $('#fileupload').addClass('fileupload-processing');
        $.ajax({
            // Uncomment the following to send cross-domain cookies:
            //xhrFields: {withCredentials: true},
            url: $('#fileupload').fileupload('option', 'url'),
            dataType: 'json',
            context: $('#fileupload')[0]
        }).always(function () {
            $(this).removeClass('fileupload-processing');
        }).done(function (result) {
            $(this).fileupload('option', 'done')
                .call(this, $.Event('done'), {result: result});
        });
    }

});
<|endoftext|>


<commit_before>$(document).ready(function() {

    var url = "http://munsangdong.cafe24.com/api/card";
    var callApi = function( url, successFn ) {
        $.ajax({
            type : 'GET',
            url : url,
            dataType : "json",
            success : successFn
        });
    };
    // callApi( url + window.location.search, response_json );

    // #ID를 달고 브라우저를 직접 접속했을 때, hash를 ?id= 로 리다이렉트 시키는 것이 필요함.
    if( window.location.hash !== "" ) {
      var URLis = "?id=" + window.location.hash.substr(1);
    //   // window.location.hash = "";
      callApi( url + URLis, response_id );
    //   console.log(window.location.search);
    //
    } else {
      callApi( url + window.location.search, response_json );
    }

    // 카드를 누르면 카드가 확대된다.
    $("body").on("click", ".activator", function ( e ){
      window.location.hash = $(this).parents('div[id]').attr('id');
      console.log(window.location.hash);
      $(this).parents(".grid-item").removeClass("grid-item s12 m12 l3").addClass(".grid expanded s12 m12 l12");

      // 클릭시 비디오가 플레이 된다.
      // 모바일에서는 지극히 느려져서.. 삭제
        // var $play = $(this).parents('.card').children('div.card-reveal').children('video').get(0);
        // $play.play();

      $('.grid').isotope();
    });

    // 닫기를 누르면 카드가 다시 작아진다.
    $( "body" ).on( "click", "div.card-reveal > span", function( e )  {
      $(this).parents(".expanded").removeClass(".grid expanded s12 m12 l12").addClass("grid-item s12 m12 l3");

      //비디오는 플레이가 중지된다.
        var $pause = $(this).parents('.card-reveal').children('video').get(0);
        $pause.pause();

      $('.grid').isotope();
    });

    // 공유 버튼을 누르면 모달 팝업이 뜬다.
    $("body").on ("click", "i.sharing", function(e){
      var sharing = $(this).attr("data-id");
      console.log(sharing);
      $('#modal1').openModal();

    });

    function response_json(json) {
      console.log(json);
        var video_list = json.content;
        video_list.forEach(function(v, i) {
            var item = v;
            // 카드를 구성한다
            var card = "
" +
                "
" +
                    "
" +
                            "" +
                            "" + item.category + "play_circle_filled" +
                    "
" +
                    "
" +
                        " " + item.name + "" +
                            "
" + item.description + "
" +
                    "
" +
                    "
" + item.category + "closeshare" +
                        "<video controls loop preload='auto' poster='" + item.picture + "' src='" + item.source + "' width='100%' >" +
                        "</video>" +
                        "

" +
                            "" + item.name + "" +
                            "
updated: " + item.updated_time + "
" +
                                "created: " + item.created_time + "

" +
                    "
" +
                  "
" ;

            //카드를 화면에 표시한다.
            // $('.grid').isotope().append(card);
            $("#FeviCard").append(card);
        });

        // 더보기 버튼 추가하기
        var addMore = "
" +
          "
" +
            "
playlist_add
" +
          "
"+
        "
";
        $("#FeviCard").append(addMore);

        //page 및 각종 앨리먼트 정보를 표시한다.
        $("#video_list > ul >li").eq(0).text(
          "총 동영상수: " + json.totalElements
        );
        $("#video_list > ul >li").eq(2).text(
          "총 페이지 수: " + json.totalPages
        );
        $("#video_list > ul >li").eq(1).text(
          "현재 페이지의 카드 수: " + json.size
        );
        $("#video_list > ul >li").eq(3).text(
          "현재 페이지 번호: " + json.number
        );

        $('.grid').isotope({
                itemSelector : '.grid-item',
                masonry : {
                    columnWidth : 50,
                    gutter : 10
                }
            });

        $('.grid').imagesLoaded().done(function() {
            $('.grid').isotope();
        });

    };

    function response_id (json) {
        var video_list = json.content;
        video_list.forEach(function(v, i) {
            var item = v;
            // 카드를 구성한다
            var card = "
" +
                "
" +
                    "
" +
                            "" +
                            "" + item.category + "play_circle_filled" +
                    "
" +
                    "
" +
                        " " + item.name + "" +
                            "
" + item.description + "
" +
                    "
" +
                    "
" + item.category + "closeshare" +
                        "<video controls loop preload='auto' poster='" + item.picture + "' src='" + item.source + "' width='100%' >" +
                        "</video>" +
                        "

" +
                            "" + item.name + "" +
                            "
updated: " + item.updated_time + "
" +
                                "created: " + item.created_time + "

" +
                    "
" +
                  "
" ;

            //카드를 화면에 표시한다.
            // $('.grid').isotope().append(card);
            $("#FeviCard").append(card);

            // ID 별로 파라메터를 따로 설정을 한다.
            var virtualPvByParam =  "index.html?id=" + item.id;
            ga('send', 'pageview', 'virtualPvByParam');
        });
      }

    // google-analytics 카드 어디를 누를지 체크
    $("body").on("click", ".activator", function ( e ){
      var contentID = $(this).parents('div[id]').attr('id');
      var clickedPath = $(this).attr('alt');
      console.log(contentID, clickedPath);

      ga('send', 'event', "card-reveal", clickedPath, contentID  );
      });

    // 카드를 눌렀을 때는 해당 카드의 PV를 따로 잡는다.
    // hash를 따로 달고 날아오는 경우와 동일하게 통계를 잡는다.
    $("body").on("click", ".activator", function ( e ){
      var contentID = $(this).parents('div[id]').attr('id');
      var virtualPvByID = "/index.html?id=" + contentID;
      ga('send', 'pageview', 'virtualPvByID');
    });

    //google-analytics 비디오 플레이를 눌렀는지 체크
    $('body').on('click', '.card-reveal', function(e){
    //   var videID = $(this).parent().attr('data-id');
      console.log(this);
    });

    // 하단 fix 버튼 클릭시 움직임
    $('#scrollTop').click(function(){
      $('html, body').animate({ scrollTop: 0}, "slow");
      return false;
    });

});
<commit_msg>GA 가상페이지 코드 수정<commit_after>$(document).ready(function() {

    var url = "http://munsangdong.cafe24.com/api/card";
    var callApi = function( url, successFn ) {
        $.ajax({
            type : 'GET',
            url : url,
            dataType : "json",
            success : successFn
        });
    };
    // callApi( url + window.location.search, response_json );

    // #ID를 달고 브라우저를 직접 접속했을 때, hash를 ?id= 로 리다이렉트 시키는 것이 필요함.
    if( window.location.hash !== "" ) {
      var URLis = "?id=" + window.location.hash.substr(1);
    //   // window.location.hash = "";
      callApi( url + URLis, response_id );
    //   console.log(window.location.search);
    //
    } else {
      callApi( url + window.location.search, response_json );
    }

    // 카드를 누르면 카드가 확대된다.
    $("body").on("click", ".activator", function ( e ){
      window.location.hash = $(this).parents('div[id]').attr('id');
      $(this).parents(".grid-item").removeClass("grid-item s12 m12 l3").addClass(".grid expanded s12 m12 l12");

      // 클릭시 비디오가 플레이 된다.
      // 모바일에서는 지극히 느려져서.. 삭제
        // var $play = $(this).parents('.card').children('div.card-reveal').children('video').get(0);
        // $play.play();

      $('.grid').isotope();
    });

    // 닫기를 누르면 카드가 다시 작아진다.
    $( "body" ).on( "click", "div.card-reveal > span", function( e )  {
      $(this).parents(".expanded").removeClass(".grid expanded s12 m12 l12").addClass("grid-item s12 m12 l3");

      //비디오는 플레이가 중지된다.
        var $pause = $(this).parents('.card-reveal').children('video').get(0);
        $pause.pause();

      $('.grid').isotope();
    });

    // 공유 버튼을 누르면 모달 팝업이 뜬다.
    $("body").on ("click", "i.sharing", function(e){
      var sharing = $(this).attr("data-id");
      $('#modal1').openModal();

    });

    function response_json(json) {
      console.log(json);
        var video_list = json.content;
        video_list.forEach(function(v, i) {
            var item = v;
            // 카드를 구성한다
            var card = "
" +
                "
" +
                    "
" +
                            "" +
                            "" + item.category + "play_circle_filled" +
                    "
" +
                    "
" +
                        " " + item.name + "" +
                            "
" + item.description + "
" +
                    "
" +
                    "
" + item.category + "closeshare" +
                        "<video controls loop preload='auto' poster='" + item.picture + "' src='" + item.source + "' width='100%' >" +
                        "</video>" +
                        "

" +
                            "" + item.name + "" +
                            "
updated: " + item.updated_time + "
" +
                                "created: " + item.created_time + "

" +
                    "
" +
                  "
" ;

            //카드를 화면에 표시한다.
            // $('.grid').isotope().append(card);
            $("#FeviCard").append(card);
        });

        // 더보기 버튼 추가하기
        var addMore = "
" +
          "
" +
            "
playlist_add
" +
          "
"+
        "
";
        $("#FeviCard").append(addMore);

        //page 및 각종 앨리먼트 정보를 표시한다.
        $("#video_list > ul >li").eq(0).text(
          "총 동영상수: " + json.totalElements
        );
        $("#video_list > ul >li").eq(2).text(
          "총 페이지 수: " + json.totalPages
        );
        $("#video_list > ul >li").eq(1).text(
          "현재 페이지의 카드 수: " + json.size
        );
        $("#video_list > ul >li").eq(3).text(
          "현재 페이지 번호: " + json.number
        );

        $('.grid').isotope({
                itemSelector : '.grid-item',
                masonry : {
                    columnWidth : 50,
                    gutter : 10
                }
            });

        $('.grid').imagesLoaded().done(function() {
            $('.grid').isotope();
        });

    };

    function response_id (json) {
        var video_list = json.content;
        video_list.forEach(function(v, i) {
            var item = v;
            // 카드를 구성한다
            var card = "
" +
                "
" +
                    "
" +
                            "" +
                            "" + item.category + "play_circle_filled" +
                    "
" +
                    "
" +
                        " " + item.name + "" +
                            "
" + item.description + "
" +
                    "
" +
                    "
" + item.category + "closeshare" +
                        "<video controls loop preload='auto' poster='" + item.picture + "' src='" + item.source + "' width='100%' >" +
                        "</video>" +
                        "

" +
                            "" + item.name + "" +
                            "
updated: " + item.updated_time + "
" +
                                "created: " + item.created_time + "

" +
                    "
" +
                  "
" ;

            //카드를 화면에 표시한다.
            // $('.grid').isotope().append(card);
            $("#FeviCard").append(card);

            // ID 별로 파라메터를 따로 설정을 한다.
            var virtualPvByParam =  "index.html?id=" + item.id;
            ga('send', 'pageview', virtualPvByParam);
        });
      }

    // google-analytics 카드 어디를 누를지 체크
    $("body").on("click", ".activator", function ( e ){
      var contentID = $(this).parents('div[id]').attr('id');
      var clickedPath = $(this).attr('alt');
      ga('send', 'event', "card-reveal", clickedPath, contentID  );
      });

    // 카드를 눌렀을 때는 해당 카드의 PV를 따로 잡는다.
    // hash를 따로 달고 날아오는 경우와 동일하게 통계를 잡는다.
    $("body").on("click", ".activator", function ( e ){
      var contentID = $(this).parents('div[id]').attr('id');
      var virtualPvByID = "/index.html?id=" + contentID;
      console.log(virtualPvByID);
      ga('send', 'pageview', virtualPvByID);
    });

    //google-analytics 비디오 플레이를 눌렀는지 체크
    $('body').on('click', '.card-reveal', function(e){
    //   var videID = $(this).parent().attr('data-id');
      // console.log(this);
    });

    // 하단 fix 버튼 클릭시 움직임
    $('#scrollTop').click(function(){
      $('html, body').animate({ scrollTop: 0}, "slow");
      return false;
    });

});
<|endoftext|>


<commit_before>'use strict';

var array = [].constructor;

/**
 * @workInProgress
 * @ngdoc function
 * @name angular.toJson
 * @function
 *
 * @description
 * Serializes the input into a JSON formated string.
 *
 * @param {Object|Array|Date|string|number} obj Input to jsonify.
 * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.
 * @returns {string} Jsonified string representing `obj`.
 */
function toJson(obj, pretty) {
  var buf = [];
  toJsonArray(buf, obj, pretty ? "\n  " : null, []);
  return buf.join('');
}

/**
 * @workInProgress
 * @ngdoc function
 * @name angular.fromJson
 * @function
 *
 * @description
 * Deserializes a string in the JSON format.
 *
 * @param {string} json JSON string to deserialize.
 * @param {boolean} [useNative=false] Use native JSON parser if available
 * @returns {Object|Array|Date|string|number} Deserialized thingy.
 */
function fromJson(json, useNative) {
  if (!isString(json)) return json;

  var obj;

  try {
    if (useNative && window.JSON && window.JSON.parse) {
      obj = JSON.parse(json);
      return transformDates(obj);
    }
    return parser(json, true).primary()();
  } catch (e) {
    error("fromJson error: ", json, e);
    throw e;
  }

  // TODO make forEach optionally recursive and remove this function
  function transformDates(obj) {
    if (isString(obj) && obj.length === DATE_ISOSTRING_LN) {
      return angularString.toDate(obj);
    } else if (isArray(obj) || isObject(obj)) {
      forEach(obj, function(val, name) {
        obj[name] = transformDates(val);
      });
    }
    return obj;
  }
}

angular.toJson = toJson;
angular.fromJson = fromJson;

function toJsonArray(buf, obj, pretty, stack) {
  if (isObject(obj)) {
    if (obj === window) {
      buf.push('WINDOW');
      return;
    }

    if (obj === document) {
      buf.push('DOCUMENT');
      return;
    }

    if (includes(stack, obj)) {
      buf.push('RECURSION');
      return;
    }
    stack.push(obj);
  }
  if (obj === null) {
    buf.push($null);
  } else if (obj instanceof RegExp) {
    buf.push(angular.String.quoteUnicode(obj.toString()));
  } else if (isFunction(obj)) {
    return;
  } else if (isBoolean(obj)) {
    buf.push('' + obj);
  } else if (isNumber(obj)) {
    if (isNaN(obj)) {
      buf.push($null);
    } else {
      buf.push('' + obj);
    }
  } else if (isString(obj)) {
    return buf.push(angular.String.quoteUnicode(obj));
  } else if (isObject(obj)) {
    if (isArray(obj)) {
      buf.push("[");
      var len = obj.length;
      var sep = false;
      for(var i=0; i<len; i++) {
        var item = obj[i];
        if (sep) buf.push(",");
        if (!(item instanceof RegExp) && (isFunction(item) || isUndefined(item))) {
          buf.push($null);
        } else {
          toJsonArray(buf, item, pretty, stack);
        }
        sep = true;
      }
      buf.push("]");
    } else if (isElement(obj)) {
      // TODO(misko): maybe in dev mode have a better error reporting?
      buf.push('DOM_ELEMENT');
    } else if (isDate(obj)) {
      buf.push(angular.String.quoteUnicode(angular.Date.toString(obj)));
    } else {
      buf.push("{");
      if (pretty) buf.push(pretty);
      var comma = false;
      var childPretty = pretty ? pretty + "  " : false;
      var keys = [];
      for(var k in obj) {
        if (obj.hasOwnProperty(k) && obj[k] !== undefined) {
          keys.push(k);
        }
      }
      keys.sort();
      for ( var keyIndex = 0; keyIndex < keys.length; keyIndex++) {
        var key = keys[keyIndex];
        var value = obj[key];
        if (!isFunction(value)) {
          if (comma) {
            buf.push(",");
            if (pretty) buf.push(pretty);
          }
          buf.push(angular.String.quote(key));
          buf.push(":");
          toJsonArray(buf, value, childPretty, stack);
          comma = true;
        }
      }
      buf.push("}");
    }
  }
  if (isObject(obj)) {
    stack.pop();
  }
}
<commit_msg>refactor(json): use angularString instead of angular.String<commit_after>'use strict';

var array = [].constructor;

/**
 * @workInProgress
 * @ngdoc function
 * @name angular.toJson
 * @function
 *
 * @description
 * Serializes the input into a JSON formated string.
 *
 * @param {Object|Array|Date|string|number} obj Input to jsonify.
 * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.
 * @returns {string} Jsonified string representing `obj`.
 */
function toJson(obj, pretty) {
  var buf = [];
  toJsonArray(buf, obj, pretty ? "\n  " : null, []);
  return buf.join('');
}

/**
 * @workInProgress
 * @ngdoc function
 * @name angular.fromJson
 * @function
 *
 * @description
 * Deserializes a string in the JSON format.
 *
 * @param {string} json JSON string to deserialize.
 * @param {boolean} [useNative=false] Use native JSON parser if available
 * @returns {Object|Array|Date|string|number} Deserialized thingy.
 */
function fromJson(json, useNative) {
  if (!isString(json)) return json;

  var obj;

  try {
    if (useNative && window.JSON && window.JSON.parse) {
      obj = JSON.parse(json);
      return transformDates(obj);
    }
    return parser(json, true).primary()();
  } catch (e) {
    error("fromJson error: ", json, e);
    throw e;
  }

  // TODO make forEach optionally recursive and remove this function
  function transformDates(obj) {
    if (isString(obj) && obj.length === DATE_ISOSTRING_LN) {
      return angularString.toDate(obj);
    } else if (isArray(obj) || isObject(obj)) {
      forEach(obj, function(val, name) {
        obj[name] = transformDates(val);
      });
    }
    return obj;
  }
}

angular.toJson = toJson;
angular.fromJson = fromJson;

function toJsonArray(buf, obj, pretty, stack) {
  if (isObject(obj)) {
    if (obj === window) {
      buf.push('WINDOW');
      return;
    }

    if (obj === document) {
      buf.push('DOCUMENT');
      return;
    }

    if (includes(stack, obj)) {
      buf.push('RECURSION');
      return;
    }
    stack.push(obj);
  }
  if (obj === null) {
    buf.push($null);
  } else if (obj instanceof RegExp) {
    buf.push(angularString.quoteUnicode(obj.toString()));
  } else if (isFunction(obj)) {
    return;
  } else if (isBoolean(obj)) {
    buf.push('' + obj);
  } else if (isNumber(obj)) {
    if (isNaN(obj)) {
      buf.push($null);
    } else {
      buf.push('' + obj);
    }
  } else if (isString(obj)) {
    return buf.push(angularString.quoteUnicode(obj));
  } else if (isObject(obj)) {
    if (isArray(obj)) {
      buf.push("[");
      var len = obj.length;
      var sep = false;
      for(var i=0; i<len; i++) {
        var item = obj[i];
        if (sep) buf.push(",");
        if (!(item instanceof RegExp) && (isFunction(item) || isUndefined(item))) {
          buf.push($null);
        } else {
          toJsonArray(buf, item, pretty, stack);
        }
        sep = true;
      }
      buf.push("]");
    } else if (isElement(obj)) {
      // TODO(misko): maybe in dev mode have a better error reporting?
      buf.push('DOM_ELEMENT');
    } else if (isDate(obj)) {
      buf.push(angularString.quoteUnicode(angular.Date.toString(obj)));
    } else {
      buf.push("{");
      if (pretty) buf.push(pretty);
      var comma = false;
      var childPretty = pretty ? pretty + "  " : false;
      var keys = [];
      for(var k in obj) {
        if (obj.hasOwnProperty(k) && obj[k] !== undefined) {
          keys.push(k);
        }
      }
      keys.sort();
      for ( var keyIndex = 0; keyIndex < keys.length; keyIndex++) {
        var key = keys[keyIndex];
        var value = obj[key];
        if (!isFunction(value)) {
          if (comma) {
            buf.push(",");
            if (pretty) buf.push(pretty);
          }
          buf.push(angularString.quote(key));
          buf.push(":");
          toJsonArray(buf, value, childPretty, stack);
          comma = true;
        }
      }
      buf.push("}");
    }
  }
  if (isObject(obj)) {
    stack.pop();
  }
}
<|endoftext|>


<commit_before>// ##########################################################################################################
// GTFS CLIENT-SIDE APPLICATION
// Created by Jon Kostyniuk on 28MAY2015
// Last modified by Jon Kostyniuk on 28MAY2015
// Property of JK Enterprises
// v0.01a
// ##########################################################################################################
//
// Version History:
// ----------------
// 28MAY2015 v0.01a - JK
//   - Initial Version.
//
// Usage:
// ------
// Describe usage.
//
// Instructions:
// -------------
// None currently.
//

// ##########################################################################################################
// DEFINITIONS
// ##########################################################################################################

// Map Variables
var $map = null;													// Google Map Variable

// GTFS Data Variables
var $AgencyData = null; 											// JSON Object for Agency Data
var $SelAgency = null;												// Selected Transit Agency ID
var $GTFS_API = "http://www.gtfs-data-exchange.com/api/agencies"	// GTFS Exchange API Data

// GUI Variables
var $diaName = null;												// Name of Dialogue Window Open

// ##########################################################################################################
// DEFINED FUNCTIONS
// ##########################################################################################################

// MODULE FUNCTIONS
// ----------------

// Function to Clear Agency
function clearAgency() {
	$SelAgency = null; // Clear Selected Agency
	$(".list-item").css("color", "#000000"); // Clear selected styles
	$(".list-item").css("background", "#ffffff"); // Clear selected styles
	$('#load-agency').prop('disabled', true); // Disable submit button
	$('#mAgency').modal('hide'); // Hide dialogue
	$diaName = null; // Clear active dialogue name
}

// Function to Initialize Google Map
function initMap() {
	// Create New Google Maps Object
	var $mapOptions = {
	    zoom: 12,
	    center: new google.maps.LatLng(43.809785, -79.454099)
		};
	$map = new google.maps.Map($('#gmap')[0], $mapOptions);
}

// Function to Load Agency
function loadAgency() {
	$(".list-item").css("color", "#000000"); // Clear selected styles
	$(".list-item").css("background", "#ffffff"); // Clear selected styles
	$('#load-agency').prop('disabled', true);
	$('#mAgency').modal('hide');
	$diaName = null;
    alert($SelAgency);
}

// Function to Load GTFS Exchange Data
function loadGTFS() {
    $("#mAgency").modal('show'); // Load dialogue window
    $diaName = "Agency"; // Set active dialogue name

	$.ajax({
	    url: $GTFS_API,
	    dataType: "jsonp",
	    success: function($data) {
	    	parseGTFS($data)
	    	//$('#agency-data').html(JSON.stringify($data));  //WORKS
	    	alert($data["status_code"]) //TEMP
	    }
	});
}

// Function to Handle List Clicks
function listClick($listID) {
	// Determine which dialogue to handle
	switch($diaName) {
	    case "Agency": // Agency Select Dialogue Window
			$SelAgency = $listID
			$('#load-agency').prop('disabled', false);
	        break;
	    // Add more cases as needed
	}

	// Clear selected styles
	$(".list-item").css("color", "#000000");
	$(".list-item").css("background", "#ffffff");

	// Add selected item style
	$("#" + $listID).css("color", "#ffffff");
	$("#" + $listID).css("background", "#0000ff");
}

// HELPER (MONKEY) FUNCTIONS
// -------------------------

// Function to Parse GTFS Data
function parseGTFS($gtfsjson) {
	var $gtfsline = "";
	//for(var $i = 0; $i < $gtfsjson["data"]; $i++) {
	//	$gtfsline += "
Junk
"
	//}
	// START HERE
	//
Junk

}

// ##########################################################################################################
// MAIN PROGRAM
// ##########################################################################################################

// When HTML Document Loaded, Add Listeners Here
$(document).ready(function() {
	// Event Handler to Load Selected Agency on Click
	$('#load-agency').on('click', function (e) {
		loadAgency();
	});

	// Event Handler to Select Agency on Click
	$('#select-agency').on('click', function (e) {
		loadGTFS();
	});
});

// Initialize Google Maps DOM on Page Load
google.maps.event.addDomListener(window, 'load', initMap());<commit_msg>Development Commit<commit_after>// ##########################################################################################################
// GTFS CLIENT-SIDE APPLICATION
// Created by Jon Kostyniuk on 28MAY2015
// Last modified by Jon Kostyniuk on 28MAY2015
// Property of JK Enterprises
// v0.01a
// ##########################################################################################################
//
// Version History:
// ----------------
// 28MAY2015 v0.01a - JK
//   - Initial Version.
//
// Usage:
// ------
// Describe usage.
//
// Instructions:
// -------------
// None currently.
//

// ##########################################################################################################
// DEFINITIONS
// ##########################################################################################################

// Map Variables
var $map = null;													// Google Map Variable

// GTFS Data Variables
var $AgencyData = null; 											// JSON Object for Agency Data
var $SelAgency = null;												// Selected Transit Agency ID
var $GTFS_API = "http://www.gtfs-data-exchange.com/api/agencies"	// GTFS Exchange API Data

// GUI Variables
var $diaName = null;												// Name of Dialogue Window Open

// ##########################################################################################################
// DEFINED FUNCTIONS
// ##########################################################################################################

// MODULE FUNCTIONS
// ----------------

// Function to Clear Agency
function clearAgency() {
	$SelAgency = null; // Clear Selected Agency
	$(".list-item").css("color", "#000000"); // Clear selected styles
	$(".list-item").css("background", "#ffffff"); // Clear selected styles
	$('#load-agency').prop('disabled', true); // Disable submit button
	$('#mAgency').modal('hide'); // Hide dialogue
	$diaName = null; // Clear active dialogue name

	return;
}

// Function to Initialize Google Map
function initMap() {
	// Create New Google Maps Object
	var $mapOptions = {
	    zoom: 12,
	    center: new google.maps.LatLng(43.809785, -79.454099)
		};
	$map = new google.maps.Map($('#gmap')[0], $mapOptions);

	return;
}

// Function to Load Agency
function loadAgency() {
	$(".list-item").css("color", "#000000"); // Clear selected styles
	$(".list-item").css("background", "#ffffff"); // Clear selected styles
	$('#load-agency').prop('disabled', true);
	$('#mAgency').modal('hide');
	$diaName = null;
    alert($SelAgency);

    return;
}

// Function to Load GTFS Exchange Data
function loadGTFS() {
    $("#mAgency").modal('show'); // Load dialogue window
    $diaName = "Agency"; // Set active dialogue name

	$.ajax({
	    url: $GTFS_API,
	    dataType: "jsonp",
	    success: function($data) {
	    	parseGTFS($data);
	    	//$('#agency-data').html(JSON.stringify($data));  //WORKS
	    	//alert($data["status_code"]); //TEMP
	    }
	});

	return;
}

// Function to Handle List Clicks
function listClick($listID) {
	// Determine which dialogue to handle
	switch($diaName) {
	    case "Agency": // Agency Select Dialogue Window
			$SelAgency = $listID
			$('#load-agency').prop('disabled', false);
	        break;
	    // Add more cases as needed
	}

	// Clear selected styles
	$(".list-item").css("color", "#000000");
	$(".list-item").css("background", "#ffffff");

	// Add selected item style
	$("#" + $listID).css("color", "#ffffff");
	$("#" + $listID).css("background", "#0000ff");

	return;
}

// HELPER (MONKEY) FUNCTIONS
// -------------------------

// Function to Parse GTFS Data
function parseGTFS($gtfsjson) {
	var $gtfsline = "";
	for(var $i = 0; $i < $gtfsjson["data"].length; $i++) {
		// Check if official feed
		if($gtfsjson["data"][$i]["is_official"] == true) {
			$isOfficial = "";
		}
		else {
			$isOfficial = "";
		}
		// Construct GTFS List
		$gtfsline += "
" + $isOfficial + " " + $gtfsjson["data"][$i]["name"];
		$gtfsline += "
";
	}
	return $("#agency-data").html($gtfsline);
}

// ##########################################################################################################
// MAIN PROGRAM
// ##########################################################################################################

// When HTML Document Loaded, Add Listeners Here
$(document).ready(function() {
	// Event Handler to Load Selected Agency on Click
	$('#load-agency').on('click', function (e) {
		loadAgency();
	});

	// Event Handler to Select Agency on Click
	$('#select-agency').on('click', function (e) {
		loadGTFS();
	});
});

// Initialize Google Maps DOM on Page Load
google.maps.event.addDomListener(window, 'load', initMap());<|endoftext|>