<commit_before>#! /usr/bin/node

var fs = require("fs");
var typ = require("./representation.js");
var tool = require("./tools.js");
var tokenizer = require("./tokenize.js");
var desugarer = require("./desugar.js");
var pprint = require("./pprint.js");
var error = require("./errors.js");

var print = console.log;

function fst(ts) {
	return ts[ts.length-1];
}

function snd(ts) {
	return ts[ts.length-2];
}

/*Checks if the next token is not followed by any of ``checks'' */
function notFollowedBy(tokens, checks, linenum, charnum) {
	if (!fst(tokens)) {
    throw error.JSyntaxError(0,0,"unexpected end of source")
  }
  var nextT = fst(tokens)[0];
	if (checks.some(function (x) {
    return x === nextT;
  }))
		return false;
	else
		return true;
}

/* returns a function that takes a parameter and
   checks if it is in the array ``props''*/
function makeChecker(props) {
	return function(x) {
		return x && props.some(function (y) {return y === x;});
	};
}

/*Tries to parse until the prediction ``valid'' fails or the wrong type is parsed
  Collects the results into an array and returns it*/
function parseMany(exprType, valid, tokens, charnum, linenum) {
  if (!fst(tokens)) {
    throw error.JSyntaxError(charnum,
                             linenum,
                             "Unexpected end of source");
  }
  var current = fst(tokens)[0];
	var results = [];
	var parsed;

	if (valid(fst(tokens)[0])) {
		parsed = parse(tokens);
	}
	else {
		throw error.JSyntaxError(linenum,
                             charnum,
                             "Unexpected token: ``"+fst(tokens)[0]+"''");
	}
  results.push(parsed);

	//make sure there are at least 2 tokens to parse
	if (tokens.length > 1 && fst(tokens) && valid(fst(tokens)[0])) {
		while (valid(snd(tokens)[0])) {
			if (!(valid(fst(tokens)[0])))
        break;
      results.push(parse(tokens));
			if (!exprType(fst(results).exprType))
				break;
			if (fst(tokens))
        current = fst(tokens)[0]
      else
        throw error.JSyntaxError(charnum, linenum, "Unexpected end of source");
			if (tokens.length <= 1)
				break;
		}
	}
	//do the same validity check as before and in the loop
  if (!fst(tokens))
    throw error.JSyntaxError(linenum,
                             charnum,
                             "unexpected end of source");
	if (valid(fst(tokens)[0]))
		results.push(parse(tokens));
	return results;
}

/* Tries to parse exprType separated by the token between
 * e.g. <identifier>,<identifier>,...
 */
function parseBetween(exprType, between, tokens, charnum, linenum) {
  var first = parse(tokens);
  if (!exprType(first)) {
    throw error.JSyntaxError(charnum, linenum, "Unexpected token: ``"+fst(tokens)[0]+"''");
  }
  var items = [first];
  var parsed;
  if (tokens.length > 1 && fst(tokens)[0] === between) {
    while (fst(tokens)[0] === between) {
      tokens.pop();
      parsed = parse(tokens);
      if (!fst(tokens))
        throw error.JSyntaxError(linenum,
                                 charnum,
                                 "Missing terminator: "+between);
      items.push(parsed);
    }
    return items;
  }
  return items;
}

function parseList(tokens) {
  if (fst(tokens)[0] === "right_square") {
      var xs = [];
  }
  else if (fst(tokens)[0] === "comma") {
    tokens.pop();
    var xs = [];
  }
  else {
    var xs = parseBetween(function (x) { return true; }, "comma", tokens, fst(tokens)[3], fst(tokens)[2]);
  }
  if (!fst(tokens) || fst(tokens)[0] !== "right_square") {
    throw error.JSyntaxError(fst(tokens)[3],
                             fst(tokens)[2],
                             "list must be terminated by ]");
  }
  tokens.pop();
  return new typ.ListT(xs);
}

function parseDefFunction(tokens) {
	var fname = parse(tokens);
  if (fname.exprType != "Name") {
    throw error.JSyntaxError(fst(tokens)[3],
                             fst(tokens)[2],
                             "Expected an identifier in function definition");
  }
  if (fst(tokens)[0] === "right_paren") {
    var parameters = [];
  }
  else {
    var parameters = parseMany(validName, validFormPar, tokens, fst(tokens)[2], fst(tokens)[3]);
  }
  if ((fst(tokens)[0]) !== "right_paren") {
    throw error.JSyntaxError(fst(tokens)[3],
                             fst(tokens)[2],
                             "Formal parameters must be followed by )");
  }
  tokens.pop();
  var body = parse(tokens);
  return new typ.DefFunc(fname, parameters, body);
}

function parseDef(tokens, linenum, charnum) {
  if (tokens.length < 2)
    throw error.JSyntaxError(linenum,
                             charnum,
                             "Unexpected end of source");
  if (fst(tokens)[0] === "left_paren") {
    /* It's a function definition */
    tokens.pop();
    return parseDefFunction(tokens);
  }
	if (notFollowedBy(tokens, ["identifier"], linenum, charnum)) {
		throw error.JSyntaxError(linenum,
                             charnum,
                             "def must be followed by identifier, not "+fst(tokens)[0]);
	}
	else {
    var identifier = parse(tokens);
    if (!fst(tokens))
      throw error.JSyntaxError(linenum,
                               charnum,
                               "Unexpected end of source");
    linenum = fst(tokens)[3];
    charnum = fst(tokens)[2];
    if (!notFollowedBy(tokens,
                       ["def", "comma", "arrow", "right_brace", "right_square"],
                       linenum,
                       charnum)) {
      throw error.JSyntaxError(linenum,
                               charnum,
                               "def " + identifier.val + " must not be followed by " + fst(tokens)[0]);
    }
		return new typ.Def(identifier, parse(tokens));
	}
 }

function parseIf(tokens) {
  var linenum = fst(tokens)[3];
  var charnum = fst(tokens)[2];
	if (!notFollowedBy(tokens,
                     ["def","comma","lambda"],
                     linenum,
                     charnum)) {
		throw error.JSyntaxError(linenum,
                             charnum,
                             "``if'' cannot be followed by "+fst(tokens)[0]) ;
	}
	else {
		var ifC = parse(tokens);
		if (!fst(tokens) || fst(tokens)[0] !== "thenexp")
			throw error.JSyntaxError(fst(tokens)[3],
                               fst(tokens)[2],
                               "if ``exp'' must be folowed by ``then'' exp, not "+snd(tokens)[0]);
		else {
			tokens.pop();
			var thenC = parse(tokens);

			if (fst(tokens) && fst(tokens)[0] === "elsexp") {
				tokens.pop();
				var elseC = parse(tokens);
				return new typ.If(ifC, thenC, elseC);

			}
			else {
				return new typ.If(ifC, thenC);
			}
		}
	}
}

var validFormPar = makeChecker(["identifier"]);
var validName = makeChecker(["Name"]);

function parseLambda(tokens) {
	var parameters = parseMany(validName,validFormPar, tokens, fst(tokens)[2], fst(tokens)[3]);

	if (fst(tokens)[0] !== "arrow") {
		throw error.JSyntaxError(fst(tokens)[3],
                             fst(tokens)[2],
                             "arrow must follow parameters in lambda, not "+fst(tokens)[0]);
	}
	tokens.pop()
	var body = parse(tokens);
	return new typ.FuncT(parameters, body);
}

//function parseLet(tokens) {

var invalidArguments = ["def", "comma", "right_paren", "right_square", "right_brace", "left_brace", "right_brace"];
var validArgument = tool.compose(tool.not, makeChecker(invalidArguments));
var validArgTypes = tool.compose(tool.not, makeChecker(["Definition"]));
var validOperator = makeChecker(["identifier"]);

/* Parses function application (either infix or prefix) */
function computeApp(tokens, charnum, linenum) {
  var lhs = parse(tokens);
	if (fst(tokens))
		var next = fst(tokens);
	else {
		throw error.JSyntaxError(linenum,
                             charnum,
                             "Unexpected end of source");
	}
	if (typ.OPInfo[next[1]]) {
		/* it's an infix expression */
		var result = parseInfix(tokens, 1, lhs, linenum, charnum);
		if (!fst(tokens) || fst(tokens)[0] !== "right_paren") {
			throw error.JSyntaxError(linenum,
                               charnum,
                               "Mismatched parentheses or missing parenthesis on right-hand side");
		}
		else {
      tokens.pop();
			return result;
		}
	}
	else {
		/* it's a prefix application */

		var parameters = parseMany(validArgTypes, validArgument, tokens, charnum, linenum);
		if ((!fst(tokens)) || fst(tokens)[0] !== "right_paren") {
			throw error.JSyntaxError(linenum,
                               charnum,
                               "Mismatched parentheses or missing parenthesis on right-hand side");
		}
		else {
      tokens.pop();
			return typ.makeApp(lhs, parameters);
		}
	}
}

/*Parses infix expressions by precedence climbing
  See this for more info and an implementation in python
  http://eli.thegreenplace.net/2012/08/02/parsing-expressions-by-precedence-climbing/
*/
function parseInfix(tokens, minPrec, lhs, linenum, charnum) {
	if (!lhs) {
		var lhs = parse(tokens);
	}
	while (true) {
		var cur = fst(tokens);
		if (!cur) {
			throw error.JSyntaxError(linenum,
                               charnum,
                               "Unexpected end of source");
		}
		var opinfo = typ.OPInfo[cur[1]];

		if (!opinfo || opinfo[0] < minPrec)
			break;

		var op = new typ.Name(cur[1]);
		var prec = opinfo[0];
		var assoc = opinfo[1];
		var nextMinPrec = assoc === "Left" ? prec + 1 : prec;
		tokens.pop();
		/*remove the operator token*/
		var rhs = parseInfix(tokens, nextMinPrec);
		lhs = typ.makeApp(op, [lhs, rhs]);
	}
	return lhs;
}

function parse(tokens) {
  var charnum = fst(tokens)[2];
  var linenum = fst(tokens)[3];
	if (fst(tokens)) {
		var toktype = fst(tokens)[0];
  }
	else {
		process.exit(code=1);
	}
	var token = fst(tokens)[1];
	tokens.pop();
	if (toktype === "stringlit")
		return new typ.StrT(token);
  else if (toktype === "left_square")
    return parseList(tokens);
	else if (toktype === "lambda")
		return parseLambda(tokens);
	else if (toktype === "integer")
		return new typ.IntT(token);
	else if (toktype === "float")
		return new typ.FloatT(token);
	else if (toktype === "identifier")
		return new typ.Name(token);
	else if (toktype === "truelit" || toktype === "falselit")
		return new typ.BoolT(token);
	else if (toktype === "def")
		return parseDef(tokens, fst(tokens)[3], fst(tokens)[2]);
	else if (toktype === "ifexp")
		return parseIf(tokens);
	else if (toktype === "left_paren") {
		if (fst(tokens)[0] === "lambda") {
      tokens.pop();
      var parsed = parseLambda(tokens);
      tokens.pop();
      return parsed;
    }
    else
      return computeApp(tokens, charnum, linenum);
  }
//  else if (toktype === "let") {
//    return parseLet(tokens);
//  }
  else {
    throw error.JSyntaxError(fst(tokens)[3],
                             fst(tokens)[2],
                             "Unexpected token: ``" + toktype+"''");
  }
}

var istr = fs.readFileSync('/dev/stdin').toString();
function parseFull(tokenized) {
  var ast = new Array();
  try {
    while (tokenized.length > 0) {
      var parsed = desugarer.desugar(parse(tokenized));
      ast.push(parsed);
    }
    return ast;
  } catch (e) {
      e.stxerror();
      process.exit(1);
  }
}
console.log(parseFull(tokenizer.tokenize(istr)).map(pprint.pprint).join("\n"));

//console.log(tokenizer.tokenize(istr));
//console.log(parseFull(tokenizer.tokenize(istr))[8].val.body);

//module.exports = {parse : tool.compose(parseFull, tokenizer.tokenize) };
<commit_msg>removed some old comments<commit_after>#! /usr/bin/node

var fs = require("fs");
var typ = require("./representation.js");
var tool = require("./tools.js");
var tokenizer = require("./tokenize.js");
var desugarer = require("./desugar.js");
var pprint = require("./pprint.js");
var error = require("./errors.js");

var print = console.log;

function fst(ts) {
	return ts[ts.length-1];
}

function snd(ts) {
	return ts[ts.length-2];
}

/*Checks if the next token is not followed by any of ``checks'' */
function notFollowedBy(tokens, checks, linenum, charnum) {
	if (!fst(tokens)) {
    throw error.JSyntaxError(0,0,"unexpected end of source")
  }
  var nextT = fst(tokens)[0];
	if (checks.some(function (x) {
    return x === nextT;
  }))
		return false;
	else
		return true;
}

/* returns a function that takes a parameter and
   checks if it is in the array ``props''*/
function makeChecker(props) {
	return function(x) {
		return x && props.some(function (y) {return y === x;});
	};
}

/*Tries to parse until the prediction ``valid'' fails or the wrong type is parsed
  Collects the results into an array and returns it*/
function parseMany(exprType, valid, tokens, charnum, linenum) {
  if (!fst(tokens)) {
    throw error.JSyntaxError(charnum,
                             linenum,
                             "Unexpected end of source");
  }
  var current = fst(tokens)[0];
	var results = [];
	var parsed;

	if (valid(fst(tokens)[0])) {
		parsed = parse(tokens);
	}
	else {
		throw error.JSyntaxError(linenum,
                             charnum,
                             "Unexpected token: ``"+fst(tokens)[0]+"''");
	}
  results.push(parsed);

	//make sure there are at least 2 tokens to parse
	if (tokens.length > 1 && fst(tokens) && valid(fst(tokens)[0])) {
		while (valid(snd(tokens)[0])) {
			if (!(valid(fst(tokens)[0])))
        break;
      results.push(parse(tokens));
			if (!exprType(fst(results).exprType))
				break;
			if (fst(tokens))
        current = fst(tokens)[0]
      else
        throw error.JSyntaxError(charnum, linenum, "Unexpected end of source");
			if (tokens.length <= 1)
				break;
		}
	}
	//do the same validity check as before and in the loop
  if (!fst(tokens))
    throw error.JSyntaxError(linenum,
                             charnum,
                             "unexpected end of source");
	if (valid(fst(tokens)[0]))
		results.push(parse(tokens));
	return results;
}

/* Tries to parse exprType separated by the token between
 * e.g. <identifier>,<identifier>,...
 */
function parseBetween(exprType, between, tokens, charnum, linenum) {
  var first = parse(tokens);
  if (!exprType(first)) {
    throw error.JSyntaxError(charnum, linenum, "Unexpected token: ``"+fst(tokens)[0]+"''");
  }
  var items = [first];
  var parsed;
  if (tokens.length > 1 && fst(tokens)[0] === between) {
    while (fst(tokens)[0] === between) {
      tokens.pop();
      parsed = parse(tokens);
      if (!fst(tokens))
        throw error.JSyntaxError(linenum,
                                 charnum,
                                 "Missing terminator: "+between);
      items.push(parsed);
    }
    return items;
  }
  return items;
}

function parseList(tokens) {
  if (fst(tokens)[0] === "right_square") {
      var xs = [];
  }
  else if (fst(tokens)[0] === "comma") {
    tokens.pop();
    var xs = [];
  }
  else {
    var xs = parseBetween(function (x) { return true; }, "comma", tokens, fst(tokens)[3], fst(tokens)[2]);
  }
  if (!fst(tokens) || fst(tokens)[0] !== "right_square") {
    throw error.JSyntaxError(fst(tokens)[3],
                             fst(tokens)[2],
                             "list must be terminated by ]");
  }
  tokens.pop();
  return new typ.ListT(xs);
}

function parseDefFunction(tokens) {
	var fname = parse(tokens);
  if (fname.exprType != "Name") {
    throw error.JSyntaxError(fst(tokens)[3],
                             fst(tokens)[2],
                             "Expected an identifier in function definition");
  }
  if (fst(tokens)[0] === "right_paren") {
    var parameters = [];
  }
  else {
    var parameters = parseMany(validName, validFormPar, tokens, fst(tokens)[2], fst(tokens)[3]);
  }
  if ((fst(tokens)[0]) !== "right_paren") {
    throw error.JSyntaxError(fst(tokens)[3],
                             fst(tokens)[2],
                             "Formal parameters must be followed by )");
  }
  tokens.pop();
  var body = parse(tokens);
  return new typ.DefFunc(fname, parameters, body);
}

function parseDef(tokens, linenum, charnum) {
  if (tokens.length < 2)
    throw error.JSyntaxError(linenum,
                             charnum,
                             "Unexpected end of source");
  if (fst(tokens)[0] === "left_paren") {
    /* It's a function definition */
    tokens.pop();
    return parseDefFunction(tokens);
  }

  if (fst(tokens)[0] === "left_brace") {
    /* It's a let/def form */
    tokens.pop();
    return parseLetForm(tokens);
  }

	if (notFollowedBy(tokens, ["identifier"], linenum, charnum)) {
		throw error.JSyntaxError(linenum,
                             charnum,
                             "def must be followed by identifier, not "+fst(tokens)[0]);
	}
	else {
    var identifier = parse(tokens);
    if (!fst(tokens))
      throw error.JSyntaxError(linenum,
                               charnum,
                               "Unexpected end of source");
    linenum = fst(tokens)[3];
    charnum = fst(tokens)[2];
    if (!notFollowedBy(tokens,
                       ["def", "comma", "arrow", "right_brace", "right_square"],
                       linenum,
                       charnum)) {
      throw error.JSyntaxError(linenum,
                               charnum,
                               "def " + identifier.val + " must not be followed by " + fst(tokens)[0]);
    }
		return new typ.Def(identifier, parse(tokens));
	}
 }

function parseIf(tokens) {
  var linenum = fst(tokens)[3];
  var charnum = fst(tokens)[2];
	if (!notFollowedBy(tokens,
                     ["def","comma","lambda"],
                     linenum,
                     charnum)) {
		throw error.JSyntaxError(linenum,
                             charnum,
                             "``if'' cannot be followed by "+fst(tokens)[0]) ;
	}
	else {
		var ifC = parse(tokens);
		if (!fst(tokens) || fst(tokens)[0] !== "thenexp")
			throw error.JSyntaxError(fst(tokens)[3],
                               fst(tokens)[2],
                               "if ``exp'' must be folowed by ``then'' exp, not "+snd(tokens)[0]);
		else {
			tokens.pop();
			var thenC = parse(tokens);

			if (fst(tokens) && fst(tokens)[0] === "elsexp") {
				tokens.pop();
				var elseC = parse(tokens);
				return new typ.If(ifC, thenC, elseC);

			}
			else {
				return new typ.If(ifC, thenC);
			}
		}
	}
}

var validFormPar = makeChecker(["identifier"]);
var validName = makeChecker(["Name"]);

function parseLambda(tokens) {
	var parameters = parseMany(validName,validFormPar, tokens, fst(tokens)[2], fst(tokens)[3]);

	if (fst(tokens)[0] !== "arrow") {
		throw error.JSyntaxError(fst(tokens)[3],
                             fst(tokens)[2],
                             "arrow must follow parameters in lambda, not "+fst(tokens)[0]);
	}
	tokens.pop()
	var body = parse(tokens);
	return new typ.FuncT(parameters, body);
}

//function parseLet(tokens) {

var invalidArguments = ["def", "comma", "right_paren", "right_square", "right_brace", "left_brace", "right_brace"];
var validArgument = tool.compose(tool.not, makeChecker(invalidArguments));
var validArgTypes = tool.compose(tool.not, makeChecker(["Definition"]));
var validOperator = makeChecker(["identifier"]);

/* Parses function application (either infix or prefix) */
function computeApp(tokens, charnum, linenum) {
  var lhs = parse(tokens);
	if (fst(tokens))
		var next = fst(tokens);
	else {
		throw error.JSyntaxError(linenum,
                             charnum,
                             "Unexpected end of source");
	}
	if (typ.OPInfo[next[1]]) {
		/* it's an infix expression */
		var result = parseInfix(tokens, 1, lhs, linenum, charnum);
		if (!fst(tokens) || fst(tokens)[0] !== "right_paren") {
			throw error.JSyntaxError(linenum,
                               charnum,
                               "Mismatched parentheses or missing parenthesis on right-hand side");
		}
		else {
      tokens.pop();
			return result;
		}
	}
	else {
		/* it's a prefix application */

		var parameters = parseMany(validArgTypes, validArgument, tokens, charnum, linenum);
		if ((!fst(tokens)) || fst(tokens)[0] !== "right_paren") {
			throw error.JSyntaxError(linenum,
                               charnum,
                               "Mismatched parentheses or missing parenthesis on right-hand side");
		}
		else {
      tokens.pop();
			return typ.makeApp(lhs, parameters);
		}
	}
}

/*Parses infix expressions by precedence climbing
  See this for more info and an implementation in python
  http://eli.thegreenplace.net/2012/08/02/parsing-expressions-by-precedence-climbing/
*/
function parseInfix(tokens, minPrec, lhs, linenum, charnum) {
	if (!lhs) {
		var lhs = parse(tokens);
	}
	while (true) {
		var cur = fst(tokens);
		if (!cur) {
			throw error.JSyntaxError(linenum,
                               charnum,
                               "Unexpected end of source");
		}
		var opinfo = typ.OPInfo[cur[1]];

		if (!opinfo || opinfo[0] < minPrec)
			break;

		var op = new typ.Name(cur[1]);
		var prec = opinfo[0];
		var assoc = opinfo[1];
		var nextMinPrec = assoc === "Left" ? prec + 1 : prec;
		tokens.pop();
		/*remove the operator token*/
		var rhs = parseInfix(tokens, nextMinPrec);
		lhs = typ.makeApp(op, [lhs, rhs]);
	}
	return lhs;
}

function parse(tokens) {
  var charnum = fst(tokens)[2];
  var linenum = fst(tokens)[3];
	if (fst(tokens)) {
		var toktype = fst(tokens)[0];
  }
	else {
		process.exit(code=1);
	}
	var token = fst(tokens)[1];
	tokens.pop();
	if (toktype === "stringlit")
		return new typ.StrT(token);
  else if (toktype === "left_square")
    return parseList(tokens);
	else if (toktype === "lambda")
		return parseLambda(tokens);
	else if (toktype === "integer")
		return new typ.IntT(token);
	else if (toktype === "float")
		return new typ.FloatT(token);
	else if (toktype === "identifier")
		return new typ.Name(token);
	else if (toktype === "truelit" || toktype === "falselit")
		return new typ.BoolT(token);
	else if (toktype === "def" ||
           toktype === "let")
		return parseDef(tokens, fst(tokens)[3], fst(tokens)[2]);
	else if (toktype === "ifexp")
		return parseIf(tokens);
	else if (toktype === "left_paren") {
		if (fst(tokens)[0] === "lambda") {
      tokens.pop();
      var parsed = parseLambda(tokens);
      tokens.pop();
      return parsed;
    }
    else
      return computeApp(tokens, charnum, linenum);
  }
  else {
    throw error.JSyntaxError(fst(tokens)[3],
                             fst(tokens)[2],
                             "Unexpected token: ``" + toktype+"''");
  }
}

var istr = fs.readFileSync('/dev/stdin').toString();
function parseFull(tokenized) {
  var ast = new Array();
  try {
    while (tokenized.length > 0) {
      var parsed = desugarer.desugar(parse(tokenized));
      ast.push(parsed);
    }
    return ast;
  } catch (e) {
      e.stxerror();
      process.exit(1);
  }
}
console.log(parseFull(tokenizer.tokenize(istr)).map(pprint.pprint).join("\n"));

//console.log(tokenizer.tokenize(istr));
//console.log(parseFull(tokenizer.tokenize(istr))[8].val.body);

//module.exports = {parse : tool.compose(parseFull, tokenizer.tokenize) };
<|endoftext|>


<commit_before>/* ************************************************************************

    License: MIT Licence

    Dependencies : [
        a.js
        core/console.js
        core/message.js
        plugin/callback.js
        plugin/language.js (optional)

        ** handlebars.js IS NEEDED AND IS EXTERNAL LIBRARY **
    ]

    Events: [
    ]

    Description:
        Manipulate the page history and templates.
        We define here some usefull function to catch some important event.

        template: Create a simple but powerfull template system based on
                    handlebars
        hash: Manage hash manipulate for page

************************************************************************ */

/**
 * Create a template system based on handlebars.
 *
 * Examples: here
 *
 * @class template
 * @static
 * @namespace a
*/
a.template = {
    /**
     * Store cached partials
     * @property _part
     * @type Object
     * @default {}
    */
    _part: {},

    /**
     * Store cached template
     * @property _tmpl
     * @type Object
     * @default {}
    */
    _tmpl: {},

    /**
     * Register a new partial into template system (handlebars partial).
     *
     * @method partial
     * @async
     *
     * @param name {String}                 The partial name to use inside
     *                                      handlebars templates
     * @param uri {String}                  The uri to load (GET method), or
     *                                      a template string (see options
     *                                      parameter)
     * @param callback {Function | null}    The callback to call after loading
     *                                      success
     * @param options {Object}              Options can have only one element:
     *                                      noLoading : Boolean
     *                                      Indicate if we should use uri as
     *                                      template string instead of uri to
     *                                      load from network
    */
    partial: function(name, uri, callback, options) {
        var handler = a.isTrueObject(window.Handlebars) ? window.Handlebars :
                                                                        null,
            fctName = 'a.template.partial';

        // Crash if handlebars is not found
        if(!handler) {
            a.console.error(fctName + ': unable to find Handlebars.JS !', 1);
            return;
        }

        var partialsStore = this._part;

        if(a.isString(partialsStore[name])) {
            a.console.log(fctName +': loading ' + name + ' from cache', 3);
            return partialsStore[name];
        }

        if(options && options.noloading == true) {
            a.console.log(fctName +': loading ' + name + ' from parameter', 3);
            partialsStore[name] = uri;
            handler.registerPartial(name, uri);

            // Callback
            if(a.isFunction(callback)) {
                callback(name, uri);
            }
        } else {
            a.loader.html(uri, function(content) {
                a.console.log(fctName +': loading ' + name + ' from url', 3);
                partialsStore[name] = content;
                handler.registerPartial(name, content);

                // Callback
                if(a.isFunction(callback)) {
                    callback(name, content);
                }
            });
        }
    },

    /**
     * Use cache or retrieve a specific template from network
     *
     * @method get
     * @async
     *
     * @param uri {String}                  The path to get the template,
     *                                      or an id if the template already
     *                                      listed in html
     * @param data {Object}                 The data to apply to template
     * @param callback {Function}           The callback to apply when
     *                                      template finish loading
     * @param error {Function | null}       The error to raise in case of
     *                                      problem
    */
    get: function(uri, data, callback, error) {
        var handler = a.isTrueObject(window.Handlebars) ? window.Handlebars :
                                                                        null,
            fctName = 'a.template.get';

        // Crash if handlebars is not found
        if(!handler) {
            a.console.error(fctName + ': unable to find Handlebars.JS !', 1);
            return;
        }

        // We create a hash from uri and sanitize
        // everything by replacing by underscore
        var orig = uri.replace(/[^a-zA-Z0-9\\-]/g, '_'),
            hash = 'a_tmpl_' + orig;

        /**
         * Parse the content with data from client,
         * then call callback with result
         *
         * @method callCallback
         * @private
         * @async
         *
         * @param clb {Function}            The callback function to call
         * @param h {String}                The hash representing the
         *                                  unique id of template
         * @param d {Object}                The data associated
        */
        var callCallback = function(clb, h, d) {
            if(a.isFunction(clb)) {

                // First try to use Handlebars.js
                if(a.isNone(handler.to_html)) {
                    // Act like a render method (threw compile method)
                    var tmpl = handler.compile(a.template._tmpl[h]);
                    clb(tmpl(d));

                // Rollback on Mustache.js
                } else {
                    clb(handler.to_html(a.template._tmpl[h], d));
                }
            }
        };

        // If the template is already listed into existing template,
        // directly load
        if(a.isString(this._tmpl[hash])) {
            a.console.log(fctName +': loading ' + hash + ' from cache', 3);
            callCallback(callback, hash, data);
            return;
        }

        // Template exist on page DOM, but it's not registred to ich for now
        if(document.getElementById(hash)) {
            // We add it to template list registered to go quicker next time
            if(!this._tmpl[hash]) {
                a.console.log(
                    fctName + ': loading ' + hash + ' from inner html page',3);
                this._tmpl[hash] = document.getElementById(hash).innerHTML;
            }

            // We finally send the callback
            callCallback(callback, hash, data);
            return;
        }

        // Same with this time original id, template exist on page DOM
        if(document.getElementById(orig)) {
            // We add it to template list registered to go quicker next time
            if(!this._tmpl[orig]) {
                a.console.log(
                    fctName + ': loading ' + orig + ' from inner html page',3);
                this._tmpl[orig] = document.getElementById(orig).innerHTML;
            }

            // We finally send the callback
            callCallback(callback, orig, data);
            return;
        }

        // Last try : we try to use uri to load template from server side,
        // then parse it
        var parse = function(content, status, state) {
            if(!a.template._tmpl[hash]) {
                a.template._tmpl[hash] = content;
            }
            callCallback(callback, hash, data);
            return;
        };

        // We use the loader to retrieve file from server side
        a.console.log(
            fctName + ': loading ' + uri + ' from external resource', 3);
        a.loader.html(uri, parse, {}, error);
    },

    /**
     * Convert an html to a dom content
     *
     * @method htmlToDom
     *
     * @param html {String}                 The string to parse
     * @return {Array}                      The result content
    */
    htmlToDom: function(html) {
        /*
         * Why this ?
         * - Using innerHTML is slow,
         *   and can remove binding (like onclick) to sibling children
         * - Doing this way is the only way to have both:
         *   full parsing on every browser, and DOM element to
         *   not have innerHTML bug.
         *   as innerHTML is configured into a temp object,
         *   this problem does not exist here anymore as it will
         *   not affect other children...
        */
        var d = document.createElement('div'),
            result = [];
        // Remove space before and after : the system fail in other case
        // (why ?)
        d.innerHTML  = html.replace(/^\s+|\s+$/g, '');

        // We select sub children of text type or element type
        a.dom.el(d).children([1, 3]).each(function() {
            result.push(this);
        });

        return result;
    },

    /**
     * Empty a dom element
     *
     * @method remove
     * @async
     *
     * @param el {DOMElement} The element to remove everything inside
     * @param callback {Function | null} The function to raise when job is done
    */
    remove: function(el, callback) {
        a.dom.el(el).empty();
        if(a.isFunction(callback)) {
            callback();
        }
    },

    /**
     * Append to the given element (given a DOM element here not a jquery one)
     *
     * @method append
     * @async
     *
     * @param el {DOMElement}               Any dom element to append to
     * @param content {String}              The html content (in string)
     *                                      to replace
     * @param callback {Function}           The callback to apply when
     *                                      template finish loading
    */
    append: function(el, content, callback) {
        el = a.dom.el(el);
        var h = this.htmlToDom(content);
        if(a.isTrueObject(h)) {
            el.append(h);
        }
        if(!a.isNone(a.language)) {
            a.each(el.getElements(), function(element) {
                a.language.translate(element);
            });
        }
        if(a.isFunction(callback)) {
            callback(content);
        }
    },

    /**
     * Same as append, just replace instead of append to element
     *
     * @method replace
     * @async
     *
     * @param el {DOMElement}               Any dom element to append to
     * @param content {String}              The html content (in string) to
     *                                      replace
     * @param callback {Function}           The callback to apply when
     *                                      template finish loading
    */
    replace: function(el, content, callback) {
        this.remove(el, function() {
            a.template.append(el, content, callback);
        });
    }
};<commit_msg>Replace current selection by new a.trim method.<commit_after>/* ************************************************************************

    License: MIT Licence

    Dependencies : [
        a.js
        core/console.js
        core/message.js
        plugin/callback.js
        plugin/language.js (optional)

        ** handlebars.js IS NEEDED AND IS EXTERNAL LIBRARY **
    ]

    Events: [
    ]

    Description:
        Manipulate the page history and templates.
        We define here some usefull function to catch some important event.

        template: Create a simple but powerfull template system based on
                    handlebars
        hash: Manage hash manipulate for page

************************************************************************ */

/**
 * Create a template system based on handlebars.
 *
 * Examples: here
 *
 * @class template
 * @static
 * @namespace a
*/
a.template = {
    /**
     * Store cached partials
     * @property _part
     * @type Object
     * @default {}
    */
    _part: {},

    /**
     * Store cached template
     * @property _tmpl
     * @type Object
     * @default {}
    */
    _tmpl: {},

    /**
     * Register a new partial into template system (handlebars partial).
     *
     * @method partial
     * @async
     *
     * @param name {String}                 The partial name to use inside
     *                                      handlebars templates
     * @param uri {String}                  The uri to load (GET method), or
     *                                      a template string (see options
     *                                      parameter)
     * @param callback {Function | null}    The callback to call after loading
     *                                      success
     * @param options {Object}              Options can have only one element:
     *                                      noLoading : Boolean
     *                                      Indicate if we should use uri as
     *                                      template string instead of uri to
     *                                      load from network
    */
    partial: function(name, uri, callback, options) {
        var handler = a.isTrueObject(window.Handlebars) ? window.Handlebars :
                                                                        null,
            fctName = 'a.template.partial';

        // Crash if handlebars is not found
        if(!handler) {
            a.console.error(fctName + ': unable to find Handlebars.JS !', 1);
            return;
        }

        var partialsStore = this._part;

        if(a.isString(partialsStore[name])) {
            a.console.log(fctName +': loading ' + name + ' from cache', 3);
            return partialsStore[name];
        }

        if(options && options.noloading == true) {
            a.console.log(fctName +': loading ' + name + ' from parameter', 3);
            partialsStore[name] = uri;
            handler.registerPartial(name, uri);

            // Callback
            if(a.isFunction(callback)) {
                callback(name, uri);
            }
        } else {
            a.loader.html(uri, function(content) {
                a.console.log(fctName +': loading ' + name + ' from url', 3);
                partialsStore[name] = content;
                handler.registerPartial(name, content);

                // Callback
                if(a.isFunction(callback)) {
                    callback(name, content);
                }
            });
        }
    },

    /**
     * Use cache or retrieve a specific template from network
     *
     * @method get
     * @async
     *
     * @param uri {String}                  The path to get the template,
     *                                      or an id if the template already
     *                                      listed in html
     * @param data {Object}                 The data to apply to template
     * @param callback {Function}           The callback to apply when
     *                                      template finish loading
     * @param error {Function | null}       The error to raise in case of
     *                                      problem
    */
    get: function(uri, data, callback, error) {
        var handler = a.isTrueObject(window.Handlebars) ? window.Handlebars :
                                                                        null,
            fctName = 'a.template.get';

        // Crash if handlebars is not found
        if(!handler) {
            a.console.error(fctName + ': unable to find Handlebars.JS !', 1);
            return;
        }

        // We create a hash from uri and sanitize
        // everything by replacing by underscore
        var orig = uri.replace(/[^a-zA-Z0-9\\-]/g, '_'),
            hash = 'a_tmpl_' + orig;

        /**
         * Parse the content with data from client,
         * then call callback with result
         *
         * @method callCallback
         * @private
         * @async
         *
         * @param clb {Function}            The callback function to call
         * @param h {String}                The hash representing the
         *                                  unique id of template
         * @param d {Object}                The data associated
        */
        var callCallback = function(clb, h, d) {
            if(a.isFunction(clb)) {

                // First try to use Handlebars.js
                if(a.isNone(handler.to_html)) {
                    // Act like a render method (threw compile method)
                    var tmpl = handler.compile(a.template._tmpl[h]);
                    clb(tmpl(d));

                // Rollback on Mustache.js
                } else {
                    clb(handler.to_html(a.template._tmpl[h], d));
                }
            }
        };

        // If the template is already listed into existing template,
        // directly load
        if(a.isString(this._tmpl[hash])) {
            a.console.log(fctName +': loading ' + hash + ' from cache', 3);
            callCallback(callback, hash, data);
            return;
        }

        // Template exist on page DOM, but it's not registred to ich for now
        if(document.getElementById(hash)) {
            // We add it to template list registered to go quicker next time
            if(!this._tmpl[hash]) {
                a.console.log(
                    fctName + ': loading ' + hash + ' from inner html page',3);
                this._tmpl[hash] = document.getElementById(hash).innerHTML;
            }

            // We finally send the callback
            callCallback(callback, hash, data);
            return;
        }

        // Same with this time original id, template exist on page DOM
        if(document.getElementById(orig)) {
            // We add it to template list registered to go quicker next time
            if(!this._tmpl[orig]) {
                a.console.log(
                    fctName + ': loading ' + orig + ' from inner html page',3);
                this._tmpl[orig] = document.getElementById(orig).innerHTML;
            }

            // We finally send the callback
            callCallback(callback, orig, data);
            return;
        }

        // Last try : we try to use uri to load template from server side,
        // then parse it
        var parse = function(content, status, state) {
            if(!a.template._tmpl[hash]) {
                a.template._tmpl[hash] = content;
            }
            callCallback(callback, hash, data);
            return;
        };

        // We use the loader to retrieve file from server side
        a.console.log(
            fctName + ': loading ' + uri + ' from external resource', 3);
        a.loader.html(uri, parse, {}, error);
    },

    /**
     * Convert an html to a dom content
     *
     * @method htmlToDom
     *
     * @param html {String}                 The string to parse
     * @return {Array}                      The result content
    */
    htmlToDom: function(html) {
        /*
         * Why this ?
         * - Using innerHTML is slow,
         *   and can remove binding (like onclick) to sibling children
         * - Doing this way is the only way to have both:
         *   full parsing on every browser, and DOM element to
         *   not have innerHTML bug.
         *   as innerHTML is configured into a temp object,
         *   this problem does not exist here anymore as it will
         *   not affect other children...
        */
        var d = document.createElement('div'),
            result = [];
        // Remove space before and after : the system fail in other case
        // (but why ?)
        d.innerHTML  = a.trim(html);

        // We select sub children of text type or element type
        a.dom.el(d).children([1, 3]).each(function() {
            result.push(this);
        });

        return result;
    },

    /**
     * Empty a dom element
     *
     * @method remove
     * @async
     *
     * @param el {DOMElement} The element to remove everything inside
     * @param callback {Function | null} The function to raise when job is done
    */
    remove: function(el, callback) {
        a.dom.el(el).empty();
        if(a.isFunction(callback)) {
            callback();
        }
    },

    /**
     * Append to the given element (given a DOM element here not a jquery one)
     *
     * @method append
     * @async
     *
     * @param el {DOMElement}               Any dom element to append to
     * @param content {String}              The html content (in string)
     *                                      to replace
     * @param callback {Function}           The callback to apply when
     *                                      template finish loading
    */
    append: function(el, content, callback) {
        el = a.dom.el(el);
        var h = this.htmlToDom(content);
        if(a.isTrueObject(h)) {
            el.append(h);
        }
        if(!a.isNone(a.language)) {
            a.each(el.getElements(), function(element) {
                a.language.translate(element);
            });
        }
        if(a.isFunction(callback)) {
            callback(content);
        }
    },

    /**
     * Same as append, just replace instead of append to element
     *
     * @method replace
     * @async
     *
     * @param el {DOMElement}               Any dom element to append to
     * @param content {String}              The html content (in string) to
     *                                      replace
     * @param callback {Function}           The callback to apply when
     *                                      template finish loading
    */
    replace: function(el, content, callback) {
        this.remove(el, function() {
            a.template.append(el, content, callback);
        });
    }
};<|endoftext|>


<commit_before>// View model for the courses page
function pageViewModel(gvm) {
    // Page specific i18n bindings
    gvm.app  = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ProjectRapportName")}, gvm);
    gvm.title = ko.computed(function(){i18n.setLocale(gvm.lang()); return gvm.app() + ' - ' + i18n.__("CourseTitle2");}, gvm);
    gvm.pageHeader = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("CourseTitle2");}, gvm);
    gvm.projectname = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ProjectRapportName");}, gvm);

    gvm.availableLocations = ko.observableArray([]);
    gvm.availableTrainings = ko.observableArray([]);
    gvm.availableCourses = ko.observableArray([]);

    /*Teacher*/
    gvm.availableTeacher = ko.observableArray([]);
    gvm.currentteacherid = null;
    /*teacher*/

    // Pagination i18n bindings
    gvm.addBtn = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("AddBtn")}, gvm);

    gvm.codeTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("CodeTableTitle");}, gvm);
    gvm.nameTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("NameTableTitle");}, gvm);
    gvm.descTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("DescTableTitle");}, gvm);
    gvm.actionTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ActionTableTitle");}, gvm);

    // The table data observable array
    gvm.tabledata = ko.observableArray([]);

    // Add data to the table
    gvm.addTableData = function(id, code, name, desc) {
        // Push data
        var tblOject = {tid: id, tcode: code, tname: name, tdesc: desc};
        gvm.tabledata.push(tblOject);

        // Attach delete handler to delete button
        $('#removebtn-' + id).bind('click', function(event, data){
            // Delete the table item
            deleteTableItem(id, tblOject);
            event.stopPropagation();
        });

        // Attach edit handler to edit button
        $('#editbtn-' + id).bind('click', function(event, data){
            // Edit the table item
            showEditProjectTypeModal(code, name, desc, id);
            event.stopPropagation();
        });

        //Attach manage handler to manage competences, subcompetences and indicators to manage button
        $('#managebtn-' + id).bind('click', function(event, data) {
            //TODO
        });

        /*$('#studentbtn-' + id).bind('click', function(event, data) {
            showCoupleStudentListModal(id);
            gvm.currentprojectid = id;
            gvm.currentselectedlist = -1;
            event.stopPropagation();
            loadCoupleDropdown();
        });*/
    }

    gvm.clearTable = function() {
        gvm.tabledata.removeAll();
    }

    gvm.updateDropdowns = function() {
        $.getJSON('api/lastdropdownchoice/' + gvm.userId, function(data) {
            if(!$.isEmptyObject(data)) {
                $.each(data, function(i, item) {
                    $(".btn-teacher span:first").text(item.teacher);
                    gvm.currentteacherid = item.id;
                    gvm.updateTeacher(item.username);
                });
            } else {

            }
        });
    }

    gvm.updateTeacher = function(id) {
    $.getJSON('/api/teacherrapport/' + id, function(data) {
        gvm.availableTeacher.removeAll();
        $.each(data, function(i, item) {
            gvm.availableTeacher.push(item);
                console.log(item)
            /* Add listener to listitem */
            $("#teacherbtn-" + item.id).click(function(){
                gvm.currentteacherid = item.id;
                $(".btn-teacher span:first").text($(this).text());
                loadTablePage(item.id, 1);
            });
        });
    });
    }
    }
/*
 * Delete item from table given the id.
 */
function deleteTableItem(id, tblOject) {
    showYesNoModal("Bent u zeker dat u dit item wil verwijderen? \r\n Let op: verwijderde items blijven in het systeem en kunnen weer actief gezet worden door een administrator. \r\n Gelieve de administrator te contacteren om een vak definitief te verwijderen.", function(val){
        if(val){
            $.ajax({
                url: "/api/coursedelete/" + id,
                type: "DELETE",
                success: function() {
                    viewModel.tabledata.remove(tblOject);
                }
            });
        }
    });
}

/*
 * Add a new projecttype
 */
function addNewProjecttypeForm(serialData, callback) {
    $.ajax({
            url: "/api/courserapport",
            type: "POST",
            data: serialData,
            success: function(data) {
                viewModel.addTableData(data['id'], data['code'], data['name'], data['description']);
                callback(true);
            },
            error: function(data) {
                callback(false);
            }
        });
}

/*
 * Add a new projecttype
 */
function addNewProjecttypeRaw(code, name, description, callback) {
    addNewProjecttypeForm("code=" + encodeURIComponent(code) + "&name=" + encodeURIComponent(name) + "&description=" + encodeURIComponent(description), callback);
}

/*
 * Update the projecttype
 * @param {type} id
 * @param {type} code
 * @param {type} name
 * @param {type} description
 * @param {type} callback
 * @returns {undefined}
 */
function updateProjecttypeForm(id, serialData, callback) {
    $.ajax({
        url: "/api/courseupdate/" + id,
        type: "PUT",
        data: serialData,
        success: function(data) {
            //viewModel.addTableData(data['id'], data['code'], data['name'], data['description']);
            loadTablePage(1); //TODO now it is refreshing table after updating but it redirects to pagenr 1     WERKT NIET
            callback(true);
        },
        error: function(data) {
            callback(false);
        }
    });
}

/**
 * update project type
 * @param {type} id
 * @param {type} code
 * @param {type} name
 * @param {type} description
 * @param {type} callback
 * @returns {undefined}
 */
function updateProjecttypeRaw(id, code, name, description, callback) {
    updateProjecttypeForm(id, "code=" + encodeURIComponent(code) + "&name=" + encodeURIComponent(name) + "&description=" + encodeURIComponent(description), callback);
}

/*
 * Load page of the table
 */
function loadTablePage(pagenr)
{
    $.getJSON('/api/coursesrapport/page/' + pagenr, function(data){

        /* Clear current table page */
        viewModel.clearTable();

        // Load table data
        $.each(data.data, function(i, item) {
            viewModel.addTableData(item.id, item.code, item.name, item.description);
        });

        /* Let previous en next buttons work */
        if(data.prev == "none"){
            $('#pager-prev-btn').addClass('disabled');
        } else {
            $('#pager-prev-btn').removeClass('disabled');
            $('#pager-prev-btn a').click(function(){
                loadTablePage(data.prev);
            });
        }

        if(data.next == "none"){
            $('#pager-next-btn').addClass('disabled');
        } else {
            $('#pager-next-btn').removeClass('disabled');
            $('#pager-next-btn a').click(function(){
                loadTablePage(data.next);
            });
        }

        // Number of pager buttons
        var numItems = $('.pager-nr-btn').length;

        /* Calculate for the pager buttons */
        var lowPage = Math.floor(pagenr/numItems) + 1;

        $('.pager-nr-btn').each(function() {
            /* calculate current page number */
            var thispagenr = lowPage++;

            /* Add the page number */
            $(this).html('' + thispagenr + '');

            /* Add active class to current page */
            if(thispagenr == pagenr) {
                $(this).addClass('active');
            } else {
                $(this).removeClass('active');
            }

            /* Disable inactive classes and bind handlers to active classes */
            if(thispagenr > data.pagecount) {
                $(this).addClass('disabled');
            } else {
                /* Add click listener for button */
                $(this).click(function() {
                    loadTablePage(thispagenr);
                });
            }
        });
    });

}

/**
 * Show a new projecttype modal.
 * @returns {undefined}
 */
function showNewProjectTypeModal()
{
    resetGeneralModal();
    setGeneralModalTitle(i18n.__("AddNewCourse"));
    setGeneralModalBody('<form id="newprojectform"> \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('CodeTableTitle') + '" " name="code"> \

 \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('NameTableTitle') + '" name="name"> \

 \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('DescTableTitle') + '" name="description"> \

 \

' +
                '<button class="btn btn-wide btn-default btn-teacher dropdown-toggle" type="button" id="availableTeacher" data-toggle="dropdown" aria-expanded="true" placeholder="' + i18n.__('TeacherTableTitle') + '">' +
                    'Teacher' + '' +
                '</button>' +
                '
' +
                    '

' +
                '
' +
            '
' +
            '</form>' );

    addGeneralModalButton(i18n.__("AddBtn"), function(){
        console.log($('#newprojectform').serialize());
       addNewProjecttypeForm($('#newprojectform').serialize(), function(result){
            hideModal();
        });
    });

    showGeneralModal();
}

/**
 * Show the edit projecttype modal.
 * @param {type} code
 * @param {type} name
 * @param {type} description
 * @param {type} tid
 * @returns {undefined}
 */
function showEditProjectTypeModal(code, name, description, tid)
{
  resetGeneralModal();
    setGeneralModalTitle(i18n.__("EditProjectTitle2"));
    setGeneralModalBody('<form id="updateprojectform"> \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('CodeTableTitle') + '" " name="code" value="' + code + '"> \

 \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('NameTableTitle') + '" name="name" value="' + name + '"> \

 \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('DescTableTitle') + '" name="description" value="' + description + '"> \

 \
        </form>');
    $.getJSON()

    addGeneralModalButton(i18n.__("SaveBtn"), function(){
        updateProjecttypeForm(tid, $('#updateprojectform').serialize(), function(result){
            hideModal();
        });
    });

    addGeneralModalButton(i18n.__("CancelBtn"), function(){
        hideModal();
    })

    showGeneralModal();
}

function showCoupleStudentListModal(projectid) {
    viewModel.currentselectedlist = -1;
    resetGeneralModal();
    setGeneralModalTitle(i18n.__("CoupleStudentList"));
    setGeneralModalBody(
        '
' +
            '<button class="btn btn-default dropdown-toggle" type="button" id="dropdownStudLists" data-toggle="dropdown" aria-expanded="true">' +
                'Dropdown' +
                '' +
            '</button>' +
            '
' +
            '
' +
        '
');

    addGeneralModalButton(i18n.__("SaveBtn"), function() {
        updateListForm(viewModel.currentselectedlist, $('#coupleform').serialize(), function(result){
            hideModal();
        });
    });

    addGeneralModalButton(i18n.__("CancelBtn"), function(){
        hideModal();
    })
    showGeneralModal();
}
function loadCoupleDropdown() {
    $.getJSON('/api/studentlists/' + viewModel.userId, function(data) {
        $.each(data, function(i, item) {
            $("#ddlLists").append('
' + item.name + '
')
            $("#dropdownitem-" + item.id).click(function(){
                $(this).parent().parent().parent().removeClass("open");
                $(this).parent().parent().parent().find(".btn").html($(this).text() + '');
                viewModel.currentselectedlist = item.id;
            });
        });
    });
    $("#dropdownStudLists").click(function() {
        $(this).parent().toggleClass("open");
    });
}

function updateListForm(id, serialData, callback) {
    $.ajax({
        url: "/api/project/" + viewModel.currentprojectid + "/studentlist/" + id,
        type: "POST",
        data: serialData,
        success: function(data) {
            callback(true);
        },
        error: function(data) {
            callback(false);
        }
    });
}

function initPage() {
    // Add button handlers
    $('#addProjectTypeBtn').click(function(){
        showNewProjectTypeModal();
    });

    $.getJSON('/api/currentuser', function(data) {
        viewModel.userId = data.id;
        viewModel.updateDropdowns();
    });

    loadTablePage(1);
}
<commit_msg>coursesrapportenviewmodel teacher<commit_after>// View model for the courses page
function pageViewModel(gvm) {
    // Page specific i18n bindings
    gvm.app  = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ProjectRapportName")}, gvm);
    gvm.title = ko.computed(function(){i18n.setLocale(gvm.lang()); return gvm.app() + ' - ' + i18n.__("CourseTitle2");}, gvm);
    gvm.pageHeader = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("CourseTitle2");}, gvm);
    gvm.projectname = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ProjectRapportName");}, gvm);

    gvm.availableLocations = ko.observableArray([]);
    gvm.availableTrainings = ko.observableArray([]);
    gvm.availableCourses = ko.observableArray([]);

    /*Teacher*/
    gvm.availableTeacher = ko.observableArray([]);
    gvm.currentteacherid = null;
    /*teacher*/

    // Pagination i18n bindings
    gvm.addBtn = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("AddBtn")}, gvm);

    gvm.codeTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("CodeTableTitle");}, gvm);
    gvm.nameTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("NameTableTitle");}, gvm);
    gvm.descTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("DescTableTitle");}, gvm);
    gvm.actionTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ActionTableTitle");}, gvm);

    // The table data observable array
    gvm.tabledata = ko.observableArray([]);

    // Add data to the table
    gvm.addTableData = function(id, code, name, desc) {
        // Push data
        var tblOject = {tid: id, tcode: code, tname: name, tdesc: desc};
        gvm.tabledata.push(tblOject);

        // Attach delete handler to delete button
        $('#removebtn-' + id).bind('click', function(event, data){
            // Delete the table item
            deleteTableItem(id, tblOject);
            event.stopPropagation();
        });

        // Attach edit handler to edit button
        $('#editbtn-' + id).bind('click', function(event, data){
            // Edit the table item
            showEditProjectTypeModal(code, name, desc, id);
            event.stopPropagation();
        });

        //Attach manage handler to manage competences, subcompetences and indicators to manage button
        $('#managebtn-' + id).bind('click', function(event, data) {
            //TODO
        });

        /*$('#studentbtn-' + id).bind('click', function(event, data) {
            showCoupleStudentListModal(id);
            gvm.currentprojectid = id;
            gvm.currentselectedlist = -1;
            event.stopPropagation();
            loadCoupleDropdown();
        });*/
    }

    gvm.clearTable = function() {
        gvm.tabledata.removeAll();
    }

    gvm.updateDropdowns = function() {
        $.getJSON('api/lastdropdownchoice/' + gvm.userId, function(data) {
            if(!$.isEmptyObject(data)) {
                $.each(data, function(i, item) {
                    $(".btn-teacher span:first").text(item.teacher);
                    gvm.currentteacherid = item.id;
                    gvm.updateTeacher(item.username);
                });
            } else {

            }
        });
    }

    gvm.updateTeacher = function(id) {
    $.getJSON('/api/teacherrapport/' + id, function(data) {
        gvm.availableTeacher.removeAll();
        $.each(data, function(i, item) {
            gvm.availableTeacher.push(item.username);
                console.log(item)
            /* Add listener to listitem */
            $("#teacherbtn-" + item.id).click(function(){
                gvm.currentteacherid = item.id;
                $(".btn-teacher span:first").text($(this).text());
                loadTablePage(item.id, 1);
            });
        });
    });
    }
    }
/*
 * Delete item from table given the id.
 */
function deleteTableItem(id, tblOject) {
    showYesNoModal("Bent u zeker dat u dit item wil verwijderen? \r\n Let op: verwijderde items blijven in het systeem en kunnen weer actief gezet worden door een administrator. \r\n Gelieve de administrator te contacteren om een vak definitief te verwijderen.", function(val){
        if(val){
            $.ajax({
                url: "/api/coursedelete/" + id,
                type: "DELETE",
                success: function() {
                    viewModel.tabledata.remove(tblOject);
                }
            });
        }
    });
}

/*
 * Add a new projecttype
 */
function addNewProjecttypeForm(serialData, callback) {
    $.ajax({
            url: "/api/courserapport",
            type: "POST",
            data: serialData,
            success: function(data) {
                viewModel.addTableData(data['id'], data['code'], data['name'], data['description']);
                callback(true);
            },
            error: function(data) {
                callback(false);
            }
        });
}

/*
 * Add a new projecttype
 */
function addNewProjecttypeRaw(code, name, description, callback) {
    addNewProjecttypeForm("code=" + encodeURIComponent(code) + "&name=" + encodeURIComponent(name) + "&description=" + encodeURIComponent(description), callback);
}

/*
 * Update the projecttype
 * @param {type} id
 * @param {type} code
 * @param {type} name
 * @param {type} description
 * @param {type} callback
 * @returns {undefined}
 */
function updateProjecttypeForm(id, serialData, callback) {
    $.ajax({
        url: "/api/courseupdate/" + id,
        type: "PUT",
        data: serialData,
        success: function(data) {
            //viewModel.addTableData(data['id'], data['code'], data['name'], data['description']);
            loadTablePage(1); //TODO now it is refreshing table after updating but it redirects to pagenr 1     WERKT NIET
            callback(true);
        },
        error: function(data) {
            callback(false);
        }
    });
}

/**
 * update project type
 * @param {type} id
 * @param {type} code
 * @param {type} name
 * @param {type} description
 * @param {type} callback
 * @returns {undefined}
 */
function updateProjecttypeRaw(id, code, name, description, callback) {
    updateProjecttypeForm(id, "code=" + encodeURIComponent(code) + "&name=" + encodeURIComponent(name) + "&description=" + encodeURIComponent(description), callback);
}

/*
 * Load page of the table
 */
function loadTablePage(pagenr)
{
    $.getJSON('/api/coursesrapport/page/' + pagenr, function(data){

        /* Clear current table page */
        viewModel.clearTable();

        // Load table data
        $.each(data.data, function(i, item) {
            viewModel.addTableData(item.id, item.code, item.name, item.description);
        });

        /* Let previous en next buttons work */
        if(data.prev == "none"){
            $('#pager-prev-btn').addClass('disabled');
        } else {
            $('#pager-prev-btn').removeClass('disabled');
            $('#pager-prev-btn a').click(function(){
                loadTablePage(data.prev);
            });
        }

        if(data.next == "none"){
            $('#pager-next-btn').addClass('disabled');
        } else {
            $('#pager-next-btn').removeClass('disabled');
            $('#pager-next-btn a').click(function(){
                loadTablePage(data.next);
            });
        }

        // Number of pager buttons
        var numItems = $('.pager-nr-btn').length;

        /* Calculate for the pager buttons */
        var lowPage = Math.floor(pagenr/numItems) + 1;

        $('.pager-nr-btn').each(function() {
            /* calculate current page number */
            var thispagenr = lowPage++;

            /* Add the page number */
            $(this).html('' + thispagenr + '');

            /* Add active class to current page */
            if(thispagenr == pagenr) {
                $(this).addClass('active');
            } else {
                $(this).removeClass('active');
            }

            /* Disable inactive classes and bind handlers to active classes */
            if(thispagenr > data.pagecount) {
                $(this).addClass('disabled');
            } else {
                /* Add click listener for button */
                $(this).click(function() {
                    loadTablePage(thispagenr);
                });
            }
        });
    });

}

/**
 * Show a new projecttype modal.
 * @returns {undefined}
 */
function showNewProjectTypeModal()
{
    resetGeneralModal();
    setGeneralModalTitle(i18n.__("AddNewCourse"));
    setGeneralModalBody('<form id="newprojectform"> \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('CodeTableTitle') + '" " name="code"> \

 \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('NameTableTitle') + '" name="name"> \

 \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('DescTableTitle') + '" name="description"> \

 \

' +
                '<button class="btn btn-wide btn-default btn-teacher dropdown-toggle" type="button" id="availableTeacher" data-toggle="dropdown" aria-expanded="true" placeholder="' + i18n.__('TeacherTableTitle') + '">' +
                    'Teacher' + '' +
                '</button>' +
                '
' +
                    '

' +
                '
' +
            '
' +
            '</form>' );

    addGeneralModalButton(i18n.__("AddBtn"), function(){
        console.log($('#newprojectform').serialize());
       addNewProjecttypeForm($('#newprojectform').serialize(), function(result){
            hideModal();
        });
    });

    showGeneralModal();
}

/**
 * Show the edit projecttype modal.
 * @param {type} code
 * @param {type} name
 * @param {type} description
 * @param {type} tid
 * @returns {undefined}
 */
function showEditProjectTypeModal(code, name, description, tid)
{
  resetGeneralModal();
    setGeneralModalTitle(i18n.__("EditProjectTitle2"));
    setGeneralModalBody('<form id="updateprojectform"> \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('CodeTableTitle') + '" " name="code" value="' + code + '"> \

 \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('NameTableTitle') + '" name="name" value="' + name + '"> \

 \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('DescTableTitle') + '" name="description" value="' + description + '"> \

 \
        </form>');
    $.getJSON()

    addGeneralModalButton(i18n.__("SaveBtn"), function(){
        updateProjecttypeForm(tid, $('#updateprojectform').serialize(), function(result){
            hideModal();
        });
    });

    addGeneralModalButton(i18n.__("CancelBtn"), function(){
        hideModal();
    })

    showGeneralModal();
}

function showCoupleStudentListModal(projectid) {
    viewModel.currentselectedlist = -1;
    resetGeneralModal();
    setGeneralModalTitle(i18n.__("CoupleStudentList"));
    setGeneralModalBody(
        '
' +
            '<button class="btn btn-default dropdown-toggle" type="button" id="dropdownStudLists" data-toggle="dropdown" aria-expanded="true">' +
                'Dropdown' +
                '' +
            '</button>' +
            '
' +
            '
' +
        '
');

    addGeneralModalButton(i18n.__("SaveBtn"), function() {
        updateListForm(viewModel.currentselectedlist, $('#coupleform').serialize(), function(result){
            hideModal();
        });
    });

    addGeneralModalButton(i18n.__("CancelBtn"), function(){
        hideModal();
    })
    showGeneralModal();
}
function loadCoupleDropdown() {
    $.getJSON('/api/studentlists/' + viewModel.userId, function(data) {
        $.each(data, function(i, item) {
            $("#ddlLists").append('
' + item.name + '
')
            $("#dropdownitem-" + item.id).click(function(){
                $(this).parent().parent().parent().removeClass("open");
                $(this).parent().parent().parent().find(".btn").html($(this).text() + '');
                viewModel.currentselectedlist = item.id;
            });
        });
    });
    $("#dropdownStudLists").click(function() {
        $(this).parent().toggleClass("open");
    });
}

function updateListForm(id, serialData, callback) {
    $.ajax({
        url: "/api/project/" + viewModel.currentprojectid + "/studentlist/" + id,
        type: "POST",
        data: serialData,
        success: function(data) {
            callback(true);
        },
        error: function(data) {
            callback(false);
        }
    });
}

function initPage() {
    // Add button handlers
    $('#addProjectTypeBtn').click(function(){
        showNewProjectTypeModal();
    });

    $.getJSON('/api/currentuser', function(data) {
        viewModel.userId = data.id;
        viewModel.updateDropdowns();
    });

    loadTablePage(1);
}
<|endoftext|>


<commit_before>var global = (typeof window !== 'undefined') ? window : {},
    Ember = global.Ember;

import { Base } from './base';
import { isSecureUrl } from '../utils/is_secure_url';

/**
  Authorizer that conforms to OAuth 2
  ([RFC 6749](http://tools.ietf.org/html/rfc6749)) by sending a bearer token
  ([RFC 6749](http://tools.ietf.org/html/rfc6750)) in the request's
  `Authorization` header.

  @class OAuth2
  @namespace Authenticators
  @extends Authorizers.Base
*/
var OAuth2 = Base.extend({
  /**
    Authorizes an XHR request by sending the `access_token` property from the
    session as a bearer token in the `Authorization` header:

    ```
    Authorization: Bearer <access_token>
    ```

    @method authorize
    @param {jqXHR} jqXHR The XHR request to authorize (see http://api.jquery.com/jQuery.ajax/#jqXHR)
    @param {Object} requestOptions The options as provided to the `$.ajax` method (see http://api.jquery.com/jQuery.ajaxPrefilter/)
  */
  authorize: function(jqXHR, requestOptions) {
    if (this.get('session.isAuthenticated') && !Ember.isEmpty(this.get('session.access_token'))) {
      if (!isSecureUrl(requestOptions.url)) {
        Ember.Logger.warn('Credentials are transmitted via an insecure connection - use HTTPS to keep them secure.');
      }
      jqXHR.setRequestHeader('Authorization', 'Bearer ' + this.get('session.access_token'));
    }
  }
});

export { OAuth2 };
<commit_msg>fixed documantation<commit_after>var global = (typeof window !== 'undefined') ? window : {},
    Ember = global.Ember;

import { Base } from './base';
import { isSecureUrl } from '../utils/is_secure_url';

/**
  Authorizer that conforms to OAuth 2
  ([RFC 6749](http://tools.ietf.org/html/rfc6749)) by sending a bearer token
  ([RFC 6749](http://tools.ietf.org/html/rfc6750)) in the request's
  `Authorization` header.

  @class OAuth2
  @namespace Authorizers
  @extends Authorizers.Base
*/
var OAuth2 = Base.extend({
  /**
    Authorizes an XHR request by sending the `access_token` property from the
    session as a bearer token in the `Authorization` header:

    ```
    Authorization: Bearer <access_token>
    ```

    @method authorize
    @param {jqXHR} jqXHR The XHR request to authorize (see http://api.jquery.com/jQuery.ajax/#jqXHR)
    @param {Object} requestOptions The options as provided to the `$.ajax` method (see http://api.jquery.com/jQuery.ajaxPrefilter/)
  */
  authorize: function(jqXHR, requestOptions) {
    if (this.get('session.isAuthenticated') && !Ember.isEmpty(this.get('session.access_token'))) {
      if (!isSecureUrl(requestOptions.url)) {
        Ember.Logger.warn('Credentials are transmitted via an insecure connection - use HTTPS to keep them secure.');
      }
      jqXHR.setRequestHeader('Authorization', 'Bearer ' + this.get('session.access_token'));
    }
  }
});

export { OAuth2 };
<|endoftext|>


<commit_before>// View model for the courses page
function pageViewModel(gvm) {
    // Page specific i18n bindings
    gvm.app  = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ProjectRapportName")}, gvm);
    gvm.title = ko.computed(function(){i18n.setLocale(gvm.lang()); return gvm.app() + ' - ' + i18n.__("CourseTitle2");}, gvm);
    gvm.pageHeader = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("CourseTitle2");}, gvm);
    gvm.projectname = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ProjectRapportName");}, gvm);

    gvm.availableLocations = ko.observableArray([]);
    gvm.availableTrainings = ko.observableArray([]);
    gvm.availableCourses = ko.observableArray([]);

    /*Teacher*/
    gvm.availableTeacher = ko.observableArray([]);
    gvm.currentteacherid = null;
    /*teacher*/

    // Pagination i18n bindings
    gvm.addBtn = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("AddBtn")}, gvm);

    gvm.codeTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("CodeTableTitle");}, gvm);
    gvm.nameTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("NameTableTitle");}, gvm);
    gvm.descTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("DescTableTitle");}, gvm);
    gvm.actionTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ActionTableTitle");}, gvm);

    // The table data observable array
    gvm.tabledata = ko.observableArray([]);

    // Add data to the table
    gvm.addTableData = function(id, code, name, desc) {
        console.log(id + ", " + code + ", " + name + ", " + desc);
        // Push data
        var tblOject = {tid: id, tcode: code, tname: name, tdesc: desc};
        gvm.tabledata.push(tblOject);

        // Attach delete handler to delete button
        $('#removebtn-' + id).bind('click', function(event, data){
            // Delete the table item
            deleteTableItem(id, tblOject);
            event.stopPropagation();
        });

        // Attach edit handler to edit button
        $('#editbtn-' + id).bind('click', function(event, data){
            // Edit the table item
            showEditProjectTypeModal(code, name, desc, id);
            event.stopPropagation();
        });

        //Attach manage handler to manage competences, subcompetences and indicators to manage button
        $('#managebtn-' + id).bind('click', function(event, data) {
            //TODO
        });

        /*$('#studentbtn-' + id).bind('click', function(event, data) {
            showCoupleStudentListModal(id);
            gvm.currentprojectid = id;
            gvm.currentselectedlist = -1;
            event.stopPropagation();
            loadCoupleDropdown();
        });*/
    }

    gvm.clearTable = function() {
        gvm.tabledata.removeAll();
    }

    gvm.updateTeacher = function(id) {
        console.log("updateteacherfunctie1");
    $.getJSON('/api/teacherrapport/' + id, function(data) {
        gvm.availableTeacher.removeAll();
        $.each(data, function(i, item) {
            gvm.availableTeacher.push(item);
                console.log("updateteacherfunctie")
            /* Add listener to listitem */
            $("#teacherbtn-" + item.id).click(function(){
                $(".btn-teacher span:first").text($(this).text());
                gvm.currentteacherid = item.id;
                gvm.saveLastSelectedDropdowns();
                loadTablePage(item.id, 1);
            });
        });
    });
    }
    }
/*
 * Delete item from table given the id.
 */
function deleteTableItem(id, tblOject) {
    showYesNoModal("Bent u zeker dat u dit item wil verwijderen? \r\n Let op: verwijderde items blijven in het systeem en kunnen weer actief gezet worden door een administrator. \r\n Gelieve de administrator te contacteren om een vak definitief te verwijderen.", function(val){
        if(val){
            $.ajax({
                url: "/api/coursedelete/" + id,
                type: "DELETE",
                success: function() {
                    viewModel.tabledata.remove(tblOject);
                }
            });
        }
    });
}

/*
 * Add a new projecttype
 */
function addNewProjecttypeForm(serialData, callback) {
    $.ajax({
            url: "/api/courserapport",
            type: "POST",
            data: serialData,
            success: function(data) {
                viewModel.addTableData(data['id'], data['code'], data['name'], data['description']);
                callback(true);
            },
            error: function(data) {
                callback(false);
            }
        });
}

/*
 * Add a new projecttype
 */
function addNewProjecttypeRaw(code, name, description, callback) {
    addNewProjecttypeForm("code=" + encodeURIComponent(code) + "&name=" + encodeURIComponent(name) + "&description=" + encodeURIComponent(description), callback);
}

/*
 * Update the projecttype
 * @param {type} id
 * @param {type} code
 * @param {type} name
 * @param {type} description
 * @param {type} callback
 * @returns {undefined}
 */
function updateProjecttypeForm(id, serialData, callback) {
    $.ajax({
        url: "/api/courseupdate/" + id,
        type: "PUT",
        data: serialData,
        success: function(data) {
            //viewModel.addTableData(data['id'], data['code'], data['name'], data['description']);
            loadTablePage(1); //TODO now it is refreshing table after updating but it redirects to pagenr 1     WERKT NIET
            callback(true);
        },
        error: function(data) {
            callback(false);
        }
    });
}

/**
 * update project type
 * @param {type} id
 * @param {type} code
 * @param {type} name
 * @param {type} description
 * @param {type} callback
 * @returns {undefined}
 */
function updateProjecttypeRaw(id, code, name, description, callback) {
    updateProjecttypeForm(id, "code=" + encodeURIComponent(code) + "&name=" + encodeURIComponent(name) + "&description=" + encodeURIComponent(description), callback);
}

/*
 * Load page of the table
 */
function loadTablePage(pagenr)
{
    $.getJSON('/api/coursesrapport/page/' + pagenr, function(data){

        /* Clear current table page */
        viewModel.clearTable();

        // Load table data
        $.each(data.data, function(i, item) {
            console.log(item.name);
            viewModel.addTableData(item.id, item.code, item.name, item.description);
        });

        /* Let previous en next buttons work */
        if(data.prev == "none"){
            $('#pager-prev-btn').addClass('disabled');
        } else {
            $('#pager-prev-btn').removeClass('disabled');
            $('#pager-prev-btn a').click(function(){
                loadTablePage(data.prev);
            });
        }

        if(data.next == "none"){
            $('#pager-next-btn').addClass('disabled');
        } else {
            $('#pager-next-btn').removeClass('disabled');
            $('#pager-next-btn a').click(function(){
                loadTablePage(data.next);
            });
        }

        // Number of pager buttons
        var numItems = $('.pager-nr-btn').length;

        /* Calculate for the pager buttons */
        var lowPage = Math.floor(pagenr/numItems) + 1;

        $('.pager-nr-btn').each(function() {
            /* calculate current page number */
            var thispagenr = lowPage++;

            /* Add the page number */
            $(this).html('' + thispagenr + '');

            /* Add active class to current page */
            if(thispagenr == pagenr) {
                $(this).addClass('active');
            } else {
                $(this).removeClass('active');
            }

            /* Disable inactive classes and bind handlers to active classes */
            if(thispagenr > data.pagecount) {
                $(this).addClass('disabled');
            } else {
                /* Add click listener for button */
                $(this).click(function() {
                    loadTablePage(thispagenr);
                });
            }
        });
    });

}

/**
 * Show a new projecttype modal.
 * @returns {undefined}
 */
function showNewProjectTypeModal()
{
    resetGeneralModal();
    setGeneralModalTitle(i18n.__("AddNewCourse"));
    setGeneralModalBody('<form id="newprojectform"> \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('CodeTableTitle') + '" " name="code"> \

 \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('NameTableTitle') + '" name="name"> \

 \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('DescTableTitle') + '" name="description"> \

 \

' +
                '<button class="btn btn-default dropdown-toggle" type="button" id="availableTeacher" data-toggle="dropdown" aria-expanded="true" placeholder="' + i18n.__('TeacherTableTitle') + '">' +
                    'Teacher' +
                    '' +
                '</button>' +
                '
' +
                '

' +
                '
' +
            '
' +
            '</form>' );

    addGeneralModalButton(i18n.__("AddBtn"), function(){
        console.log($('#newprojectform').serialize());
       addNewProjecttypeForm($('#newprojectform').serialize(), function(result){
            hideModal();
        });
    });

    showGeneralModal();
}

/**
 * Show the edit projecttype modal.
 * @param {type} code
 * @param {type} name
 * @param {type} description
 * @param {type} tid
 * @returns {undefined}
 */
function showEditProjectTypeModal(code, name, description, tid)
{
  resetGeneralModal();
    setGeneralModalTitle(i18n.__("EditProjectTitle2"));
    setGeneralModalBody('<form id="updateprojectform"> \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('CodeTableTitle') + '" " name="code" value="' + code + '"> \

 \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('NameTableTitle') + '" name="name" value="' + name + '"> \

 \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('DescTableTitle') + '" name="description" value="' + description + '"> \

 \
        </form>');
    $.getJSON()

    addGeneralModalButton(i18n.__("SaveBtn"), function(){
        updateProjecttypeForm(tid, $('#updateprojectform').serialize(), function(result){
            hideModal();
        });
    });

    addGeneralModalButton(i18n.__("CancelBtn"), function(){
        hideModal();
    })

    showGeneralModal();
}

function showCoupleStudentListModal(projectid) {
    viewModel.currentselectedlist = -1;
    resetGeneralModal();
    setGeneralModalTitle(i18n.__("CoupleStudentList"));
    setGeneralModalBody(
        '
' +
            '<button class="btn btn-default dropdown-toggle" type="button" id="dropdownStudLists" data-toggle="dropdown" aria-expanded="true">' +
                'Dropdown' +
                '' +
            '</button>' +
            '
' +
            '
' +
        '
');

    addGeneralModalButton(i18n.__("SaveBtn"), function() {
        updateListForm(viewModel.currentselectedlist, $('#coupleform').serialize(), function(result){
            hideModal();
        });
    });

    addGeneralModalButton(i18n.__("CancelBtn"), function(){
        hideModal();
    })
    showGeneralModal();
}
function loadCoupleDropdown() {
    $.getJSON('/api/studentlists/' + viewModel.userId, function(data) {
        $.each(data, function(i, item) {
            $("#ddlLists").append('
' + item.name + '
')
            $("#dropdownitem-" + item.id).click(function(){
                $(this).parent().parent().parent().removeClass("open");
                $(this).parent().parent().parent().find(".btn").html($(this).text() + '');
                viewModel.currentselectedlist = item.id;
            });
        });
    });
    $("#dropdownStudLists").click(function() {
        $(this).parent().toggleClass("open");
    });
}

function updateListForm(id, serialData, callback) {
    $.ajax({
        url: "/api/project/" + viewModel.currentprojectid + "/studentlist/" + id,
        type: "POST",
        data: serialData,
        success: function(data) {
            callback(true);
        },
        error: function(data) {
            callback(false);
        }
    });
}

function initPage() {
    // Add button handlers
    $('#addProjectTypeBtn').click(function(){
        showNewProjectTypeModal();
    });

    $.getJSON('/api/currentuser', function(data) {
        viewModel.userId = data.id;
    });

    loadTablePage(1);
}
<commit_msg>coursesrapportenviewmodel teacher<commit_after>// View model for the courses page
function pageViewModel(gvm) {
    // Page specific i18n bindings
    gvm.app  = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ProjectRapportName")}, gvm);
    gvm.title = ko.computed(function(){i18n.setLocale(gvm.lang()); return gvm.app() + ' - ' + i18n.__("CourseTitle2");}, gvm);
    gvm.pageHeader = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("CourseTitle2");}, gvm);
    gvm.projectname = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ProjectRapportName");}, gvm);

    gvm.availableLocations = ko.observableArray([]);
    gvm.availableTrainings = ko.observableArray([]);
    gvm.availableCourses = ko.observableArray([]);

    /*Teacher*/
    gvm.availableTeacher = ko.observableArray([]);
    gvm.currentteacherid = null;
    /*teacher*/

    // Pagination i18n bindings
    gvm.addBtn = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("AddBtn")}, gvm);

    gvm.codeTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("CodeTableTitle");}, gvm);
    gvm.nameTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("NameTableTitle");}, gvm);
    gvm.descTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("DescTableTitle");}, gvm);
    gvm.actionTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ActionTableTitle");}, gvm);

    // The table data observable array
    gvm.tabledata = ko.observableArray([]);

    // Add data to the table
    gvm.addTableData = function(id, code, name, desc) {
        console.log(id + ", " + code + ", " + name + ", " + desc);
        // Push data
        var tblOject = {tid: id, tcode: code, tname: name, tdesc: desc};
        gvm.tabledata.push(tblOject);

        // Attach delete handler to delete button
        $('#removebtn-' + id).bind('click', function(event, data){
            // Delete the table item
            deleteTableItem(id, tblOject);
            event.stopPropagation();
        });

        // Attach edit handler to edit button
        $('#editbtn-' + id).bind('click', function(event, data){
            // Edit the table item
            showEditProjectTypeModal(code, name, desc, id);
            event.stopPropagation();
        });

        //Attach manage handler to manage competences, subcompetences and indicators to manage button
        $('#managebtn-' + id).bind('click', function(event, data) {
            //TODO
        });

        /*$('#studentbtn-' + id).bind('click', function(event, data) {
            showCoupleStudentListModal(id);
            gvm.currentprojectid = id;
            gvm.currentselectedlist = -1;
            event.stopPropagation();
            loadCoupleDropdown();
        });*/
    }

    gvm.clearTable = function() {
        gvm.tabledata.removeAll();
    }

    gvm.updateTeacher = function(id) {
        console.log("updateteacherfunctie1");
    $.getJSON('/api/teacherrapport/' + id, function(data) {
        gvm.availableTeacher.removeAll();
        $.each(data, function(i, item) {
            gvm.availableTeacher.push(item);
                console.log("updateteacherfunctie")
            /* Add listener to listitem */
            $("#teacherbtn-" + item.id).click(function(){
                $(".btn-teacher span:first").text($(this).text());
                gvm.currentteacherid = item.id;
                gvm.saveLastSelectedDropdowns();
                loadTablePage(item.id, 1);
            });
        });
    });
    }
    }
/*
 * Delete item from table given the id.
 */
function deleteTableItem(id, tblOject) {
    showYesNoModal("Bent u zeker dat u dit item wil verwijderen? \r\n Let op: verwijderde items blijven in het systeem en kunnen weer actief gezet worden door een administrator. \r\n Gelieve de administrator te contacteren om een vak definitief te verwijderen.", function(val){
        if(val){
            $.ajax({
                url: "/api/coursedelete/" + id,
                type: "DELETE",
                success: function() {
                    viewModel.tabledata.remove(tblOject);
                }
            });
        }
    });
}

/*
 * Add a new projecttype
 */
function addNewProjecttypeForm(serialData, callback) {
    $.ajax({
            url: "/api/courserapport",
            type: "POST",
            data: serialData,
            success: function(data) {
                viewModel.addTableData(data['id'], data['code'], data['name'], data['description']);
                callback(true);
            },
            error: function(data) {
                callback(false);
            }
        });
}

/*
 * Add a new projecttype
 */
function addNewProjecttypeRaw(code, name, description, callback) {
    addNewProjecttypeForm("code=" + encodeURIComponent(code) + "&name=" + encodeURIComponent(name) + "&description=" + encodeURIComponent(description), callback);
}

/*
 * Update the projecttype
 * @param {type} id
 * @param {type} code
 * @param {type} name
 * @param {type} description
 * @param {type} callback
 * @returns {undefined}
 */
function updateProjecttypeForm(id, serialData, callback) {
    $.ajax({
        url: "/api/courseupdate/" + id,
        type: "PUT",
        data: serialData,
        success: function(data) {
            //viewModel.addTableData(data['id'], data['code'], data['name'], data['description']);
            loadTablePage(1); //TODO now it is refreshing table after updating but it redirects to pagenr 1     WERKT NIET
            callback(true);
        },
        error: function(data) {
            callback(false);
        }
    });
}

/**
 * update project type
 * @param {type} id
 * @param {type} code
 * @param {type} name
 * @param {type} description
 * @param {type} callback
 * @returns {undefined}
 */
function updateProjecttypeRaw(id, code, name, description, callback) {
    updateProjecttypeForm(id, "code=" + encodeURIComponent(code) + "&name=" + encodeURIComponent(name) + "&description=" + encodeURIComponent(description), callback);
}

/*
 * Load page of the table
 */
function loadTablePage(pagenr)
{
    $.getJSON('/api/coursesrapport/page/' + pagenr, function(data){

        /* Clear current table page */
        viewModel.clearTable();

        // Load table data
        $.each(data.data, function(i, item) {
            console.log(item.name);
            viewModel.addTableData(item.id, item.code, item.name, item.description);
        });

        /* Let previous en next buttons work */
        if(data.prev == "none"){
            $('#pager-prev-btn').addClass('disabled');
        } else {
            $('#pager-prev-btn').removeClass('disabled');
            $('#pager-prev-btn a').click(function(){
                loadTablePage(data.prev);
            });
        }

        if(data.next == "none"){
            $('#pager-next-btn').addClass('disabled');
        } else {
            $('#pager-next-btn').removeClass('disabled');
            $('#pager-next-btn a').click(function(){
                loadTablePage(data.next);
            });
        }

        // Number of pager buttons
        var numItems = $('.pager-nr-btn').length;

        /* Calculate for the pager buttons */
        var lowPage = Math.floor(pagenr/numItems) + 1;

        $('.pager-nr-btn').each(function() {
            /* calculate current page number */
            var thispagenr = lowPage++;

            /* Add the page number */
            $(this).html('' + thispagenr + '');

            /* Add active class to current page */
            if(thispagenr == pagenr) {
                $(this).addClass('active');
            } else {
                $(this).removeClass('active');
            }

            /* Disable inactive classes and bind handlers to active classes */
            if(thispagenr > data.pagecount) {
                $(this).addClass('disabled');
            } else {
                /* Add click listener for button */
                $(this).click(function() {
                    loadTablePage(thispagenr);
                });
            }
        });
    });

}

/**
 * Show a new projecttype modal.
 * @returns {undefined}
 */
function showNewProjectTypeModal()
{
    resetGeneralModal();
    setGeneralModalTitle(i18n.__("AddNewCourse"));
    setGeneralModalBody('<form id="newprojectform"> \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('CodeTableTitle') + '" " name="code"> \

 \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('NameTableTitle') + '" name="name"> \

 \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('DescTableTitle') + '" name="description"> \

 \

' +
                '<button class="btn btn-default dropdown-toggle" type="button" id="availableTeacher" data-toggle="dropdown" aria-expanded="true" placeholder="' + i18n.__('TeacherTableTitle') + '">' +
                    'Teacher' + '' +
                '</button>' +
                '
' +
                    '

' +
                '
' +
            '
' +
            '</form>' );

    addGeneralModalButton(i18n.__("AddBtn"), function(){
        console.log($('#newprojectform').serialize());
       addNewProjecttypeForm($('#newprojectform').serialize(), function(result){
            hideModal();
        });
    });

    showGeneralModal();
}

/**
 * Show the edit projecttype modal.
 * @param {type} code
 * @param {type} name
 * @param {type} description
 * @param {type} tid
 * @returns {undefined}
 */
function showEditProjectTypeModal(code, name, description, tid)
{
  resetGeneralModal();
    setGeneralModalTitle(i18n.__("EditProjectTitle2"));
    setGeneralModalBody('<form id="updateprojectform"> \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('CodeTableTitle') + '" " name="code" value="' + code + '"> \

 \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('NameTableTitle') + '" name="name" value="' + name + '"> \

 \

 \
                <input type="text" class="form-control input-lg" placeholder="' + i18n.__('DescTableTitle') + '" name="description" value="' + description + '"> \

 \
        </form>');
    $.getJSON()

    addGeneralModalButton(i18n.__("SaveBtn"), function(){
        updateProjecttypeForm(tid, $('#updateprojectform').serialize(), function(result){
            hideModal();
        });
    });

    addGeneralModalButton(i18n.__("CancelBtn"), function(){
        hideModal();
    })

    showGeneralModal();
}

function showCoupleStudentListModal(projectid) {
    viewModel.currentselectedlist = -1;
    resetGeneralModal();
    setGeneralModalTitle(i18n.__("CoupleStudentList"));
    setGeneralModalBody(
        '
' +
            '<button class="btn btn-default dropdown-toggle" type="button" id="dropdownStudLists" data-toggle="dropdown" aria-expanded="true">' +
                'Dropdown' +
                '' +
            '</button>' +
            '
' +
            '
' +
        '
');

    addGeneralModalButton(i18n.__("SaveBtn"), function() {
        updateListForm(viewModel.currentselectedlist, $('#coupleform').serialize(), function(result){
            hideModal();
        });
    });

    addGeneralModalButton(i18n.__("CancelBtn"), function(){
        hideModal();
    })
    showGeneralModal();
}
function loadCoupleDropdown() {
    $.getJSON('/api/studentlists/' + viewModel.userId, function(data) {
        $.each(data, function(i, item) {
            $("#ddlLists").append('
' + item.name + '
')
            $("#dropdownitem-" + item.id).click(function(){
                $(this).parent().parent().parent().removeClass("open");
                $(this).parent().parent().parent().find(".btn").html($(this).text() + '');
                viewModel.currentselectedlist = item.id;
            });
        });
    });
    $("#dropdownStudLists").click(function() {
        $(this).parent().toggleClass("open");
    });
}

function updateListForm(id, serialData, callback) {
    $.ajax({
        url: "/api/project/" + viewModel.currentprojectid + "/studentlist/" + id,
        type: "POST",
        data: serialData,
        success: function(data) {
            callback(true);
        },
        error: function(data) {
            callback(false);
        }
    });
}

function initPage() {
    // Add button handlers
    $('#addProjectTypeBtn').click(function(){
        showNewProjectTypeModal();
    });

    $.getJSON('/api/currentuser', function(data) {
        viewModel.userId = data.id;
    });

    loadTablePage(1);
}
<|endoftext|>