<commit_before>(function (exports) {

  var keys = {
    CONTEXT: '@context',
    ID: '@id',
    TYPE: '@type',
    VALUE: '@value',
    LANG: '@language',
    LIST: "@list",
    GRAPH: "@graph"
  };

  var RDF_TYPE = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type";

  function Graph(mappings) {
    this.resolver = new Resolver(mappings);
    this.idMap = {};
  }
  Graph.prototype = {

    get: function (termOrCURIEorIRI) {
      return this.idMap[this.resolver.resolve(termOrCURIEorIRI)];
    },

    all: function () {
      var result = [], map = this.idMap;
      for (var id in map) {
        result.push(map[id]);
      }
      return result;
    },

    allByType: function (/*types...*/) {
      var result = [];
      for (var cls=null, i=0; cls=arguments[i++];) {
        result = result.concat(this.get(cls).revMap[RDF_TYPE])
      }
      return result;
    },

    importItem: function (item) {
      var node = this.toNode(item[keys.ID]); // TODO: item.getSource()
      for (var p in item) {
        if (p === keys.ID) {
          continue;
        }
        var o = item[p];
        if (o instanceof Array) {
          for (var i=0, it=null; it=o[i++];) {
            this.addObject(node, p, it);
          }
        } else {
          this.addObject(node, p, o);
        }
      }
    },

    toNode: function (id) {
      var node = this.idMap[id];
      if (node === undefined) {
        node = this.idMap[id] = new Node(id, this);
      }
      return node;
    },

    addObject: function (node, p, o) {
      if (p === keys.TYPE) {
        p = RDF_TYPE;
        if (typeof o === 'string') {
          o = {"@id": o};
        }
      }
      if (o[keys.ID]) {
        node.addLink(p, o[keys.ID]);
        this.importItem(o);
      } else if (o[keys.LIST]) {
        // TODO: List
        node.add(p, toList(o[keys.LIST]));
      } else {
        node.addValue(p, o[keys.VALUE], o[keys.LANG], o[keys.TYPE]);
      }
    },

    toJSON: function () {
      var l = [];
      for (var p in this.idMap)
        if (this.hasOwnProperty(p))
          l.push(this.idMap[p]);
      return l;
    }

  };

  function Resolver(mappings) {
    var map = this.map = {};
    for (key in mappings) {
      var val = mappings[key];
      if (typeof val === 'string') {
        map[key] = val;
      } else if (val[keys.ID]) {
        map[key] = val[keys.ID];
      }
    }
  }
  Resolver.prototype.resolve = function (termOrCURIEorIRI) {
    var def = this.map[termOrCURIEorIRI];
    if (def == undefined) {
      var parts = termOrCURIEorIRI.split(':');
      var ns = this.map[parts[0]];
      if (ns !== undefined) {
        return ns + parts[1];
      }
      return termOrCURIEorIRI;
    }
    return (typeof def === 'string')? def : def[keys.ID];
  };

  function Node(id, graph) {
    this.id = id;
    this.graph = graph;
    this.properties = {};
    this.revMap = {};
  }
  Node.prototype = {
    constructor: Node,

    toString: function () { return this.id; },

    toJSON: function () {
      return this.properties;
    },

    get: function (path) {
      return this.getAll(path)[0];
    },

    getAll: function (path) {
      var result;
      if (path[0] === '^') {
        var iri = this.graph.resolver.resolve(path.substring(1));
        result = this.revMap[iri];
      } else {
        var iri = this.graph.resolver.resolve(path);
        result = this.properties[iri];
      }
      if (result === undefined)
        return [];
      else
        return result;
    },

    addLink: function (rel, id) {
      var object = this.graph.toNode(id);
      var rel = this.graph.resolver.resolve(rel);
      this.add(rel, object.toRef());
      var rev = object.revMap[rel];
      if (rev === undefined) {
        rev = [];
        object.revMap[rel] = rev;
      }
      if (rev[this.id] === undefined) {
        var ref = this.toRef();
        rev.push(ref);
        rev[this.id] = ref;
      }
    },

    addValue: function (rel, value, lang, datatype) {
      // TODO: check if really literal or coerced...
      var literal = new Literal(value, lang, datatype);
      this.add(rel, literal);
    },

    /*
    TODO: ...
    setLink: function (rel, id) { },
    setLiteral: function (rel, value, lang, datatype) { },
    remove...
    */

    add: function (rel, item) {
      var all = this.properties[rel];
      if (all === undefined) {
        all = this.properties[rel] = [];
      }
      all.push(item);
    },

    toRef: function () {
      function Ref() {}
      Ref.prototype = this;
      var ref = new Ref();
      ref.toJSON = function () { return {"@id": this[keys.ID]}; };
      return ref;
    }

  };

  function Literal(value, lang, datatype, graph) {
    this[keys.VALUE] = value;
    this[keys.TYPE] = datatype;
    this[keys.LANG] = lang;
    this.graph = graph;
  }
  Literal.prototype = {
    constructor: Literal,

    toString: function () { return this[keys.VALUE]; },

    asNumber: function () {}, // TODO

    asBoolean: function () {}, // TODO

    asDate: function () {}, // TODO

    asNative: function () {
      return this.toDate() ||
        this.toBoolean() ||
          this.toNumber() ||
            this.toString();
    }

  };

  function toList(list) {
    function L() {}
    L.prototype = list;
    var wrapped = new L;
    wrapped.toJSON = function () {
        return {"@list": base};
    }
    return wrapped;
  }

  function toGraph(source, mappings) {
    var graph = new Graph(mappings);
    for (var it=null, i=0; it=source[i++];) {
      graph.importItem(it);
    }
    return graph;
  }

  exports.toGraph = toGraph;
  exports.Graph = Graph;
  exports.Node = Node;
  exports.Literal = Literal;

})(typeof exports !== 'undefined'? exports : RDF = {});
<commit_msg>Some fixes for toJSON and toList in rdf.js<commit_after>(function (exports) {

  var keys = {
    CONTEXT: '@context',
    ID: '@id',
    TYPE: '@type',
    VALUE: '@value',
    LANG: '@language',
    LIST: "@list",
    GRAPH: "@graph"
  };

  var RDF_TYPE = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type";

  function Graph(mappings) {
    this.resolver = new Resolver(mappings);
    this.idMap = {};
  }
  Graph.prototype = {

    get: function (termOrCURIEorIRI) {
      return this.idMap[this.resolver.resolve(termOrCURIEorIRI)];
    },

    all: function () {
      var result = [], map = this.idMap;
      for (var id in map) {
        result.push(map[id]);
      }
      return result;
    },

    allByType: function (/*types...*/) {
      var result = [];
      for (var cls=null, i=0; cls=arguments[i++];) {
        result = result.concat(this.get(cls).revMap[RDF_TYPE])
      }
      return result;
    },

    importItem: function (item) {
      var node = this.toNode(item[keys.ID]); // TODO: item.getSource()
      for (var p in item) {
        if (p === keys.ID) {
          continue;
        }
        var o = item[p];
        if (o instanceof Array) {
          for (var i=0, it=null; it=o[i++];) {
            this.addObject(node, p, it);
          }
        } else {
          this.addObject(node, p, o);
        }
      }
    },

    toNode: function (id) {
      var node = this.idMap[id];
      if (node === undefined) {
        node = this.idMap[id] = new Node(id, this);
      }
      return node;
    },

    addObject: function (node, p, o) {
      if (p === keys.TYPE) {
        p = RDF_TYPE;
        if (typeof o === 'string') {
          o = {"@id": o};
        }
      }
      if (o[keys.ID]) {
        node.addLink(p, o[keys.ID]);
        this.importItem(o);
      } else if (o[keys.LIST]) {
        // TODO: List
        node.add(p, toList(o[keys.LIST]));
      } else {
        node.addValue(p, o[keys.VALUE], o[keys.LANG], o[keys.TYPE]);
      }
    },

    toJSON: function () {
      var l = [];
      for (var p in this.idMap)
        if (this.hasOwnProperty(p))
          l.push(this.idMap[p]);
      return l;
    }

  };

  function Resolver(mappings) {
    var map = this.map = {};
    for (key in mappings) {
      var val = mappings[key];
      if (typeof val === 'string') {
        map[key] = val;
      } else if (val[keys.ID]) {
        map[key] = val[keys.ID];
      }
    }
  }
  Resolver.prototype.resolve = function (termOrCURIEorIRI) {
    var def = this.map[termOrCURIEorIRI];
    if (def == undefined) {
      var parts = termOrCURIEorIRI.split(':');
      var ns = this.map[parts[0]];
      if (ns !== undefined) {
        return ns + parts[1];
      }
      return termOrCURIEorIRI;
    }
    return (typeof def === 'string')? def : def[keys.ID];
  };

  function Node(id, graph) {
    this.id = id;
    this.graph = graph;
    this.properties = {};
    this.revMap = {};
  }
  Node.prototype = {
    constructor: Node,

    toString: function () { return this.id; },

    toJSON: function () {
      var o = {}, props = this.properties;
      o[keys.ID] = this.id;
      for (var p in props) {
        o[p] = props[p];
      }
      return o;
    },

    get: function (path) {
      return this.getAll(path)[0];
    },

    getAll: function (path) {
      var result;
      if (path[0] === '^') {
        var iri = this.graph.resolver.resolve(path.substring(1));
        result = this.revMap[iri];
      } else {
        var iri = this.graph.resolver.resolve(path);
        result = this.properties[iri];
      }
      if (result === undefined)
        return [];
      else
        return result;
    },

    addLink: function (rel, id) {
      var object = this.graph.toNode(id);
      var rel = this.graph.resolver.resolve(rel);
      this.add(rel, object.toRef());
      var rev = object.revMap[rel];
      if (rev === undefined) {
        rev = [];
        object.revMap[rel] = rev;
      }
      if (rev[this.id] === undefined) {
        var ref = this.toRef();
        rev.push(ref);
        rev[this.id] = ref;
      }
    },

    addValue: function (rel, value, lang, datatype) {
      // TODO: check if really literal or coerced...
      var literal = new Literal(value, lang, datatype);
      this.add(rel, literal);
    },

    /*
    TODO: ...
    setLink: function (rel, id) { },
    setLiteral: function (rel, value, lang, datatype) { },
    remove...
    */

    add: function (rel, item) {
      var all = this.properties[rel];
      if (all === undefined) {
        all = this.properties[rel] = [];
      }
      all.push(item);
    },

    toRef: function () {
      function Ref() {}
      Ref.prototype = this;
      var ref = new Ref();
      ref.toJSON = function () { return {"@id": this[keys.ID]}; };
      return ref;
    }

  };

  function Literal(value, lang, datatype, graph) {
    this.value = value;
    this.datatype = datatype;
    this.lang = lang;
    this.graph = graph;
  }
  Literal.prototype = {
    constructor: Literal,

    toString: function () { return this.value; },

    toJSON: function () {
      var o = {};
      o[keys.VALUE] = this.value;
      if (this.type) o[keys.TYPE] = this.datatype;
      if (this.lang) o[keys.LANG] = this.lang;
      return o;
    },

    asNumber: function () {}, // TODO

    asBoolean: function () {}, // TODO

    asDate: function () {}, // TODO

    asNative: function () {
      return this.toDate() ||
        this.toBoolean() ||
          this.toNumber() ||
            this.toString();
    }

  };

  //function List(array) {
  //  this.items = array;
  //}
  function toList(array) {
    var copy = array.slice();
    // TODO: change use of constructor to an attribute for type?
    copy.type = 'list';
    copy.toJSON = function () {
      var o = {}; o[keys.LIST] = array; return o;
    }
    return copy;
  }

  function toGraph(source, mappings) {
    var graph = new Graph(mappings);
    for (var it=null, i=0; it=source[i++];) {
      graph.importItem(it);
    }
    return graph;
  }

  exports.toGraph = toGraph;
  exports.Graph = Graph;
  exports.Node = Node;
  exports.Literal = Literal;

})(typeof exports !== 'undefined'? exports : RDF = {});
<|endoftext|>


<commit_before>/**
 * JavaScript file for the "run" page in the browser.
 *
 * @author John Resig, 2008-2011
 * @author Timo Tijhof, 2012
 * @since 0.1.0
 * @package TestSwarm
 */
(function ( $, SWARM, undefined ) {
	var currRunId, currRunUrl, testTimeout, pauseTimer, cmds, errorOut;

	function msg( htmlMsg ) {
		$( "#msg" ).html( htmlMsg );
	}

	function log( htmlMsg ) {
		$( "#history" ).prepend( "
" +
			new Date().toString().replace( /^\w+ /, "" ).replace( /:[^:]+$/, "" ) +
			": " + htmlMsg + "
"
		);

		msg( htmlMsg );
	}

	/**
	 * Softly validate the SWARM object
	 */
	if ( !SWARM.client_id || !SWARM.conf ) {
		$( function () {
			msg( "Error: No client id configured! Aborting." );
		});
		return;
	}

	errorOut = 0;
	cmds = {
		reload: function () {
			window.location.reload();
		}
	};

	/**
	 * @param query String|Object: $.ajax "data" option, converted with $.param.
	 * @param retry Function
	 * @param ok Function
	 */
	function retrySend( query, retry, ok ) {
		$.ajax({
			type: "POST",
			url: SWARM.conf.web.contextpath + "api.php",
			timeout: SWARM.conf.client.savereq_timeout * 1000,
			cache: false,
			data: query,
			dataType: "json",
			success: function () {
				errorOut = 0;
				ok.apply( this, arguments );
			},
			error: function () {
				if ( errorOut > SWARM.conf.client.saveretry_max ) {
					cmds.reload();
				} else {
					errorOut += 1;
					msg( "Error connecting to server, retrying..." );
					setTimeout( retry, SWARM.conf.client.saveretry_sleep * 1000 );
				}
			}
		});
	}

	function getTests() {
		if ( currRunId === undefined ) {
			log( "Connected to the swarm." );
		}

		currRunId = 0;
		currRunUrl = false;

		msg( "Querying for tests to run..." );
		retrySend( {
			action: "getrun",
			client_id: SWARM.client_id,
			run_token: SWARM.run_token
		}, getTests, runTests );
	}

	function cancelTest() {
		if ( testTimeout ) {
			clearTimeout( testTimeout );
			testTimeout = 0;
		}

		$( "iframe" ).remove();
	}

	function testTimedout() {
		cancelTest();
		retrySend(
			{
				action: "saverun",
				fail: "-1",
				error: "0",
				total: "-1",
				results: "Test Timed Out.",
				run_id: currRunId,
				client_id: SWARM.client_id,
				run_token: SWARM.run_token
			},
			testTimedout,
			function ( data ) {
				if ( data.saverun === "ok" ) {
					SWARM.runDone();
				} else {
					getTests();
				}
			}
		);
	}

	/**
	 * @param data Object: Reponse from api.php?action=getrun
	 */
	function runTests( data ) {
		var norun_msg, timeLeft, runInfo, params, iframe;

		if ( !$.isPlainObject( data ) || data.error ) {
			// Handle session timeout, where server sends back "Username required."
			// Handle TestSwarm reset, where server sends back "Client doesn't exist."
			if ( data.error ) {
				$(function () {
					msg( 'action=getrun failed. ' + $( "
" ).text( data.error.info ).html() );
				});
				return;
			}
		}

		if ( data.getrun ) {
			// Handle configuration update
			if ( data.getrun.confUpdate ) {

				// Refresh control
				if ( SWARM.conf.client.refresh_control < data.getrun.confUpdate.client.refresh_control ) {
					cmds.reload();
					return;
				}

				$.extend( SWARM.conf, data.getrun.confUpdate );
			}

			// Handle actual retreived tests from runInfo
			runInfo = data.getrun.runInfo;
			if ( runInfo ) {
				currRunId = runInfo.id;
				currRunUrl = runInfo.url;

				log( "Running " + ( runInfo.desc || "" ) + " tests..." );

				iframe = document.createElement( "iframe" );
				iframe.width = 1000;
				iframe.height = 600;
				iframe.className = "test-runner-frame";
				iframe.src = currRunUrl + (currRunUrl.indexOf( "?" ) > -1 ? "&" : "?") + $.param({
					// Cache buster
					"_" : new Date().getTime(),
					// Homing signal for inject.js so that it can find its target for action=saverun
					"swarmURL" : window.location.protocol + "//" + window.location.host + SWARM.conf.web.contextpath
						+ "index.php?"
						+ $.param({
							run_id: currRunId,
							client_id: SWARM.client_id,
							run_token: SWARM.run_token,
						}),
				});

				$( "#iframes" ).append( iframe );

				// Timeout after a period of time
				testTimeout = setTimeout( testTimedout, SWARM.conf.client.run_timeout * 1000 );

				return;
			}

		}

		// If we're still here then either there are no new tests to run, or this is a call
		// triggerd by an iframe to continue the loop. We'll do so a short timeout,
		// optionally replacing the message by data.timeoutMsg
		clearTimeout( pauseTimer );

		norun_msg = data.timeoutMsg || "No new tests to run.";

		msg( norun_msg );

		// If we just completed a run, do a cooldown before we fetch the next run (if there is one).
		// If we just completed a cooldown a no runs where available, nonewruns_sleep instead.
		timeLeft = currRunUrl ? SWARM.conf.client.cooldown_sleep : SWARM.conf.client.nonewruns_sleep;

		pauseTimer = setTimeout(function leftTimer() {
			msg(norun_msg + " Getting more in " + timeLeft + " seconds." );
			if ( timeLeft >= 1 ) {
				timeLeft -= 1;
				pauseTimer = setTimeout( leftTimer, 1000 );
			} else {
				timeLeft -= 1;
				getTests();
			}
		}, 1000);

	}

	// Needs to be a publicly exposed function,
	// so that when inject.js does a <form> submission,
	// it can call this from within the frame
	// as window.parent.SWARM.runDone();
	SWARM.runDone = function () {
		cancelTest();
		runTests({ timeoutMsg: "Cooling down." });
	};

	function handleMessage(e) {
		e = e || window.event;
		retrySend( e.data, function () {
			handleMessage(e);
		}, SWARM.runDone );
	}

	/**
	 * Bind
	 */
	if ( window.addEventListener ) {
		window.addEventListener( "message", handleMessage, false );
	} else if ( window.attachEvent ) {
		window.attachEvent( "onmessage", handleMessage );
	}

	$( document).ready( getTests );

}( jQuery, SWARM ) );
<commit_msg>fix trailing commas in object literals that crash IE<commit_after>/**
 * JavaScript file for the "run" page in the browser.
 *
 * @author John Resig, 2008-2011
 * @author Timo Tijhof, 2012
 * @since 0.1.0
 * @package TestSwarm
 */
(function ( $, SWARM, undefined ) {
	var currRunId, currRunUrl, testTimeout, pauseTimer, cmds, errorOut;

	function msg( htmlMsg ) {
		$( "#msg" ).html( htmlMsg );
	}

	function log( htmlMsg ) {
		$( "#history" ).prepend( "
" +
			new Date().toString().replace( /^\w+ /, "" ).replace( /:[^:]+$/, "" ) +
			": " + htmlMsg + "
"
		);

		msg( htmlMsg );
	}

	/**
	 * Softly validate the SWARM object
	 */
	if ( !SWARM.client_id || !SWARM.conf ) {
		$( function () {
			msg( "Error: No client id configured! Aborting." );
		});
		return;
	}

	errorOut = 0;
	cmds = {
		reload: function () {
			window.location.reload();
		}
	};

	/**
	 * @param query String|Object: $.ajax "data" option, converted with $.param.
	 * @param retry Function
	 * @param ok Function
	 */
	function retrySend( query, retry, ok ) {
		$.ajax({
			type: "POST",
			url: SWARM.conf.web.contextpath + "api.php",
			timeout: SWARM.conf.client.savereq_timeout * 1000,
			cache: false,
			data: query,
			dataType: "json",
			success: function () {
				errorOut = 0;
				ok.apply( this, arguments );
			},
			error: function () {
				if ( errorOut > SWARM.conf.client.saveretry_max ) {
					cmds.reload();
				} else {
					errorOut += 1;
					msg( "Error connecting to server, retrying..." );
					setTimeout( retry, SWARM.conf.client.saveretry_sleep * 1000 );
				}
			}
		});
	}

	function getTests() {
		if ( currRunId === undefined ) {
			log( "Connected to the swarm." );
		}

		currRunId = 0;
		currRunUrl = false;

		msg( "Querying for tests to run..." );
		retrySend( {
			action: "getrun",
			client_id: SWARM.client_id,
			run_token: SWARM.run_token
		}, getTests, runTests );
	}

	function cancelTest() {
		if ( testTimeout ) {
			clearTimeout( testTimeout );
			testTimeout = 0;
		}

		$( "iframe" ).remove();
	}

	function testTimedout() {
		cancelTest();
		retrySend(
			{
				action: "saverun",
				fail: "-1",
				error: "0",
				total: "-1",
				results: "Test Timed Out.",
				run_id: currRunId,
				client_id: SWARM.client_id,
				run_token: SWARM.run_token
			},
			testTimedout,
			function ( data ) {
				if ( data.saverun === "ok" ) {
					SWARM.runDone();
				} else {
					getTests();
				}
			}
		);
	}

	/**
	 * @param data Object: Reponse from api.php?action=getrun
	 */
	function runTests( data ) {
		var norun_msg, timeLeft, runInfo, params, iframe;

		if ( !$.isPlainObject( data ) || data.error ) {
			// Handle session timeout, where server sends back "Username required."
			// Handle TestSwarm reset, where server sends back "Client doesn't exist."
			if ( data.error ) {
				$(function () {
					msg( 'action=getrun failed. ' + $( "
" ).text( data.error.info ).html() );
				});
				return;
			}
		}

		if ( data.getrun ) {
			// Handle configuration update
			if ( data.getrun.confUpdate ) {

				// Refresh control
				if ( SWARM.conf.client.refresh_control < data.getrun.confUpdate.client.refresh_control ) {
					cmds.reload();
					return;
				}

				$.extend( SWARM.conf, data.getrun.confUpdate );
			}

			// Handle actual retreived tests from runInfo
			runInfo = data.getrun.runInfo;
			if ( runInfo ) {
				currRunId = runInfo.id;
				currRunUrl = runInfo.url;

				log( "Running " + ( runInfo.desc || "" ) + " tests..." );

				iframe = document.createElement( "iframe" );
				iframe.width = 1000;
				iframe.height = 600;
				iframe.className = "test-runner-frame";
				iframe.src = currRunUrl + (currRunUrl.indexOf( "?" ) > -1 ? "&" : "?") + $.param({
					// Cache buster
					"_" : new Date().getTime(),
					// Homing signal for inject.js so that it can find its target for action=saverun
					"swarmURL" : window.location.protocol + "//" + window.location.host + SWARM.conf.web.contextpath
						+ "index.php?"
						+ $.param({
							run_id: currRunId,
							client_id: SWARM.client_id,
							run_token: SWARM.run_token
						})
				});

				$( "#iframes" ).append( iframe );

				// Timeout after a period of time
				testTimeout = setTimeout( testTimedout, SWARM.conf.client.run_timeout * 1000 );

				return;
			}

		}

		// If we're still here then either there are no new tests to run, or this is a call
		// triggerd by an iframe to continue the loop. We'll do so a short timeout,
		// optionally replacing the message by data.timeoutMsg
		clearTimeout( pauseTimer );

		norun_msg = data.timeoutMsg || "No new tests to run.";

		msg( norun_msg );

		// If we just completed a run, do a cooldown before we fetch the next run (if there is one).
		// If we just completed a cooldown a no runs where available, nonewruns_sleep instead.
		timeLeft = currRunUrl ? SWARM.conf.client.cooldown_sleep : SWARM.conf.client.nonewruns_sleep;

		pauseTimer = setTimeout(function leftTimer() {
			msg(norun_msg + " Getting more in " + timeLeft + " seconds." );
			if ( timeLeft >= 1 ) {
				timeLeft -= 1;
				pauseTimer = setTimeout( leftTimer, 1000 );
			} else {
				timeLeft -= 1;
				getTests();
			}
		}, 1000);

	}

	// Needs to be a publicly exposed function,
	// so that when inject.js does a <form> submission,
	// it can call this from within the frame
	// as window.parent.SWARM.runDone();
	SWARM.runDone = function () {
		cancelTest();
		runTests({ timeoutMsg: "Cooling down." });
	};

	function handleMessage(e) {
		e = e || window.event;
		retrySend( e.data, function () {
			handleMessage(e);
		}, SWARM.runDone );
	}

	/**
	 * Bind
	 */
	if ( window.addEventListener ) {
		window.addEventListener( "message", handleMessage, false );
	} else if ( window.attachEvent ) {
		window.attachEvent( "onmessage", handleMessage );
	}

	$( document).ready( getTests );

}( jQuery, SWARM ) );
<|endoftext|>


<commit_before>var response_kakao = function (json) {
  var video_list = json.content;
    video_list.forEach(function(v, i) {
        var item = v;
        var shareLink = "http://vikicast.com/index.html?utm_source=kakaoLink&utm_medium=social#" + item.id;
        console.log(shareLink);
        // 카카오톡 링크 버튼을 생성합니다. 처음 한번만 호출하면 됩니다.
        Kakao.Link.sendTalkLink({
          label: item.description,
          image: {
            src: item.picture,
            width: item.width,
            height: item.height
          },
          webButton: {
            text: "vikicast x " + item.name,
            url: shareLink // 앱 설정의 웹 플랫폼에 등록한 도메인의 URL이어야 합니다.
          },
          fail: Materialize.toast('카카오톡 링크는 모바일 기기에서만 전송 가능합니다.', 4000, 'rounded')
          // webLink : {
          //   text: item.name,
          //   url: 'http://facebook.com/' + item.id
          // }
        });
        // Kakao.Link.cleanup();
        // 카카오 공유를 GA로 추적
        ga('send', 'event', "shareLink", "sendkakao", item.id );
      });
    }

    // 페이스북
    var windowHeight = 360;
    var windowWidth = 640;

    var response_facebook = function (json){
      var video_list = json.content;
        video_list.forEach(function(v, i) {
            var item = v;
            var REDIRECT_URL = "http://vikicast.com/index.html#" + item.id;
            console.log(REDIRECT_URL);

            // 페이스북 메타 데이터 변경
            $("meta[property=og\\:url]").attr("content", REDIRECT_URL);
            // $("meta[property=og\\:type]").attr("content", item.category);
            $("meta[property=og\\:title]").attr("content", "[VIKICAST x" + item.name + "]");
            $("meta[property=og\\:description]").attr("content", item.description);
            $("meta[property=og\\:image]").attr("content", item.picture);

            //  페이스북 로그인 시도
         FB.ui(
                {
                   method: 'feed',
                   display: 'touch',
                   name: 'VIKICAST x ' + item.name,
                   redirect_uri: "http://vikicast.com/responseSuccess.html",
                   picture: "http://vikicast.com/res/facebook/Untitled05.png",
                   caption: 'category: ' + item.category ,
                   description: item.description ,
                   message: '당신만 못 봤던 그 영상, 여기 다 있다!',
                   link: REDIRECT_URL
                 },
                 function(response) {
                   if (response && response.post_id) {
                     console.log('Post was published.');
                     ga('send', 'event', "sendFBshareSuccess", item.id );

                     if(window.location.search.indexOf('post_id')==1) window.close();

                   } else {
                     console.log('Post was not published.');
                     ga('send', 'event', "sendFBshareFail", item.id );

                   }
                 }
               );

            // var facebookUrl = "https://www.facebook.com/dialog/feed?"+
            // "app_id=1463571523951964" +
            // "&display=touch" +
            // "&utm_source=facebookLink&utm_medium=social" +
            // "&action_type=og.like"+
            // "$description=" + item.description +
            // "&name=VIKICAST x " + item.name +
            // "&caption=category: " + item.category +
            // "&pictire=" + item.pictire +
            // "&redirect_uri=http://vikicast.com/responseSuccess.html" +
            // "&action_properties={'object':'"+ REDIRECT_URL +"'}"

            // "&href=" + REDIRECT_URL;
            // var $fbiFrame = "";

            // $('.modal-content').append($fbiFrame);
            // $('#modal1').openModal();

            // ga('send', 'event', "sendFBshareRequest", item.id );
            // window.open(facebookUrl, "_blank", "height=" + windowHeight + ",width=" + windowWidth);
          });
        }

var shareTwitter = function() {
  var twitterUrl = "https://twitter.com/intent/tweet?url=" + location.href;
  window.open(twitterUrl, "_blank", "height=" + windowHeight + ",width=" + windowWidth);
};
<commit_msg>이미지 수정을 테스트<commit_after>var response_kakao = function (json) {
  var video_list = json.content;
    video_list.forEach(function(v, i) {
        var item = v;
        var shareLink = "http://vikicast.com/index.html?utm_source=kakaoLink&utm_medium=social#" + item.id;
        console.log(shareLink);
        // 카카오톡 링크 버튼을 생성합니다. 처음 한번만 호출하면 됩니다.
        Kakao.Link.sendTalkLink({
          label: item.description,
          image: {
            src: item.picture,
            width: item.width,
            height: item.height
          },
          webButton: {
            text: "vikicast x " + item.name,
            url: shareLink // 앱 설정의 웹 플랫폼에 등록한 도메인의 URL이어야 합니다.
          },
          fail: Materialize.toast('카카오톡 링크는 모바일 기기에서만 전송 가능합니다.', 4000, 'rounded')
          // webLink : {
          //   text: item.name,
          //   url: 'http://facebook.com/' + item.id
          // }
        });
        // Kakao.Link.cleanup();
        // 카카오 공유를 GA로 추적
        ga('send', 'event', "shareLink", "sendkakao", item.id );
      });
    }

    // 페이스북
    var windowHeight = 360;
    var windowWidth = 640;

    var response_facebook = function (json){
      var video_list = json.content;
        video_list.forEach(function(v, i) {
            var item = v;
            var REDIRECT_URL = "http://vikicast.com/index.html#" + item.id;
            console.log(REDIRECT_URL);

            // 페이스북 메타 데이터 변경
            $("meta[property=og\\:url]").attr("content", REDIRECT_URL);
            // $("meta[property=og\\:type]").attr("content", item.category);
            $("meta[property=og\\:title]").attr("content", "[VIKICAST x" + item.name + "]");
            $("meta[property=og\\:description]").attr("content", item.description);
            $("meta[property=og\\:image]").attr("content", item.picture);

            //  페이스북 로그인 시도
         FB.ui(
                {
                   method: 'feed',
                   display: 'popup',
                   name: 'VIKICAST x ' + item.name,
                   redirect_uri: "http://vikicast.com/responseSuccess.html",
                   picture: item.picture,
                   caption: 'category: ' + item.category ,
                   description: item.description ,
                   message: '당신만 못 봤던 그 영상, 여기 다 있다!',
                   link: REDIRECT_URL
                 },
                 function(response) {
                   if (response && response.post_id) {
                     console.log('Post was published.');
                     ga('send', 'event', "sendFBshareSuccess", item.id );

                     if(window.location.search.indexOf('post_id')==1) window.close();

                   } else {
                     console.log('Post was not published.');
                     ga('send', 'event', "sendFBshareFail", item.id );

                   }
                 }
               );

            // var facebookUrl = "https://www.facebook.com/dialog/feed?"+
            // "app_id=1463571523951964" +
            // "&display=touch" +
            // "&utm_source=facebookLink&utm_medium=social" +
            // "&action_type=og.like"+
            // "$description=" + item.description +
            // "&name=VIKICAST x " + item.name +
            // "&caption=category: " + item.category +
            // "&pictire=" + item.pictire +
            // "&redirect_uri=http://vikicast.com/responseSuccess.html" +
            // "&action_properties={'object':'"+ REDIRECT_URL +"'}"

            // "&href=" + REDIRECT_URL;
            // var $fbiFrame = "";

            // $('.modal-content').append($fbiFrame);
            // $('#modal1').openModal();

            // ga('send', 'event', "sendFBshareRequest", item.id );
            // window.open(facebookUrl, "_blank", "height=" + windowHeight + ",width=" + windowWidth);
          });
        }

var shareTwitter = function() {
  var twitterUrl = "https://twitter.com/intent/tweet?url=" + location.href;
  window.open(twitterUrl, "_blank", "height=" + windowHeight + ",width=" + windowWidth);
};
<|endoftext|>


<commit_before>var cities = []
var totalCities = 12;

var recordDistance;
var bestEver;

function setup() {
  createCanvas(800, 500);

  // create the city vertices
  for (var i=0; i<totalCities; i++) {
    var v = createVector(random(width), random(height));
    cities[i] = v;
  }
  // initialize
  var d = calcDistance(cities);
  recordDistance = d;
  bestEver = cities.slice();
}

function draw() {
  background(0);

  // draw the city vertices
  fill(255);
  for (var i=0; i<cities.length; i++) {
    ellipse(cities[i].x, cities[i].y, 8, 8);
  }

  // draw the path (in white)
  stroke(255);
  strokeWeight(2);
  noFill();
  beginShape();
  for (var i=0; i<cities.length; i++) {
    vertex(cities[i].x, cities[i].y);
  }
  //go back to the start
  vertex(cities[0].x, cities[0].y);
  endShape();

  // draw the bestEver path (in green)
  stroke(0, 255, 88);
  strokeWeight(3);
  noFill();
  beginShape();
  for (var i=0; i<cities.length; i++) {
    vertex(bestEver[i].x, bestEver[i].y);
  }
  // go back to the start
  vertex(bestEver[0].x, bestEver[0].y);
  endShape();

  // random swap
  var i = floor(random(cities.length));
  var j = floor(random(cities.length));
  swap(cities, i, j)

  // calculate the distance
  var d = calcDistance(cities);
  if (d < recordDistance) {
    recordDistance = d;
    bestEver = cities.slice();
  }
}

function swap(a, i, j) {
  var temp = a[i];
  a[i] = a[j];
  a[j] = temp;
}

function calcDistance(points) {
  var sum = 0;
  for (var i=0; i<points.length-1; i++) {
    var d = dist(points[i].x, points[i].y, points[i+1].x, points[i+1].y)
    sum += d;
  }
  // add the distance from the start to finish
  d = dist(points[0].x,
    points[0].y,
    points[points.length-1].x,
    points[points.length-1].y);
  sum += d;
  return sum;
}
<commit_msg>Update tsp.js<commit_after>var cities = []
var totalCities = 12;

var recordDistance;
var bestEver;

function setup() {
  createCanvas(800, 500);

  // Move the canvas so it's inside our <div id="sketch-holder">.
  canvas.parent('sketch-holder');

  // create the city vertices
  for (var i=0; i<totalCities; i++) {
    var v = createVector(random(width), random(height));
    cities[i] = v;
  }
  // initialize
  var d = calcDistance(cities);
  recordDistance = d;
  bestEver = cities.slice();
}

function draw() {
  background(0);

  // draw the city vertices
  fill(255);
  for (var i=0; i<cities.length; i++) {
    ellipse(cities[i].x, cities[i].y, 8, 8);
  }

  // draw the path (in white)
  stroke(255);
  strokeWeight(2);
  noFill();
  beginShape();
  for (var i=0; i<cities.length; i++) {
    vertex(cities[i].x, cities[i].y);
  }
  //go back to the start
  vertex(cities[0].x, cities[0].y);
  endShape();

  // draw the bestEver path (in green)
  stroke(0, 255, 88);
  strokeWeight(3);
  noFill();
  beginShape();
  for (var i=0; i<cities.length; i++) {
    vertex(bestEver[i].x, bestEver[i].y);
  }
  // go back to the start
  vertex(bestEver[0].x, bestEver[0].y);
  endShape();

  // random swap
  var i = floor(random(cities.length));
  var j = floor(random(cities.length));
  swap(cities, i, j)

  // calculate the distance
  var d = calcDistance(cities);
  if (d < recordDistance) {
    recordDistance = d;
    bestEver = cities.slice();
  }
}

function swap(a, i, j) {
  var temp = a[i];
  a[i] = a[j];
  a[j] = temp;
}

function calcDistance(points) {
  var sum = 0;
  for (var i=0; i<points.length-1; i++) {
    var d = dist(points[i].x, points[i].y, points[i+1].x, points[i+1].y)
    sum += d;
  }
  // add the distance from the start to finish
  d = dist(points[0].x,
    points[0].y,
    points[points.length-1].x,
    points[points.length-1].y);
  sum += d;
  return sum;
}
<|endoftext|>


<commit_before>var jslide = (function() {
  var scaleFactor, // scale factor
      current;     // current slide number

  function buildSpotLight(r) {
    var canvas, c, grad, im,
        shown = false,
        x, y;

    // build canvas
    canvas = $('<canvas/>').addClass('jslideSpotlight');
    $('body').append(canvas);

    // initial position
    x = 0;
    y = 0;

    // draw and cache spotlight
    c = canvas[0].getContext('2d');
    recache(r);

    // bind the 'dry' mousemove handler (only update coordinates, no redrawing)
    $(document).bind( 'mousemove', mouseMoveHandlerDry );

    // methods
    function recache(newr) {
      r = newr;
      // resize temporarily
      canvas[0].width = 2*r;
      canvas[0].height = 2*r;
      // radial gradient
      grad = c.createRadialGradient(r,r,r*0.75,r,r,r);
      grad.addColorStop(0, 'rgba(0,0,0,0)');
      grad.addColorStop(1, 'rgba(0,0,0,0.5)');
      // draw shapes
      c.fillStyle = grad;
      c.fillRect(0,0,2*r,2*r);
      im = c.getImageData( 0, 0, 2*r, 2*r );

      // scale back and redraw
      scale();
    }
    function scale() {
      var w = $(window).width(),
          h = $(window).height();
      canvas[0].width = w;
      canvas[0].height = h;
      draw();
    }
    function draw() {
      c.fillStyle = 'rgba(0,0,0,0.5)';
      c.clearRect(0,0,canvas[0].width,canvas[0].height);
      c.fillRect(0,0,canvas[0].width,canvas[0].height);
      c.putImageData( im, x, y );
    }
    function mouseMoveHandler(e) {
      var coord = e.pageX + ' ' + e.pageY;
      x = e.pageX - r;
      y = e.pageY - r;
      draw();
    }
    function mouseMoveHandlerDry(e) {
      var coord = e.pageX + ' ' + e.pageY;
      x = e.pageX - r;
      y = e.pageY - r;
    }
    function mouseWheelHandler(e, delta) {
      var newr = Math.floor( r + (10+r/10)*delta );
      if( newr < 30 || newr > 1000 ) { return; }
      x = x + r - newr;
      y = y + r - newr;
      recache( newr );
    }
    function show() {
      $(document).unbind( 'mousemove', mouseMoveHandlerDry );
      $(document).bind( 'mousemove', mouseMoveHandler );
      $(document).mousewheel( mouseWheelHandler );
      $(window).bind( 'resize', scale );
      $('body').css('cursor','crosshair');
      scale();
      canvas.fadeIn();
      shown = true;
    }
    function hide() {
      $(document).unbind( 'mousemove', mouseMoveHandler );
      $(document).bind( 'mousemove', mouseMoveHandlerDry );
      $(document).unmousewheel( mouseWheelHandler );
      $(window).unbind( 'resize', scale );
      $('body').css('cursor','');
      canvas.fadeOut();
      shown = false;
    }
    function toggle() {
      if( shown ) {
        hide();
      } else {
        show();
      }
      return shown;
    }

    return {
      toggle : toggle
    };
  };

  // global: scaleFactor
  function scale() {
    var cs = $(slideList[current]),
        sc = $('.slides'),
        ww = $(window).width(),
        wh = $(window).height(),
        ew = cs.outerWidth(),
        eh = cs.outerHeight(),
        r = Math.min(ww/ew,wh/eh),
        sx = Math.round((ww-ew*r)/2),
        sy = Math.round((wh-eh*r)/2);

    // scale
    $.each(['webkit','moz','o'], function(i,p) { sc.css('-'+p+'-transform','scale('+r+', '+r+')'); } );
    scaleFactor = r;

    // center
    sc.css( { left: sx+'px', top: sy+'px' } );
  }

  // go to slide
  // global: current
  function goToSlide(n) {
    var handler;
    // leaving a slide or entering the presentation?
    if( current !== undefined ) {
      // fire onleave handler for current slide (may prevent leaving)
      handler = $(slideList[current]).data('onleave');
      if( handler && handler() === false ) {
        return;
      }
    }
    current = n;

    // fire onenter hander
    handler = $(slideList[current]).data('onenter');
    if( handler ) {
      handler();
    }

    // reset visibility
    slideList.each( function(i,e) {
      $(e).attr( 'class', slideClass[i] );
      if( i == current ) {
        $(e).addClass('slideCurrent');
      } else if ( i == current-1 ) {
        $(e).addClass('slidePrev');
      } else if ( i == current+1 ) {
        $(e).addClass('slideNext');
      } else if ( i < current-1 ) {
        $(e).addClass('slideFarPrev');
      } else if ( i > current+1 ) {
        $(e).addClass('slideFarNext');
      }
    } );

    // make visible changes
    window.location.hash = slideList[current].id;
    scale();
  }

  // next slide
  function nextSlide() {
    if( current < slideList.length-1 ) {
      goToSlide(current+1);
    }
  }

  // previous slide
  function prevSlide() {
    if( current > 0 ) {
      goToSlide(current-1);
    }
  }

  function parseSteps(s) {
    var passTwo = [], steps = [],
        items = s.split(','),
        toEnd = /^(\d+)-$/,
        fromBegin = /^-(\d+)$/,
        range = /^(\d+)-(\d+)$/,
        num   = /^(\d+)$/,
        i, j, m;
    for( i = 0; i < items.length; ++i ) {
      // range
      m = range.exec( items[i] );
      if( m ) {
        if( m[1] == 0 ) {
          throw 'Steps start at 1';
        }
        for( j = m[1]; j <= m[2]; j++ ) {
          steps[j-1] = true;
        }
        continue;
      }

      // single step
      m = num.exec( items[i] );
      if( m ) {
        if( m[1] == 0 ) {
          throw 'Steps start at 1';
        }
        steps[m[1]-1] = true;
        continue;
      }

      // invalid
      throw 'Invalid step set:' + s;
    }

    return steps;
  }

  // add svg overlay to current slide
  function addOverlay( slide, callback ) {
    var o = $('

').addClass('svgOverlay');
    $(slide).append(o);
    function initOverlay(svg) {
      var d = svg.defs('myDefs');
      var m = svg.marker(d,'overlayArrow',3,2,4,4,'auto');
      svg.polyline(m,[[0,0], [4,2],[0,4],[1,2]]);

      callback(svg);
    }
    o.svg( { onLoad: initOverlay } );
  }
  // get svg handler for slide
  function getOverlay( slide ) {
    return $(slide).find('.svgOverlay').svg('get');
  }
  // draw an arrow
  function arrow(svg,x1,y1,x2,y2, options) {
    svg.line( x1, y1, x2, y2, $.extend( { markerEnd: 'url(#overlayArrow)', strokeWidth: 5, stroke: 'blue' }, options ) );
  }
  // connect two elements on the slide with an arrow
  function arrowFromTo( slide, from, to, options ) {
    var f = $(from).offset(), t = $(to).offset(), s = $(slide).offset(),
        x1 = ( f.left - s.left )/scaleFactor + $(from).width()/2,
        x2 = ( t.left - s.left )/scaleFactor + $(to).width()/2,
        y1 = ( f.top - s.top )/scaleFactor + $(from).height()/2,
        y2 = ( t.top - s.top )/scaleFactor + $(to).height()/2;
    arrow(getOverlay(slide),x1,y1,x2,y2,options);
  }
  // draw an ellipse around an element on the slide
  function ellipseAround( slide, to, options ) {
    var t = $(to).offset(), s = $(slide).offset(),
        rx = $(to).width()/2,
        x  = ( t.left - s.left )/scaleFactor  + rx,
        ry = $(to).height()/2,
        y  = ( t.top - s.top )/scaleFactor + ry;
    getOverlay(slide).ellipse(x,y,rx*1.4,ry*1.4,$.extend( { strokeWidth: 5, stroke: 'blue', fill: 'none', opacity: 0.75 }, options ) );
  }

  // initialization
  var slideList, slideClass = [], stepTable, spotLight;
  function init() {
    var i, j, h,
        common,
        handlerList = ['onleave', 'onenter'];

    // build list of slides, remember orignal classes
    slideList = $('div.slide');
    slideList.each( function(i,e) { slideClass[i] = $(e).attr('class') });

    // append common content to all slides
    common = $('.slidecommon').detach();
    slideList.append(common);

    // compile slide event handlers
    slideList.each( function(i,e) {
      var handler;
      for( j = 0; j < handlerList.length; ++j ) {
        handler =  $(e).data(handlerList[j]);
        if( handler ) {
          $(e).data(handlerList[j], new Function(handler) );
        }
      }
    });

    // analyse step-by-step reveal information
    slideList.each( function(i,e) {
      var steps = $(e).data('steps');
      if( steps !== undefined ) {
        $(e).find('[step]').each( function(j,e) {
          // hook into list
        });
      }
    });

    // Spotlight
    spotLight = buildSpotLight(100);

    // honor url hash
    h = window.location.hash.substr(1);
    if( h !== '' ) {
      for( i = 0; i < slideList.length; ++i ) {
        if( slideList[i].id === h ) {
          goToSlide(i);
          break;
        }
      }
      if( i == slideList.length ) {
        // not found
        alert( h + " not found" );
        goToSlide(0);
      }
    } else {
      goToSlide(0);
    }
    $(window).resize(scale);
    scale();

    // add event handlers
    var frozen = false;
    $(document).keyup( function(e) {
      if( frozen ) { return; }
      switch(e.which) {
        case 34: // page down
        case 39: // crsr right
        case 40: // crsr down
        case 32: // space
          nextSlide(); break;
        case 8 : // backspace
        case 33: // page up
        case 37: // crsr left
        case 38: // crsr up
          prevSlide(); break;
        case 35: // end
          goToSlide(slideList.length-1); break;
        case 36: // home
          goToSlide(0); break;
        case 83 : // s
          spotLight.toggle(); break;
      }
    } );
  }

  return {
    init : init,
    nextSlide : nextSlide,
    prevSlide : prevSlide,
    freeze    : function() { frozen = true; },
    unfreeze  : function() { frozen = false; },
    addOverlay   : addOverlay,
    getOverlay   : getOverlay,
    arrow        : arrow,
    arrowFromTo  : arrowFromTo,
    ellipseAround: ellipseAround,
    style : { redArrow : { stroke: 'red' } },
    getStatus : function() { return [ current, slideList, spotLight ]; }
  };
})();

$(jslide.init);

<commit_msg>arrow styles<commit_after>var jslide = (function() {
  var scaleFactor, // scale factor
      current,     // current slide number
      acolor = ['red','green','blue','yellow','magenta','pink','brown','black'],
      astyle = [];      // available arrow colors

  function buildSpotLight(r) {
    var canvas, c, grad, im,
        shown = false,
        x, y;

    // build canvas
    canvas = $('<canvas/>').addClass('jslideSpotlight');
    $('body').append(canvas);

    // initial position
    x = 0;
    y = 0;

    // draw and cache spotlight
    c = canvas[0].getContext('2d');
    recache(r);

    // bind the 'dry' mousemove handler (only update coordinates, no redrawing)
    $(document).bind( 'mousemove', mouseMoveHandlerDry );

    // methods
    function recache(newr) {
      r = newr;
      // resize temporarily
      canvas[0].width = 2*r;
      canvas[0].height = 2*r;
      // radial gradient
      grad = c.createRadialGradient(r,r,r*0.75,r,r,r);
      grad.addColorStop(0, 'rgba(0,0,0,0)');
      grad.addColorStop(1, 'rgba(0,0,0,0.5)');
      // draw shapes
      c.fillStyle = grad;
      c.fillRect(0,0,2*r,2*r);
      im = c.getImageData( 0, 0, 2*r, 2*r );

      // scale back and redraw
      scale();
    }
    function scale() {
      var w = $(window).width(),
          h = $(window).height();
      canvas[0].width = w;
      canvas[0].height = h;
      draw();
    }
    function draw() {
      c.fillStyle = 'rgba(0,0,0,0.5)';
      c.clearRect(0,0,canvas[0].width,canvas[0].height);
      c.fillRect(0,0,canvas[0].width,canvas[0].height);
      c.putImageData( im, x, y );
    }
    function mouseMoveHandler(e) {
      var coord = e.pageX + ' ' + e.pageY;
      x = e.pageX - r;
      y = e.pageY - r;
      draw();
    }
    function mouseMoveHandlerDry(e) {
      var coord = e.pageX + ' ' + e.pageY;
      x = e.pageX - r;
      y = e.pageY - r;
    }
    function mouseWheelHandler(e, delta) {
      var newr = Math.floor( r + (10+r/10)*delta );
      if( newr < 30 || newr > 1000 ) { return; }
      x = x + r - newr;
      y = y + r - newr;
      recache( newr );
    }
    function show() {
      $(document).unbind( 'mousemove', mouseMoveHandlerDry );
      $(document).bind( 'mousemove', mouseMoveHandler );
      $(document).mousewheel( mouseWheelHandler );
      $(window).bind( 'resize', scale );
      $('body').css('cursor','crosshair');
      scale();
      canvas.fadeIn();
      shown = true;
    }
    function hide() {
      $(document).unbind( 'mousemove', mouseMoveHandler );
      $(document).bind( 'mousemove', mouseMoveHandlerDry );
      $(document).unmousewheel( mouseWheelHandler );
      $(window).unbind( 'resize', scale );
      $('body').css('cursor','');
      canvas.fadeOut();
      shown = false;
    }
    function toggle() {
      if( shown ) {
        hide();
      } else {
        show();
      }
      return shown;
    }

    return {
      toggle : toggle
    };
  };

  // global: scaleFactor
  function scale() {
    var cs = $(slideList[current]),
        sc = $('.slides'),
        ww = $(window).width(),
        wh = $(window).height(),
        ew = cs.outerWidth(),
        eh = cs.outerHeight(),
        r = Math.min(ww/ew,wh/eh),
        sx = Math.round((ww-ew*r)/2),
        sy = Math.round((wh-eh*r)/2);

    // scale
    $.each(['webkit','moz','o'], function(i,p) { sc.css('-'+p+'-transform','scale('+r+', '+r+')'); } );
    scaleFactor = r;

    // center
    sc.css( { left: sx+'px', top: sy+'px' } );
  }

  // go to slide
  // global: current
  function goToSlide(n) {
    var handler;
    // leaving a slide or entering the presentation?
    if( current !== undefined ) {
      // fire onleave handler for current slide (may prevent leaving)
      handler = $(slideList[current]).data('onleave');
      if( handler && handler() === false ) {
        return;
      }
    }
    current = n;

    // fire onenter hander
    handler = $(slideList[current]).data('onenter');
    if( handler ) {
      handler();
    }

    // reset visibility
    slideList.each( function(i,e) {
      $(e).attr( 'class', slideClass[i] );
      if( i == current ) {
        $(e).addClass('slideCurrent');
      } else if ( i == current-1 ) {
        $(e).addClass('slidePrev');
      } else if ( i == current+1 ) {
        $(e).addClass('slideNext');
      } else if ( i < current-1 ) {
        $(e).addClass('slideFarPrev');
      } else if ( i > current+1 ) {
        $(e).addClass('slideFarNext');
      }
    } );

    // make visible changes
    window.location.hash = slideList[current].id;
    scale();
  }

  // next slide
  function nextSlide() {
    if( current < slideList.length-1 ) {
      goToSlide(current+1);
    }
  }

  // previous slide
  function prevSlide() {
    if( current > 0 ) {
      goToSlide(current-1);
    }
  }

  function parseSteps(s) {
    var passTwo = [], steps = [],
        items = s.split(','),
        toEnd = /^(\d+)-$/,
        fromBegin = /^-(\d+)$/,
        range = /^(\d+)-(\d+)$/,
        num   = /^(\d+)$/,
        i, j, m;
    for( i = 0; i < items.length; ++i ) {
      // range
      m = range.exec( items[i] );
      if( m ) {
        if( m[1] == 0 ) {
          throw 'Steps start at 1';
        }
        for( j = m[1]; j <= m[2]; j++ ) {
          steps[j-1] = true;
        }
        continue;
      }

      // single step
      m = num.exec( items[i] );
      if( m ) {
        if( m[1] == 0 ) {
          throw 'Steps start at 1';
        }
        steps[m[1]-1] = true;
        continue;
      }

      // invalid
      throw 'Invalid step set:' + s;
    }

    return steps;
  }

  // add svg overlay to current slide
  function addOverlay( slide, callback ) {
    var o = $('

').addClass('svgOverlay');
    $(slide).append(o);
    function initOverlay(svg) {
      var d,m,i;
      d = svg.defs('myDefs');
      for( var i=0; i<acolor.length; i++ ) {
        m = svg.marker(d,acolor[i]+'Arrow',3,2,4,4,'auto');
        svg.polyline(m,[[0,0], [4,2],[0,4],[1,2]], { fill: acolor[i] } );
      }
      callback(svg);
    }
    o.svg( { onLoad: initOverlay } );
  }
  // get svg handler for slide
  function getOverlay( slide ) {
    return $(slide).find('.svgOverlay').svg('get');
  }
  // draw an arrow
  function arrow(svg,x1,y1,x2,y2, options) {
    svg.line( x1, y1, x2, y2, $.extend( { strokeWidth: 5, opacity: 0.75 }, options ) );
  }
  // connect two elements on the slide with an arrow
  function arrowFromTo( slide, from, to, options ) {
    var f = $(from).offset(), t = $(to).offset(), s = $(slide).offset(),
        x1 = ( f.left - s.left )/scaleFactor + $(from).width()/2,
        x2 = ( t.left - s.left )/scaleFactor + $(to).width()/2,
        y1 = ( f.top - s.top )/scaleFactor + $(from).height()/2,
        y2 = ( t.top - s.top )/scaleFactor + $(to).height()/2;
    arrow(getOverlay(slide),x1,y1,x2,y2,options);
  }
  // draw an ellipse around an element on the slide
  function ellipseAround( slide, to, options ) {
    var t = $(to).offset(), s = $(slide).offset(),
        rx = $(to).width()/2,
        x  = ( t.left - s.left )/scaleFactor  + rx,
        ry = $(to).height()/2,
        y  = ( t.top - s.top )/scaleFactor + ry;
    getOverlay(slide).ellipse(x,y,rx*1.4,ry*1.4,$.extend( { strokeWidth: 5, stroke: 'blue', fill: 'none', opacity: 0.75 }, options ) );
  }

  // initialization
  var slideList, slideClass = [], stepTable, spotLight;
  function init() {
    var i, j, h,
        common,
        handlerList = ['onleave', 'onenter'];

    // build list of slides, remember orignal classes
    slideList = $('div.slide');
    slideList.each( function(i,e) { slideClass[i] = $(e).attr('class') });

    // append common content to all slides
    common = $('.slidecommon').detach();
    slideList.append(common);

    // compile slide event handlers
    slideList.each( function(i,e) {
      var handler;
      for( j = 0; j < handlerList.length; ++j ) {
        handler =  $(e).data(handlerList[j]);
        if( handler ) {
          $(e).data(handlerList[j], new Function(handler) );
        }
      }
    });

    // analyse step-by-step reveal information
    slideList.each( function(i,e) {
      var steps = $(e).data('steps');
      if( steps !== undefined ) {
        $(e).find('[step]').each( function(j,e) {
          // hook into list
        });
      }
    });

    // Spotlight
    spotLight = buildSpotLight(100);

    // honor url hash
    h = window.location.hash.substr(1);
    if( h !== '' ) {
      for( i = 0; i < slideList.length; ++i ) {
        if( slideList[i].id === h ) {
          goToSlide(i);
          break;
        }
      }
      if( i == slideList.length ) {
        // not found
        alert( h + " not found" );
        goToSlide(0);
      }
    } else {
      goToSlide(0);
    }
    $(window).resize(scale);
    scale();

    // add event handlers
    var frozen = false;
    $(document).keyup( function(e) {
      if( frozen ) { return; }
      switch(e.which) {
        case 34: // page down
        case 39: // crsr right
        case 40: // crsr down
        case 32: // space
          nextSlide(); break;
        case 8 : // backspace
        case 33: // page up
        case 37: // crsr left
        case 38: // crsr up
          prevSlide(); break;
        case 35: // end
          goToSlide(slideList.length-1); break;
        case 36: // home
          goToSlide(0); break;
        case 83 : // s
          spotLight.toggle(); break;
      }
    } );

    // polulate arrow style list
    for( var i=0; i<acolor.length; i++ ) {
      astyle[acolor[i]] = { markerEnd: 'url(#'+acolor[i]+'Arrow)', strokeWidth: 5, stroke: acolor[i] };
    }
  }

  return {
    init : init,
    nextSlide : nextSlide,
    prevSlide : prevSlide,
    freeze    : function() { frozen = true; },
    unfreeze  : function() { frozen = false; },
    addOverlay   : addOverlay,
    getOverlay   : getOverlay,
    arrow        : arrow,
    arrowFromTo  : arrowFromTo,
    ellipseAround: ellipseAround,
    astyle : astyle,
    getStatus : function() { return [ current, slideList, spotLight ]; }
  };
})();

$(jslide.init);

<|endoftext|>


<commit_before>/*
 * Artefact Web Extensions
 *
 * Copyright 2012, Artefact Group LLC
 * Licensed under MIT.
 */

(function(Awe, global, document, undefined) {

  // = Awe.StateMachine =
  //
  // A general state machine. More documentation to come...
  //
  // State contains any of:
  //  {{{allowOnly}}} - array with 0 or more states (or null)
  //  {{{doNotAllow}}} - array with 1 or more states (or null)
  //  {{{start}}} function (or null)
  //  {{{update}}} function (or null)
  //  {{{end}}} function (or null)

  var StateMachine = Awe.StateMachine = function(name, stateMap, initialStateId) {
    var _i = this;

    function _sm_trace(str) { console.log("[awe.sm] " + str); }
    function _sm_trace_na(from,to) { _sm_trace(from + " -> " + to + " not allowed"); }
    function _sm_trace_e(s) { _sm_trace("enter : " + s); }
    function _sm_trace_x(s) { _sm_trace("exit  : " + s); }

    StateMachine.stateMachines.push(_i);

    _i.name = name;
    _i.states = stateMap || [];
    _i.currentStateId = null;

    _i.tracing = false;

    _i.addState = function(id, state) {
      if (_i.states[id]) {
        throw "Duplicate state added!";
      }
      _i.states[id] = state;
    }

    _i.getCurrentStateId = function() {
      return _i.currentStateId;
    }

    // Request a state that is assumed to be a transitional state and call the supplied callback on completion.
    // The callback will not be called if the transition state is interrupted, but you can prevent this by making
    // the transition state uninterruptable: pass an empty array in the transition states allowOnly field, which will
    // disallow any transitions while the state is active. The transitionCompleteCallback should then change state
    // once the transition is complete.
    _i.requestTransitionState = function(id) {

      if (typeof(arguments[arguments.length - 1]) != "function") {
        throw "Last argument of StateMachine.requestTransitionState must be an on-complete callback"
      }

      if (_i.requestState.apply(_i, arguments)) {
        _i.transitionCompleteCallback = arguments[arguments.length - 1];

        if (!_i.states[_i.currentStateId].update) {
          throw "ERROR: Transition states must have an update method, otherwise they will never be able to complete.";
        }
        return true;
      }

      // Remove the transition complete callback if the switch to the transition state was refused.
      _i.transitionCompleteCallback = null;
      return false;
    }

    // Request a change to the supplied state. If a current state exists that will be checked for any conditions that
    // disallow transition to the new state.
    _i.requestState = function(id) {

      if(!id) throw 'Cannot request a null state';

      var nextState = _i.states[id];

      if (!nextState) throw 'Specified state does not exist';

      if (_i.currentStateId) {
        var currentState = _i.states[_i.currentStateId];

        if (!_i.currentStateDone && currentState.allowOnly && currentState.allowOnly.indexOf(id) < 0) {
          if(_i.tracing) _sm_trace_na(_i.currentStateId, id);
          return false;
        }
        if (!_i.currentStateDone && currentState.doNotAllow && currentState.doNotAllow.indexOf(id) >= 0) {
          if(_i.tracing) _sm_trace_na(_i.currentStateId, id)
          return false;
        }

        if (currentState.end) {
          if(_i.tracing) _sm_trace_x(_i.currentStateId);
          currentState.end.call(currentState, id);
        }
      }

      if (nextState) {
        nextState._startTime = Date.now();
        nextState.runTime = 0;
        if (nextState.start) {
          if(_i.tracing) _sm_trace_e(_i.currentStateId);
          nextState.start.apply(nextState, [_i.currentState && _i.currentState.id].concat(Array.prototype.slice.call(arguments,1)));
        }
      }

      _i.currentStateId = id;

      return true;
    }

    _i.update = function() {
      var currentState = _i.states[_i.currentStateId];
      currentState.runTime = (Date.now() - currentState._startTime) * 0.001;
      if (currentState && currentState.update) {
        // Update the current state and if it's a transition state, call the transition state callback once the
        // transition state's update returns true to signify completion
        if (currentState.update.call(currentState) && _i.transitionCompleteCallback) {
          var callback = _i.transitionCompleteCallback;
          _i.transitionCompleteCallback = null;
          _i.currentStateDone = true;
          callback();
          _i.currentStateDone = false;
        }
      }
    }

    if (initialStateId) {
      _i.requestState(initialStateId);
    }

    return _i;
  }

  StateMachine.stateMachines = []
  StateMachine.update = function() {
    for (var i = 0; i < StateMachine.stateMachines.length; ++i) {
      StateMachine.stateMachines[i].update();
    }
  }
})(Awe, this, document)
<commit_msg>Fix bugs in awe-sm tracing<commit_after>/*
 * Artefact Web Extensions
 *
 * Copyright 2012, Artefact Group LLC
 * Licensed under MIT.
 */

(function(Awe, global, document, undefined) {

  // = Awe.StateMachine =
  //
  // A general state machine. More documentation to come...
  //
  // State contains any of:
  //  {{{allowOnly}}} - array with 0 or more states (or null)
  //  {{{doNotAllow}}} - array with 1 or more states (or null)
  //  {{{start}}} function (or null)
  //  {{{update}}} function (or null)
  //  {{{end}}} function (or null)

  var StateMachine = Awe.StateMachine = function(name, stateMap, initialStateId) {
    var _i = this;

    function _sm_trace(str) { console.log("[awe.sm] " + str); }
    function _sm_trace_na(from,to) { _sm_trace(from + " -> " + to + " not allowed"); }
    function _sm_trace_e(s) { _sm_trace("enter : " + s); }
    function _sm_trace_x(s) { _sm_trace("exit  : " + s); }

    StateMachine.stateMachines.push(_i);

    _i.name = name;
    _i.states = stateMap || [];
    _i.currentStateId = null;

    _i.tracing = false;

    _i.addState = function(id, state) {
      if (_i.states[id]) {
        throw "Duplicate state added!";
      }
      _i.states[id] = state;
    }

    _i.getCurrentStateId = function() {
      return _i.currentStateId;
    }

    // Request a state that is assumed to be a transitional state and call the supplied callback on completion.
    // The callback will not be called if the transition state is interrupted, but you can prevent this by making
    // the transition state uninterruptable: pass an empty array in the transition states allowOnly field, which will
    // disallow any transitions while the state is active. The transitionCompleteCallback should then change state
    // once the transition is complete.
    _i.requestTransitionState = function(id) {

      if (typeof(arguments[arguments.length - 1]) != "function") {
        throw "Last argument of StateMachine.requestTransitionState must be an on-complete callback"
      }

      if (_i.requestState.apply(_i, arguments)) {
        _i.transitionCompleteCallback = arguments[arguments.length - 1];

        if (!_i.states[_i.currentStateId].update) {
          throw "ERROR: Transition states must have an update method, otherwise they will never be able to complete.";
        }
        return true;
      }

      // Remove the transition complete callback if the switch to the transition state was refused.
      _i.transitionCompleteCallback = null;
      return false;
    }

    // Request a change to the supplied state. If a current state exists that will be checked for any conditions that
    // disallow transition to the new state.
    _i.requestState = function(id) {

      if(!id) throw 'Cannot request a null state';

      var nextState = _i.states[id];

      if (!nextState) throw 'Specified state does not exist';

      if (_i.currentStateId) {
        var currentState = _i.states[_i.currentStateId];

        if (!_i.currentStateDone && currentState.allowOnly && currentState.allowOnly.indexOf(id) < 0) {
          if(_i.tracing) _sm_trace_na(_i.currentStateId, id);
          return false;
        }
        if (!_i.currentStateDone && currentState.doNotAllow && currentState.doNotAllow.indexOf(id) >= 0) {
          if(_i.tracing) _sm_trace_na(_i.currentStateId, id)
          return false;
        }

        if(_i.tracing) _sm_trace_x(_i.currentStateId);
        if (currentState.end) {
          currentState.end.call(currentState, id);
        }
      }

      if (nextState) {
        nextState._startTime = Date.now();
        nextState.runTime = 0;
        if(_i.tracing) _sm_trace_e(id);
        if (nextState.start) {
          nextState.start.apply(nextState, [_i.currentState && _i.currentState.id].concat(Array.prototype.slice.call(arguments,1)));
        }
      }

      _i.currentStateId = id;

      return true;
    }

    _i.update = function() {
      var currentState = _i.states[_i.currentStateId];
      currentState.runTime = (Date.now() - currentState._startTime) * 0.001;
      if (currentState && currentState.update) {
        // Update the current state and if it's a transition state, call the transition state callback once the
        // transition state's update returns true to signify completion
        if (currentState.update.call(currentState) && _i.transitionCompleteCallback) {
          var callback = _i.transitionCompleteCallback;
          _i.transitionCompleteCallback = null;
          _i.currentStateDone = true;
          callback();
          _i.currentStateDone = false;
        }
      }
    }

    if (initialStateId) {
      _i.requestState(initialStateId);
    }

    return _i;
  }

  StateMachine.stateMachines = []
  StateMachine.update = function() {
    for (var i = 0; i < StateMachine.stateMachines.length; ++i) {
      StateMachine.stateMachines[i].update();
    }
  }
})(Awe, this, document)
<|endoftext|>


<commit_before>$(function() {
    $.widget("sjl.jsnake", {
	options: {
	    update_interval: 500
	},

	// These double as character codes for the keypresses.
	LEFT: 37,
	UP: 38,
	RIGHT: 39,
	DOWN: 40,

	_create: function () {
	    var ctx = this.element[0].getContext("2d");
	    this._board_width = 50;
	    this._board_height = 50;

	    this._x = Math.round(this._board_width/2);
	    this._y = Math.round(this._board_height/2);

	    this._valid_directions = [this.LEFT, this.RIGHT,
				     this.DOWN, this.UP];

	    this._direction = this.RIGHT;

	    this._snake = [{x: this._x, y: this._y,
			    direction: this._direction}];

	    if (ctx) {
		this.element.css("border", "1px solid black");
		setTimeout($.proxy(this.update, this),
			   this.options.update_interval);
		this._square_side = this.element.width()/this._board_width;
		this._ctx = ctx;
		$(document).on('keydown',
				$.proxy(function (e) {
				    if (this._valid_directions.indexOf(
					e.which) != -1)
					this._change_direction(e.which);
				} ,
					this));
	    }
	},

	_change_direction: function (new_direction) {
	    this._direction = new_direction;
	},

	_clear_square: function (x, y) {
	    this._ctx.clearRect(x * this._square_side, y * this._square_side,
				this._square_side, this._square_side);
	},

	_draw_square: function (x, y) {
	    this._ctx.fillStyle = "rgb(200, 0, 0)";
	    this._ctx.fillRect(x * this._square_side, y * this._square_side,
			       this._square_side, this._square_side);
	},

	_snake_still_legal: function () {
	    if (this._x < 0)
		return false;
	    if (this._x > this._board_width)
		return false;
	    if (this._y < 0)
		return false;
	    if (this._y > this._board_height)
		return false;
	    return true;
	},

	_grow_counter: 0,

	_snake_should_grow: function () {
	    return this._grow_counter++ % 3;
	},

	_move_snake: function () {
	    switch (this._direction) {
		case this.LEFT:
		this._x--;
		break;
		case this.RIGHT:
		this._x++;
		break;
		case this.UP:
		this._y--;
		break;
		case this.DOWN:
		this._y++;
		break;
	    }

	    if (!this._snake_should_grow()) {
		var last = this._snake.pop();
		this._clear_square(last.x, last.y);
	    }

	    this._snake.unshift({x: this._x, y: this._y,
				 direction: this._direction})
	    if (this._snake_still_legal()) {
		this._draw_square(this._x, this._y);
		return false;
	    } else {
		return true;
	    }
	},

	update: function () {
	    var at_end = this._move_snake();
	    if (!at_end) {
		setTimeout($.proxy(this.update, this),
			   this.options.update_interval);
	    } else {
		alert("dead meat.");
	    }
	}
    });
});
<commit_msg>Snake can collide with itself.<commit_after>$(function() {
    $.widget("sjl.jsnake", {
	options: {
	    update_interval: 500
	},

	// These double as character codes for the keypresses.
	LEFT: 37,
	UP: 38,
	RIGHT: 39,
	DOWN: 40,

	_create: function () {
	    var ctx = this.element[0].getContext("2d");
	    this._board_width = 50;
	    this._board_height = 50;

	    this._x = Math.round(this._board_width/2);
	    this._y = Math.round(this._board_height/2);

	    this._valid_directions = [this.LEFT, this.RIGHT,
				     this.DOWN, this.UP];

	    this._direction = this.RIGHT;

	    this._snake = [{x: this._x, y: this._y,
			    direction: this._direction}];

	    if (ctx) {
		this.element.css("border", "1px solid black");
		setTimeout($.proxy(this.update, this),
			   this.options.update_interval);
		this._square_side = this.element.width()/this._board_width;
		this._ctx = ctx;
		$(document).on('keydown',
				$.proxy(function (e) {
				    if (this._valid_directions.indexOf(
					e.which) != -1)
					this._change_direction(e.which);
				} ,
					this));
	    }
	},

	_change_direction: function (new_direction) {
	    this._direction = new_direction;
	},

	_clear_square: function (x, y) {
	    this._ctx.clearRect(x * this._square_side, y * this._square_side,
				this._square_side, this._square_side);
	},

	_draw_square: function (x, y) {
	    this._ctx.fillStyle = "rgb(200, 0, 0)";
	    this._ctx.fillRect(x * this._square_side, y * this._square_side,
			       this._square_side, this._square_side);
	},

	_occupied_by_snake: function (x, y) {
	    for (var ii = 0; ii < this._snake.length; ii++) {
		var joint = this._snake[ii];
		if (joint.x == x && joint.y == y)
		    return true;
	    }
	    return false;
	},

	_snake_still_legal: function () {
	    if (this._x < 0)
		return false;
	    if (this._x > this._board_width)
		return false;
	    if (this._y < 0)
		return false;
	    if (this._y > this._board_height)
		return false;

	    if (this._occupied_by_snake(this._x, this._y))
		return false;
	    return true;
	},

	_grow_counter: 0,

	_snake_should_grow: function () {
	    return this._grow_counter++ % 3;
	},

	_move_snake: function () {
	    switch (this._direction) {
		case this.LEFT:
		this._x--;
		break;
		case this.RIGHT:
		this._x++;
		break;
		case this.UP:
		this._y--;
		break;
		case this.DOWN:
		this._y++;
		break;
	    }

	    if (!this._snake_should_grow()) {
		var last = this._snake.pop();
		this._clear_square(last.x, last.y);
	    }

	    if (this._snake_still_legal()) {
		this._snake.unshift({x: this._x, y: this._y,
				     direction: this._direction})
		this._draw_square(this._x, this._y);
		return false;
	    } else {
		return true;
	    }
	},

	update: function () {
	    var at_end = this._move_snake();
	    if (!at_end) {
		setTimeout($.proxy(this.update, this),
			   this.options.update_interval);
	    } else {
		alert("dead meat.");
	    }
	}
    });
});
<|endoftext|>


<commit_before>var express = require('express');
var router = express.Router();
var passport = require('passport');

var indexCtrl = require('../controllers/index.ctrl');
var userCtrl = require('../controllers/user.ctrl');
var coursesCtrl = require('../controllers/courses.ctrl');

/* API routes */
router.get('/courses', coursesCtrl.list);
router.post('/courses', coursesCtrl.create);
router.post('/courses/:courseId', coursesCtrl.edit);

/* Frontend routes */
router.get('/', indexCtrl.getIndex);

router.get('/join', userCtrl.getRegister);
router.post('/register', userCtrl.register);
router.get('/login', userCtrl.getLogin);
router.post('/login', passport.authenticate('local', { successRedirect: '/', failureRedirect: '/login' }));

router.get('/profile', userCtrl.getUser);
router.get('/new', coursesCtrl.getCreate);
router.get('/:username', coursesCtrl.getOwnCourses);
router.get('/:username/:courseId', coursesCtrl.getCourse);
router.get('/:username/:courseId/new', coursesCtrl.getNewSection);
router.get('/:username/:courseId/:sectionId', coursesCtrl.getSection);

module.exports = router;
<commit_msg>add edit course route<commit_after>var express = require('express');
var router = express.Router();
var passport = require('passport');

var indexCtrl = require('../controllers/index.ctrl');
var userCtrl = require('../controllers/user.ctrl');
var coursesCtrl = require('../controllers/courses.ctrl');

/* API routes */
router.get('/courses', coursesCtrl.list);
router.post('/courses', coursesCtrl.create);
router.post('/courses/:courseId', coursesCtrl.edit);

/* Frontend routes */
router.get('/', indexCtrl.getIndex);

router.get('/join', userCtrl.getRegister);
router.post('/register', userCtrl.register);
router.get('/login', userCtrl.getLogin);
router.post('/login', passport.authenticate('local', { successRedirect: '/', failureRedirect: '/login' }));

router.get('/profile', userCtrl.getUser);
router.get('/new', coursesCtrl.getCreate);
router.get('/:username', coursesCtrl.getOwnCourses);
router.get('/:username/:courseId', coursesCtrl.getCourse);
router.get('/:username/:courseId/edit', coursesCtrl.getEditCourse);
router.get('/:username/:courseId/new', coursesCtrl.getNewSection);
router.get('/:username/:courseId/:sectionId', coursesCtrl.getSection);

module.exports = router;
<|endoftext|>


<commit_before>(function($, _, Backbone) {

	var template = _.template(
		'<% if (title) { %>\

\
			<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>\

<%=title%>
\

\
		<% } %>\

<% if(body) { %><%=body%><% } %>
\

\
			<% if (cancelText) { %>\
			<%=cancelText%>\
			<% } %>\
			<%=okText%>\

');

	var Modal = Backbone.View.extend({

	    className: 'modal fade',

	    events: {
		    'click .cancel': function(e){
			    this.trigger('cancel', this);
		    },
		    'click .ok': function(e){
			    this.trigger('ok', this);
		    }
	    },

		_modalOptions: {},

		body: null,

	    /**
	     * Creates an instance of a Bootstrap Modal
	     * @param {Object} options
	     * @param {String|View} [options.body] Modal content. Default: none
	     * @param {String} [options.title]        Title. Default: none
	     * @param {String} [options.okText]       Text for the OK button. Default: 'OK'
	     * @param {String} [options.cancelText]   Text for the cancel button. Default: 'Cancel'. If passed a falsey value, the button will be removed
	     * @param {Function} [options.template]   Compiled underscore template to override the default one
	     */
	    initialize: function(options) {
			if(options && options.options){
			    this._modalOptions = options.options;
			    delete options.options;
			}
		    if(options && options.content){
			    options.body = options.content;
			    delete options.content;
		    }
		    if(options.body && options.body.$el){
			    this.body = options.body;
			    delete options.body;
		    }
			this.options = _.extend({
				title: null,
				body: null,
				okText: 'OK',
				cancelText: 'Отмена',
				template: template
			}, options);

			_.bindAll(this, '_shown', '_hidden');
		    var _this = this;
			this.$el
			    .on('shown', this._shown)
			    .on('hidden', this._hidden)
			    .on('show shown hide hidden', function(e){
				    _this.trigger(e.type, this);
			    });
		    this.on('all', this._bodyProxyEvent, this);
	    },

		_bodyProxyEvent: function(event){
			if(this.body && this.body.trigger){
				this.body.trigger(event, this);
			}
		},

	    render: function() {
	      this.$el.html(this.options.template(this.options));
	      if (this.body && this.body.$el) {
		      this.body.render();
	          this.$('.modal-body').append(this.body.$el);
	      }
		  this.$el.modal(this._modalOptions);
	      this.isRendered = true;
	      return this;
	    },

	    show: function() {
			if (!this.isRendered) this.render();
			this.$el.modal('show');
			return this;
	    },

	    hide: function() {
	        this.$el.modal('hide');
		    return this;
	    },

		toggle: function(){
			this.$el.modal('toggle');
			return this;
		},

		_hidden: function(){
			Modal.count--;
		},

		_shown: function(){
			Modal.count++;
			//Adjust the modal and backdrop z-index; for dealing with multiple modals
			var	numModals = Modal.count,
				$backdrop = $('.modal-backdrop:eq('+numModals+')'),
				backdropIndex = parseInt($backdrop.css('z-index'),10),
				elIndex = parseInt($backdrop.css('z-index'), 10);

			$backdrop.css('z-index', backdropIndex + numModals);
			this.$el.css('z-index', elIndex + numModals);
		}
	},
	{
	    //STATICS The number of modals on display
	    count: 0
	}
	);

	//EXPORTS
	//CommonJS
	if (typeof require == 'function' && typeof module !== 'undefined' && exports) {
		module.exports = Modal;
	}
	//AMD / RequireJS
	if (typeof define === 'function' && define.amd) {
		return define(function() {
		    Backbone.TbModal = Backbone.BootstrapModal = Modal;
		})
	}
	//Regular; add to Backbone
	else {
		Backbone.TbModal = Backbone.BootstrapModal = Modal;
	}

}(jQuery, _, Backbone));<commit_msg>BS3 compatibility<commit_after>(function($, _, Backbone) {

	var template = _.template(
		'
\

\
		<% if (title) { %>\

\
			<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>\

<%=title%>
\

\
		<% } %>\

<% if(body) { %><%=body%><% } %>
\

\
			<% if (cancelText) { %>\
			<%=cancelText%>\
			<% } %>\
			<a href="<%=url%>" class="btn btn-warning ok"><%=okText%>\

\

\

\
		');

	var Modal = Backbone.View.extend({

			className: 'modal fade',

			events: {
				'click .cancel': function(e){
					this.trigger('cancel', this);
				},
				'click .ok': function(e){
					this.trigger('ok', this);
				}
			},

			_modalOptions: {},

			body: null,

			/**
			 * Creates an instance of a Bootstrap Modal
			 * @param {Object} options
			 * @param {String|View} [options.body] Modal content. Default: none
			 * @param {String} [options.title]        Title. Default: none
			 * @param {String} [options.okText]       Text for the OK button. Default: 'OK'
			 * @param {String} [options.cancelText]   Text for the cancel button. Default: 'Cancel'. If passed a falsey value, the button will be removed
			 * @param {Function} [options.template]   Compiled underscore template to override the default one
			 */
			initialize: function(options) {
				if(options && options.options){
					this._modalOptions = options.options;
					delete options.options;
				}
				if(options && options.content){
					options.body = options.content;
					delete options.content;
				}
				if(options.body && options.body.$el){
					this.body = options.body;
					delete options.body;
				}
				this.options = _.extend({
					title: null,
					body: null,
					okText: 'OK',
					cancelText: 'Отмена',
					template: template,
					url: '#'
				}, options);

				_.bindAll(this, '_shown', '_hidden');
				var _this = this;
				this.$el
					.on('shown.bs.modal', this._shown)
					.on('hidden.bs.modal', this._hidden)
					.on('show.bs.modal shown.bs.modal hide.bs.modal hidden.bs.modal', function(e){
						_this.trigger(e.type, this);
					});
				this.on('all', this._bodyProxyEvent, this);
			},

			/**
			 * Proxy all events to the Modal.body
			 * @param event
			 * @private
			 */
			_bodyProxyEvent: function(event){
				if(this.body && this.body.trigger){
					this.body.trigger(event, this);
				}
			},

			render: function() {
				this.$el.html(this.options.template(this.options));
				if (this.body && this.body.$el) {
					this.body.render();
					this.$('.modal-body').append(this.body.$el);
				}
				this.$el.modal(this._modalOptions);
				this.isRendered = true;
				this.trigger('render', this);
				return this;
			},

			show: function() {
				if (!this.isRendered) this.render();
				this.$el.modal('show');
				return this;
			},

			hide: function() {
				this.$el.modal('hide');
				return this;
			},

			toggle: function(){
				this.$el.modal('toggle');
				return this;
			},

			_hidden: function(){
				Modal.count--;
			},

			_shown: function(){
				Modal.count++;
				//Adjust the modal and backdrop z-index; for dealing with multiple modals
				var	numModals = Modal.count,
					$backdrop = $('.modal-backdrop:eq('+numModals+')'),
					backdropIndex = parseInt($backdrop.css('z-index'),10),
					elIndex = parseInt($backdrop.css('z-index'), 10);

				$backdrop.css('z-index', backdropIndex + numModals);
				this.$el.css('z-index', elIndex + numModals);
			}
		},
		{
			//STATICS The number of modals on display
			count: 0
		}
	);

	//EXPORTS
	//CommonJS
	if (typeof require == 'function' && typeof module !== 'undefined' && exports) {
		module.exports = Modal;
	}
	//AMD / RequireJS
	if (typeof define === 'function' && define.amd) {
		return define(function() {
			Backbone.TbModal = Backbone.BootstrapModal = Modal;
		})
	}
	//Regular; add to Backbone
	else {
		Backbone.TbModal = Backbone.BootstrapModal = Modal;
	}

}(jQuery, _, Backbone));<|endoftext|>


<commit_before>"use strict";

if (chrome.storage && Settings.get("vimSync") === true) setTimeout(function() {
  Settings.Sync = {
    storage: chrome.storage.sync,
    doNotSync: ["settingsVersion", "previousVersion", "keyboard"],
    fetchAsync: function() {
      var _this = this;
      this.storage.get(null, function(items) {
        var key, value, hasOwn;
        if (chrome.runtime.lastError) {
          return chrome.runtime.lastError;
        }
        hasOwn = Object.prototype.hasOwnProperty;
        for (key in items) {
          if (!hasOwn.call(items, key)) continue;
          value = items[key];
          _this.storeAndPropagate(key, value);
        }
      });
    },
    HandleStorageUpdate: function(changes) {
      var change, key;
      var _this = Settings.Sync, func = Object.prototype.hasOwnProperty;
      for (key in changes) {
        if (!func.call(changes, key)) continue;
        change = changes[key];
        _this.storeAndPropagate(key, change != null ? change.newValue : undefined);
      }
    },
    storeAndPropagate: function(key, value) {
      var defaultValue, defaultValueJSON;
      if (!(key in Settings.defaults)) {
        return;
      }
      if (!this.shouldSyncKey(key)) {
        return;
      }
      if (value && key in localStorage && localStorage[key] === value) {
        return;
      }
      defaultValue = Settings.defaults[key];
      defaultValueJSON = JSON.stringify(defaultValue);
      if (value && value !== defaultValueJSON) {
        value = JSON.parse(value);
      } else {
        value = defaultValue;
      }
      Settings.set(key, value);
    },
    set: function(key, value) {
      if (this.shouldSyncKey(key)) {
        var settings = {};
        settings[key] = value;
        this.storage.set(settings);
      }
    },
    clear: function(key) {
      if (this.shouldSyncKey(key)) {
        this.storage.remove(key);
      }
    },
    shouldSyncKey: function(key) {
      return this.doNotSync.index(key) < 0;
    }
  };
  chrome.storage.onChanged.addListener(Settings.Sync.HandleStorageUpdate);
  Settings.Sync.fetchAsync();
}, 100);

if (chrome.browserAction) setTimeout(function() {
  var func;
  g_requestHandlers.SetIcon = function(tabId, type, pass) {
    chrome.browserAction.setIcon({
      tabId: tabId,
      path: Settings.icons[type ||
        (pass === null ? "enabled" : pass ? "partial" : "disabled")]
    });
  };
  func = Settings.updateHooks.showActionIcon;
  Settings.updateHooks.showActionIcon = function (value) {
    func.call(Settings, value);
    if (value) {
      chrome.browserAction.setTitle({
        title: "Vimium++"
      });
      chrome.browserAction.enable();
    } else {
      chrome.browserAction.disable();
      chrome.browserAction.setTitle({
        title: "Vimium++\nThis icon is not in use"
      });
    }
  };
  Settings.postUpdate("showActionIcon");
}, 50);

if (chrome.omnibox) setTimeout(function() {
  var last, firstUrl, lastSuggest, spanRe = /<(\/?)span(?: [^>]+)?>/g,
  tempRequest, timeout = 0,
  defaultSug = { description: "<dim>Open: </dim><url>%s</url>" },
  format = function(sug) {
    var str;
    if (sug.description) {
      str = sug.description;
    } else {
      str = "<url>" + sug.textSplit.replace(spanRe, "<$1match>");
      str += sug.title ? "</url><dim> - " + Utils.escapeText(sug.title) + "</dim>"
        : "</url>";
    }
    return {
      content: sug.url,
      description: str
    }
  },
  clean = function() {
    firstUrl = "";
    last = null;
    if (lastSuggest) {
      lastSuggest.isOff = true;
      lastSuggest = null;
    }
    tempRequest = null;
  },
  onTimer = function() {
    timeout = 0;
    var arr;
    if (arr = tempRequest) {
      tempRequest = null;
      onInput(arr[0], arr[1]);
    }
  },
  onComplete = function(suggest, response) {
    if (!lastSuggest || suggest.isOff) { return; }
    if (suggest === lastSuggest) { lastSuggest = null; }
    var sug = response[0];
    if (!sug || sug.type !== "search") {
      chrome.omnibox.setDefaultSuggestion(defaultSug);
    } else {
      firstUrl = sug.url;
      var text = sug.titleSplit.replace(spanRe, "");
      text = Utils.escapeText(text.substring(0, text.indexOf(":")));
      text = "<dim>" + text + " - </dim><url>" +
        sug.textSplit.replace(spanRe, "<$1match>") + "</url>";
      chrome.omnibox.setDefaultSuggestion({ description: text });
      response.shift();
      if (sug = response[0]) switch (sug.type) {
      case "math":
        sug.description = "<dim>" + sug.textSplit + " = </dim><url><match>" +
          sug.titleSplit + "</match></url>";
        break;
      }
    }
    response = response.map(format);
    suggest(response);
  },
  onInput = function(key, suggest) {
    key && (key = key.trim());
    if (key === last) { return; }
    lastSuggest && (lastSuggest.isOff = true);
    if (timeout) {
      tempRequest = [key, suggest];
      return;
    }
    timeout = setTimeout(onTimer, 500);
    firstUrl = "";
    last = key;
    lastSuggest = suggest;
    Completers.omni.filter(key ? key.split(Utils.spacesRe) : [], {
      clientWidth: 0,
      maxResults: 6,
      showFavIcon: false
    }, onComplete.bind(null, suggest));
  };
  chrome.omnibox.onInputChanged.addListener(onInput);
  chrome.omnibox.onInputEntered.addListener(function(text, disposition) {
    if (text === last && firstUrl) { text = firstUrl; }
    clean();
    switch (disposition) {
    case "currentTab":
      g_requestHandlers.openUrlInCurrentTab({ url: text });
      break;
    case "newForegroundTab": case "newBackgroundTab":
      chrome.tabs.query({currentWindow: true, active: true},
      g_requestHandlers.openUrlInNewTab.bind(null, {
        active: disposition === "newForegroundTab",
        url: text
      }));
      break;
    }
  });
}, 1500);

// According to tests: onInstalled will be executed after 0 ~ 16 ms if needed
chrome.runtime.onInstalled.addListener(function(details) {
window.b = setTimeout(function() {
  var reason = details.reason, func;
  if (reason === "install") { reason = ""; }
  else if (reason === "update") { reason = details.previousVersion; }
  else { return; }
  if (Settings.CONST.Timer > 0) {
    clearTimeout(Settings.CONST.Timer);
    Settings.CONST.Timer = 0;
  }

  chrome.tabs.query({
    status: "complete"
  }, function(tabs) {
    var _i = tabs.length, tabId, _j, _len, callback, url, t = chrome.tabs, ref, contentScripts, js;
    callback = function() { return chrome.runtime.lastError; };
    contentScripts = chrome.runtime.getManifest().content_scripts[0];
    ref = {file: "", allFrames: contentScripts.all_frames};
    js = contentScripts.js;
    js.pop();
    for (; 0 <= --_i; ) {
      url = tabs[_i].url;
      if (url.startsWith("chrome") || url.indexOf("://") === -1) continue;
      tabId = tabs[_i].id;
      for (_j = 0, _len = js.length; _j < _len; ++_j) {
        ref.file = js[_j];
        t.executeScript(tabId, ref, callback);
      }
    }
    console.log("%cVimium++%c has %cinstalled%c", "color:blue", "color:auto"
      , "color:red", "color:auto;", "with", details, ".");
  });

  if (!reason || !chrome.notifications) { return; }

  func = function(versionA, versionB) {
    var a, b, i, _ref;
    versionA = versionA.split('.');
    versionB = versionB.split('.');
    for (i = 0, _ref = Math.max(versionA.length, versionB.length); i < _ref; ++i) {
      a = parseInt(versionA[i] || 0, 10);
      b = parseInt(versionB[i] || 0, 10);
      if (a < b) {
        return -1;
      } else if (a > b) {
        return 1;
      }
    }
    return 0;
  };
  if (func(Settings.CONST.CurrentVersion, reason) <= 0) { return; }

  reason = "vimium++_upgradeNotification";
  chrome.notifications.create(reason, {
    type: "basic",
    iconUrl: chrome.runtime.getURL("icons/icon128.png"),
    title: "Vimium++ Upgrade",
    message: "Vimium++ has been upgraded to version " + Settings.CONST.CurrentVersion
      + ". Click here for more information.",
    isClickable: true
  }, function(notificationId) {
    if (chrome.runtime.lastError) {
      return chrome.runtime.lastError;
    }
    reason = notificationId || reason;
    chrome.notifications.onClicked.addListener(function(id) {
      if (id !== reason) { return; }
      g_requestHandlers.focusOrLaunch({
        url: "https://github.com/gdh1995/vimium-plus#release-notes"
      });
    });
  });
}, 500);
});

setTimeout(function() {
  chrome.runtime.onInstalled.removeListener(window.b);
  window.b = null;
}, 200);

//* #if DEBUG
var a, b, c, cb, log;
cb = function(b) { a = b; console.log(b); };
setTimeout(function() {
  a = c = null; b = cb; log = function() {
    console.log.apply(console, arguments);
  };
}, 2000); // #endif */
<commit_msg>Chrome omnibox: add support to sessionId<commit_after>"use strict";

if (chrome.storage && Settings.get("vimSync") === true) setTimeout(function() {
  Settings.Sync = {
    storage: chrome.storage.sync,
    doNotSync: ["settingsVersion", "previousVersion", "keyboard"],
    fetchAsync: function() {
      var _this = this;
      this.storage.get(null, function(items) {
        var key, value, hasOwn;
        if (chrome.runtime.lastError) {
          return chrome.runtime.lastError;
        }
        hasOwn = Object.prototype.hasOwnProperty;
        for (key in items) {
          if (!hasOwn.call(items, key)) continue;
          value = items[key];
          _this.storeAndPropagate(key, value);
        }
      });
    },
    HandleStorageUpdate: function(changes) {
      var change, key;
      var _this = Settings.Sync, func = Object.prototype.hasOwnProperty;
      for (key in changes) {
        if (!func.call(changes, key)) continue;
        change = changes[key];
        _this.storeAndPropagate(key, change != null ? change.newValue : undefined);
      }
    },
    storeAndPropagate: function(key, value) {
      var defaultValue, defaultValueJSON;
      if (!(key in Settings.defaults)) {
        return;
      }
      if (!this.shouldSyncKey(key)) {
        return;
      }
      if (value && key in localStorage && localStorage[key] === value) {
        return;
      }
      defaultValue = Settings.defaults[key];
      defaultValueJSON = JSON.stringify(defaultValue);
      if (value && value !== defaultValueJSON) {
        value = JSON.parse(value);
      } else {
        value = defaultValue;
      }
      Settings.set(key, value);
    },
    set: function(key, value) {
      if (this.shouldSyncKey(key)) {
        var settings = {};
        settings[key] = value;
        this.storage.set(settings);
      }
    },
    clear: function(key) {
      if (this.shouldSyncKey(key)) {
        this.storage.remove(key);
      }
    },
    shouldSyncKey: function(key) {
      return this.doNotSync.index(key) < 0;
    }
  };
  chrome.storage.onChanged.addListener(Settings.Sync.HandleStorageUpdate);
  Settings.Sync.fetchAsync();
}, 100);

if (chrome.browserAction) setTimeout(function() {
  var func;
  g_requestHandlers.SetIcon = function(tabId, type, pass) {
    chrome.browserAction.setIcon({
      tabId: tabId,
      path: Settings.icons[type ||
        (pass === null ? "enabled" : pass ? "partial" : "disabled")]
    });
  };
  func = Settings.updateHooks.showActionIcon;
  Settings.updateHooks.showActionIcon = function (value) {
    func.call(Settings, value);
    if (value) {
      chrome.browserAction.setTitle({
        title: "Vimium++"
      });
      chrome.browserAction.enable();
    } else {
      chrome.browserAction.disable();
      chrome.browserAction.setTitle({
        title: "Vimium++\nThis icon is not in use"
      });
    }
  };
  Settings.postUpdate("showActionIcon");
}, 50);

if (chrome.omnibox) setTimeout(function() {
  var last, firstUrl, lastSuggest, spanRe = /<(\/?)span(?: [^>]+)?>/g,
  tempRequest, timeout = 0, sessionIds,
  defaultSug = { description: "<dim>Open: </dim><url>%s</url>" },
  formatSessionId = function(sug) {
    if (sug.sessionId != null) {
      sessionIds[sug.url] = sug.sessionId;
    }
  },
  format = function(sug) {
    var str;
    if (sug.description) {
      str = sug.description;
    } else {
      str = "<url>" + sug.textSplit.replace(spanRe, "<$1match>");
      str += sug.title ? "</url><dim> - " + Utils.escapeText(sug.title) + "</dim>"
        : "</url>";
    }
    return {
      content: sug.url,
      description: str
    }
  },
  clean = function() {
    firstUrl = "";
    last = null;
    if (lastSuggest) {
      lastSuggest.isOff = true;
      lastSuggest = null;
    }
    tempRequest = null;
    sessionIds = null;
  },
  onTimer = function() {
    timeout = 0;
    var arr;
    if (arr = tempRequest) {
      tempRequest = null;
      onInput(arr[0], arr[1]);
    }
  },
  onComplete = function(suggest, response) {
    if (!lastSuggest || suggest.isOff) { return; }
    if (suggest === lastSuggest) { lastSuggest = null; }
    var sug = response[0];
    if (!sug || sug.type !== "search") {
      chrome.omnibox.setDefaultSuggestion(defaultSug);
      sessionIds = Utils.makeNullProto();
      response.forEach(formatSessionId);
    } else {
      firstUrl = sug.url;
      var text = sug.titleSplit.replace(spanRe, "");
      text = Utils.escapeText(text.substring(0, text.indexOf(":")));
      text = "<dim>" + text + " - </dim><url>" +
        sug.textSplit.replace(spanRe, "<$1match>") + "</url>";
      chrome.omnibox.setDefaultSuggestion({ description: text });
      response.shift();
      if (sug = response[0]) switch (sug.type) {
      case "math":
        sug.description = "<dim>" + sug.textSplit + " = </dim><url><match>" +
          sug.titleSplit + "</match></url>";
        break;
      }
    }
    response = response.map(format);
    suggest(response);
  },
  onInput = function(key, suggest) {
    key && (key = key.trim());
    if (key === last) { return; }
    lastSuggest && (lastSuggest.isOff = true);
    if (timeout) {
      tempRequest = [key, suggest];
      return;
    }
    timeout = setTimeout(onTimer, 500);
    firstUrl = "";
    sessionIds = null;
    last = key;
    lastSuggest = suggest;
    Completers.omni.filter(key ? key.split(Utils.spacesRe) : [], {
      clientWidth: 0,
      maxResults: 6,
      showFavIcon: false
    }, onComplete.bind(null, suggest));
  };
  chrome.omnibox.onInputChanged.addListener(onInput);
  chrome.omnibox.onInputEntered.addListener(function(text, disposition) {
    if (text === last && firstUrl) { text = firstUrl; }
    var sessionId = sessionIds && sessionIds[text];
    clean();
    if (sessionId != null) {
      if (typeof sessionId === "number") {
        g_requestHandlers.selectTab({ tabId: sessionId });
      } else {
        g_requestHandlers.restoreSession({ sessionId: sessionId });
      }
      return;
    }
    switch (disposition) {
    case "currentTab":
      g_requestHandlers.openUrlInCurrentTab({ url: text });
      break;
    case "newForegroundTab": case "newBackgroundTab":
      chrome.tabs.query({currentWindow: true, active: true},
      g_requestHandlers.openUrlInNewTab.bind(null, {
        active: disposition === "newForegroundTab",
        url: text
      }));
      break;
    }
  });
}, 1500);

// According to tests: onInstalled will be executed after 0 ~ 16 ms if needed
chrome.runtime.onInstalled.addListener(function(details) {
window.b = setTimeout(function() {
  var reason = details.reason, func;
  if (reason === "install") { reason = ""; }
  else if (reason === "update") { reason = details.previousVersion; }
  else { return; }
  if (Settings.CONST.Timer > 0) {
    clearTimeout(Settings.CONST.Timer);
    Settings.CONST.Timer = 0;
  }

  chrome.tabs.query({
    status: "complete"
  }, function(tabs) {
    var _i = tabs.length, tabId, _j, _len, callback, url, t = chrome.tabs, ref, contentScripts, js;
    callback = function() { return chrome.runtime.lastError; };
    contentScripts = chrome.runtime.getManifest().content_scripts[0];
    ref = {file: "", allFrames: contentScripts.all_frames};
    js = contentScripts.js;
    js.pop();
    for (; 0 <= --_i; ) {
      url = tabs[_i].url;
      if (url.startsWith("chrome") || url.indexOf("://") === -1) continue;
      tabId = tabs[_i].id;
      for (_j = 0, _len = js.length; _j < _len; ++_j) {
        ref.file = js[_j];
        t.executeScript(tabId, ref, callback);
      }
    }
    console.log("%cVimium++%c has %cinstalled%c", "color:blue", "color:auto"
      , "color:red", "color:auto;", "with", details, ".");
  });

  if (!reason || !chrome.notifications) { return; }

  func = function(versionA, versionB) {
    var a, b, i, _ref;
    versionA = versionA.split('.');
    versionB = versionB.split('.');
    for (i = 0, _ref = Math.max(versionA.length, versionB.length); i < _ref; ++i) {
      a = parseInt(versionA[i] || 0, 10);
      b = parseInt(versionB[i] || 0, 10);
      if (a < b) {
        return -1;
      } else if (a > b) {
        return 1;
      }
    }
    return 0;
  };
  if (func(Settings.CONST.CurrentVersion, reason) <= 0) { return; }

  reason = "vimium++_upgradeNotification";
  chrome.notifications.create(reason, {
    type: "basic",
    iconUrl: chrome.runtime.getURL("icons/icon128.png"),
    title: "Vimium++ Upgrade",
    message: "Vimium++ has been upgraded to version " + Settings.CONST.CurrentVersion
      + ". Click here for more information.",
    isClickable: true
  }, function(notificationId) {
    if (chrome.runtime.lastError) {
      return chrome.runtime.lastError;
    }
    reason = notificationId || reason;
    chrome.notifications.onClicked.addListener(function(id) {
      if (id !== reason) { return; }
      g_requestHandlers.focusOrLaunch({
        url: "https://github.com/gdh1995/vimium-plus#release-notes"
      });
    });
  });
}, 500);
});

setTimeout(function() {
  chrome.runtime.onInstalled.removeListener(window.b);
  window.b = null;
}, 200);

//* #if DEBUG
var a, b, c, cb, log;
cb = function(b) { a = b; console.log(b); };
setTimeout(function() {
  a = c = null; b = cb; log = function() {
    console.log.apply(console, arguments);
  };
}, 2000); // #endif */
<|endoftext|>