<commit_before>/**
 * Copyright 2014 Simon Edwards <simon@simonzone.com>
 */
define(['child_process', 'term.js', 'util', 'events', 'lodash-node', 'commandframe'],
function(child_process, termjs, util, events, _, commandframe) {
var EventEmitter = events.EventEmitter;

var debug = false;
function log() {
  if (debug) {
    console.log.apply(console, arguments);
  }
}

var EXTRATERM_COOKIE_ENV = "EXTRATERM_COOKIE";
var SEMANTIC_TYPE = "data-extraterm-type";
var SEMANTIC_VALUE = "data-extraterm-value";
var SEMANTIC_START_OUTPUT = "data-extraterm-start-output";
var SEMANTIC_RETURN_CODE = "data-extraterm-return-code";

var APPLICATION_MODE_NONE = 0;
var APPLICATION_MODE_HTML = 1;
var APPLICATION_MODE_OUTPUT_BRACKET_START = 2;
var APPLICATION_MODE_OUTPUT_BRACKET_END = 3;
var TYPE_OUTPUT_START = "command-output-start";
var TYPE_OUTPUT = "command-output";

/**
 * Create a new terminal.
 *
 * See startUp().
 *
 * @param {type} parentElement The DOM element under which the terminal will
 *     be placed.
 * @returns {Terminal}
 */
function Terminal(parentElement) {
  if (!(this instanceof Terminal)) {
    throw new Error("Call Terminal using the new keyword.");
  }
  this._parentElement = parentElement;
  _.bindAll(this);

  this._term = null;
  this._htmlData = null;
  this._applicationMode = APPLICATION_MODE_NONE;
  this._bracketStyle = null;
  this._lastBashBracket = null;
  this._blinkingCursor = false;
  this._title = "New Tab";
}
util.inherits(Terminal, EventEmitter);

/**
 * Destroy the terminal.
 */
Terminal.prototype.destroy = function() {

  if (this._ptyBridge !== null) {
    this._ptyBridge.removeAllListeners();

    this._ptyBridge.kill('SIGHUP');
    this._ptyBridge.disconnect();
    this._ptyBridge = null;
  }

  if (this._term !== null) {
    this._getWindow().removeEventListener('resize', this._handleResize);
    this._getWindow().document.body.removeEventListener('click', this._handleWindowClick);
    this._term.destroy();
  }
  this._term = null;
};

Terminal.prototype.getTitle = function() {
  return this._title;
};

/**
 * Set whether the cursor should blink.
 *
 * @param {boolean} blink Set to true if the cursor should blink.
 */
Terminal.prototype.setBlinkingCursor = function(blinking) {
  this._blinkingCursor = blinking;
  if (this._term !== null) {
    this._term.setCursorBlink(blinking);
  }
};

/**
 * Get the window which this terminal is on.
 *
 * @returns {Window} The window object.
 */
Terminal.prototype._getWindow = function() {
  return this._parentElement.ownerDocument.defaultView;
};

Terminal.prototype._colors = function() {
  var colorList = termjs.Terminal.colors.slice();
  var i;

  var linuxColors = [
    "#000000",
    "#b21818",
    "#18b218",
    "#b26818",
    "#3535ff",
    "#b218b2",
    "#18b2b2",
    "#b2b2b2",
    "#686868",
    "#ff5454",
    "#54ff54",
    "#ffff54",
    "#7373ff",
    "#ff54ff",
    "#54ffff",
    "#ffffff"];

  for (i=0; i < linuxColors.length; i++) {
    colorList[i] = linuxColors[i];
  }

  colorList[256] = "#000000";
  colorList[257] = "#b2b2b2";

  return colorList;
};

/**
 * Start the terminal up.
 *
 * This method should be called once all event handlers have been set up.
 */
Terminal.prototype.startUp = function() {
  var size;
  var cookie;

  cookie = "DEADBEEF";  // FIXME
  process.env[EXTRATERM_COOKIE_ENV] = cookie;

  this._term = new termjs.Terminal({
    cols: 80,
    rows: 30,
    colors: this._colors(),
    scrollback: 10000,
    cursorBlink: this._blinkingCursor,
    physicalScroll: true,
    applicationModeCookie: cookie
  });
  this._term.debug = true;
  this._term.on('title', this._handleTitle);
  this._term.on('data', this._handleTermData);
  this._getWindow().addEventListener('resize', this._handleResize);
  this._term.on('key', this._handleKeyDown);
  this._term.on('unknown-keydown', this._handleUnknownKeyDown);

  // Application mode handlers
  this._term.on('application-mode-start', this._handleApplicationModeStart);
  this._term.on('application-mode-data', this._handleApplicationModeData);
  this._term.on('application-mode-end', this._handleApplicationModeEnd);

  // Window DOM event handlers
  this._getWindow().document.body.addEventListener('click', this._handleWindowClick);

  this._term.open(this._parentElement);
  this._term.write('\x1b[31mWelcome to Extraterm!\x1b[m\r\n');

  // Start our PTY bridge process and connect it to our terminal.
  this._ptyBridge = child_process.spawn('node', ['pty_bridge.js'], {
    env: process.env
  });
  this._ptyBridge.stdout.on('data', this._handlePtyStdoutData);
  this._ptyBridge.stderr.on('data', this._handlePtyStderrData);
  this._ptyBridge.on('close', this._handlePtyClose);

  size = this._term.resizeToContainer();
  this._sendResize(size.cols, size.rows);
};

/**
 * Focus on this terminal.
 */
Terminal.prototype.focus = function() {
  if (this._term !== null) {
    this._term.focus();
  }
};

Terminal.prototype.write = function(text) {
  if (this._term !== null) {
    this._term.write(text);
  }
};

Terminal.prototype.send = function(text) {
  if (this._term !== null) {
    this._sendDataToPty(text);
  }
};

Terminal.prototype.scrollToBottom = function() {
  this._term.scrollToBottom();
};

/**
 * Handler for window title change events from the pty.
 *
 * @param {String} title The new window title for this terminal.
 */
Terminal.prototype._handleTitle = function(title) {
  this._title = title;
  this.emit('title', this, title);
};

/**
 * Handle a resize event from the window.
 */
Terminal.prototype._handleResize = function() {
  var size = this._term.resizeToContainer();
  this._sendResize(size.cols, size.rows);
};

Terminal.prototype._handleKeyDown = function(key, ev) {
  if (key !== null) {
    this._term.scrollToBottom();
  }
};

Terminal.prototype._handleUnknownKeyDown = function(ev) {
  this.emit('unknown-keydown', this, ev);
  return false;
};

/**
 * Handle when the embedded term.js enters start of application mode.
 *
 * @param {array} params The list of parameter which were specified in the
 *     escape sequence.
 */
Terminal.prototype._handleApplicationModeStart = function(params) {
  log("application-mode started! ",params);
  if (params.length === 1) {
    // Normal HTML mode.
    this._applicationMode = APPLICATION_MODE_HTML;

  } else if(params.length >= 2) {
    switch ("" + params[1]) {
      case "2":
      this._applicationMode = APPLICATION_MODE_OUTPUT_BRACKET_START;
      this._bracketStyle = params[2];
      break;

    case "3":
      this._applicationMode = APPLICATION_MODE_OUTPUT_BRACKET_END;
      log("Starting APPLICATION_MODE_OUTPUT_BRACKET_END");
      break;

    default:
      log("Unrecognized application escape parameters.");
      break;
    }
  }
  this._htmlData = "";
};

/**
 * Handle incoming data while in application mode.
 *
 * @param {string} data The new data.
 */
Terminal.prototype._handleApplicationModeData = function(data) {
//      console.log("html-mode data!", data);
  if (this._applicationMode !== APPLICATION_MODE_NONE) {
    this._htmlData = this._htmlData + data;
  }
};

/**
 * Handle the exit from application mode.
 */
Terminal.prototype._handleApplicationModeEnd = function() {
  var el;
  var cleancommand;
  var trimmed;
  var startdivs;
  var outputdiv;
  var node;
  var nodelist;

  switch (this._applicationMode) {
    case APPLICATION_MODE_HTML:
      el = this._getWindow().document.createElement("div");
      el.innerHTML = this._htmlData;
      this._term.appendElement(el);
      break;

    case APPLICATION_MODE_OUTPUT_BRACKET_START:
      if (this._lastBashBracket !== this._htmlData) {
        el = this._getWindow().document.createElement("et-commandframe");
        el.addEventListener('close-request', function() {
          el.remove();
        });
        cleancommand = this._htmlData;
        if (this._bracketStyle === "bash") {
          // Bash includes the history number. Remove it.
          trimmed = this._htmlData.trimLeft();
          cleancommand = trimmed.slice(trimmed.indexOf(" ")).trimLeft();
        }
        el.setAttribute('command-line', cleancommand);
        this._term.appendElement(el);
        this._lastBashBracket = this._htmlData;
      }
      break;

    case APPLICATION_MODE_OUTPUT_BRACKET_END:
      log("startdivs:", startdivs);
      this._term.moveRowsToScrollback();
      startdivs = this._term.element.querySelectorAll("et-commandframe:not([return-code])");
      if (startdivs.length !== 0) {
        outputdiv = startdivs[startdivs.length-1];
        node = outputdiv.nextSibling;

        nodelist = [];
        while (node !== null) {
          nodelist.push(node);
          node = node.nextSibling;
        }
        nodelist.forEach(function(node) {
          outputdiv.appendChild(node);
        });
        outputdiv.setAttribute('return-code', this._htmlData);
        outputdiv.className = "extraterm_output";
      }

      break;

    default:
      break;
  }
  this._applicationMode = APPLICATION_MODE_NONE;

  log("html-mode end!",this._htmlData);
  this._htmlData = null;
};

/**
 * Handle a click inside the terminal.
 *
 * @param {event} event
 */
Terminal.prototype._handleWindowClick = function(event) {
  var type;
  var value;

//      log("body on click!",event);
  type = event.srcElement.getAttribute(SEMANTIC_TYPE);
  value = event.srcElement.getAttribute(SEMANTIC_VALUE);
  this._handleMineTypeClick(type, value);
};

/**
 * Handle new stdout data from the pty.
 *
 * @param {string} data New data.
 */
Terminal.prototype._handlePtyStdoutData = function (data) {
  log("incoming data:",""+data);
  this._term.write("" + data);
};

/**
 * Handle new stderr data from the pty.
 *
 * @param {type} data New data.
 */
Terminal.prototype._handlePtyStderrData = function(data) {
  this._term.write(data);
};

/**
 * Handle a pty close event.
 *
 * @param {string} data
 */
Terminal.prototype._handlePtyClose = function(data) {
  this._ptyBridge = null;
  this.emit('ptyclose', this);
};

/**
 * Handle data coming from the user.
 *
 * This just pushes the keys from the user through to the pty.
 * @param {string} data The data to process.
 */
Terminal.prototype._handleTermData = function(data) {
  this._sendDataToPty(data);
};

/**
 * Send data to the pseudoterminal.
 *
 * @param {string} text
 * @param {function} callback (Optional) Callback to call once the data has
 *     been sent.
 */
Terminal.prototype._sendDataToPty = function(text, callback) {
  var jsonString = JSON.stringify({stream: text});
//      console.log("<<< json string is ",jsonString);
//      console.log("<<< json string length is ",jsonString.length);
  var sizeHeaderBuffer = new Buffer(4);
  sizeHeaderBuffer.writeUInt32BE(jsonString.length, 0);

  this._ptyBridge.stdin.write(sizeHeaderBuffer);
  this._ptyBridge.stdin.write(jsonString, callback);
};

/**
 * Send a resize message to the pty.
 *
 * @param {number} cols The new number of columns in the terminal.
 * @param {number} rows The new number of rows in the terminal.
 * @param {function} callback (Optional) Callback to call once the data has
 *     been sent.
 */
Terminal.prototype._sendResize = function(cols, rows, callback) {
  var jsonString = JSON.stringify({resize: [cols, rows]});
//      console.log("<<< json string is ",jsonString);
//      console.log("<<< json string length is ",jsonString.length);
  var sizeHeaderBuffer = new Buffer(4);
  sizeHeaderBuffer.writeUInt32BE(jsonString.length, 0);

  this._ptyBridge.stdin.write(sizeHeaderBuffer);
  this._ptyBridge.stdin.write(jsonString, callback);
};

/**
 * Process a click on a item of the given mimetype and value.
 *
 * @param {string} type
 * @param {string} value
 */
Terminal.prototype._handleMineTypeClick = function(type, value) {
  if (type === "directory") {
    this._sendDataToPty("cd " + value + "\n"); // FIXME escaping
  }
};

return {
  Terminal: Terminal
};

});
<commit_msg>Produce fewer blank lines.<commit_after>/**
 * Copyright 2014 Simon Edwards <simon@simonzone.com>
 */
define(['child_process', 'term.js', 'util', 'events', 'lodash-node', 'commandframe'],
function(child_process, termjs, util, events, _, commandframe) {
var EventEmitter = events.EventEmitter;

var debug = false;
function log() {
  if (debug) {
    console.log.apply(console, arguments);
  }
}

var EXTRATERM_COOKIE_ENV = "EXTRATERM_COOKIE";
var SEMANTIC_TYPE = "data-extraterm-type";
var SEMANTIC_VALUE = "data-extraterm-value";
var SEMANTIC_START_OUTPUT = "data-extraterm-start-output";
var SEMANTIC_RETURN_CODE = "data-extraterm-return-code";

var APPLICATION_MODE_NONE = 0;
var APPLICATION_MODE_HTML = 1;
var APPLICATION_MODE_OUTPUT_BRACKET_START = 2;
var APPLICATION_MODE_OUTPUT_BRACKET_END = 3;
var TYPE_OUTPUT_START = "command-output-start";
var TYPE_OUTPUT = "command-output";

/**
 * Create a new terminal.
 *
 * See startUp().
 *
 * @param {type} parentElement The DOM element under which the terminal will
 *     be placed.
 * @returns {Terminal}
 */
function Terminal(parentElement) {
  if (!(this instanceof Terminal)) {
    throw new Error("Call Terminal using the new keyword.");
  }
  this._parentElement = parentElement;
  _.bindAll(this);

  this._term = null;
  this._htmlData = null;
  this._applicationMode = APPLICATION_MODE_NONE;
  this._bracketStyle = null;
  this._lastBashBracket = null;
  this._blinkingCursor = false;
  this._title = "New Tab";
}
util.inherits(Terminal, EventEmitter);

/**
 * Destroy the terminal.
 */
Terminal.prototype.destroy = function() {

  if (this._ptyBridge !== null) {
    this._ptyBridge.removeAllListeners();

    this._ptyBridge.kill('SIGHUP');
    this._ptyBridge.disconnect();
    this._ptyBridge = null;
  }

  if (this._term !== null) {
    this._getWindow().removeEventListener('resize', this._handleResize);
    this._getWindow().document.body.removeEventListener('click', this._handleWindowClick);
    this._term.destroy();
  }
  this._term = null;
};

Terminal.prototype.getTitle = function() {
  return this._title;
};

/**
 * Set whether the cursor should blink.
 *
 * @param {boolean} blink Set to true if the cursor should blink.
 */
Terminal.prototype.setBlinkingCursor = function(blinking) {
  this._blinkingCursor = blinking;
  if (this._term !== null) {
    this._term.setCursorBlink(blinking);
  }
};

/**
 * Get the window which this terminal is on.
 *
 * @returns {Window} The window object.
 */
Terminal.prototype._getWindow = function() {
  return this._parentElement.ownerDocument.defaultView;
};

Terminal.prototype._colors = function() {
  var colorList = termjs.Terminal.colors.slice();
  var i;

  var linuxColors = [
    "#000000",
    "#b21818",
    "#18b218",
    "#b26818",
    "#3535ff",
    "#b218b2",
    "#18b2b2",
    "#b2b2b2",
    "#686868",
    "#ff5454",
    "#54ff54",
    "#ffff54",
    "#7373ff",
    "#ff54ff",
    "#54ffff",
    "#ffffff"];

  for (i=0; i < linuxColors.length; i++) {
    colorList[i] = linuxColors[i];
  }

  colorList[256] = "#000000";
  colorList[257] = "#b2b2b2";

  return colorList;
};

/**
 * Start the terminal up.
 *
 * This method should be called once all event handlers have been set up.
 */
Terminal.prototype.startUp = function() {
  var size;
  var cookie;

  cookie = "DEADBEEF";  // FIXME
  process.env[EXTRATERM_COOKIE_ENV] = cookie;

  this._term = new termjs.Terminal({
    cols: 80,
    rows: 30,
    colors: this._colors(),
    scrollback: 10000,
    cursorBlink: this._blinkingCursor,
    physicalScroll: true,
    applicationModeCookie: cookie
  });
  this._term.debug = true;
  this._term.on('title', this._handleTitle);
  this._term.on('data', this._handleTermData);
  this._getWindow().addEventListener('resize', this._handleResize);
  this._term.on('key', this._handleKeyDown);
  this._term.on('unknown-keydown', this._handleUnknownKeyDown);

  // Application mode handlers
  this._term.on('application-mode-start', this._handleApplicationModeStart);
  this._term.on('application-mode-data', this._handleApplicationModeData);
  this._term.on('application-mode-end', this._handleApplicationModeEnd);

  // Window DOM event handlers
  this._getWindow().document.body.addEventListener('click', this._handleWindowClick);

  this._term.open(this._parentElement);
  this._term.write('\x1b[31mWelcome to Extraterm!\x1b[m\r\n');

  // Start our PTY bridge process and connect it to our terminal.
  this._ptyBridge = child_process.spawn('node', ['pty_bridge.js'], {
    env: process.env
  });
  this._ptyBridge.stdout.on('data', this._handlePtyStdoutData);
  this._ptyBridge.stderr.on('data', this._handlePtyStderrData);
  this._ptyBridge.on('close', this._handlePtyClose);

  size = this._term.resizeToContainer();
  this._sendResize(size.cols, size.rows);
};

/**
 * Focus on this terminal.
 */
Terminal.prototype.focus = function() {
  if (this._term !== null) {
    this._term.focus();
  }
};

Terminal.prototype.write = function(text) {
  if (this._term !== null) {
    this._term.write(text);
  }
};

Terminal.prototype.send = function(text) {
  if (this._term !== null) {
    this._sendDataToPty(text);
  }
};

Terminal.prototype.scrollToBottom = function() {
  this._term.scrollToBottom();
};

/**
 * Handler for window title change events from the pty.
 *
 * @param {String} title The new window title for this terminal.
 */
Terminal.prototype._handleTitle = function(title) {
  this._title = title;
  this.emit('title', this, title);
};

/**
 * Handle a resize event from the window.
 */
Terminal.prototype._handleResize = function() {
  var size = this._term.resizeToContainer();
  this._sendResize(size.cols, size.rows);
};

Terminal.prototype._handleKeyDown = function(key, ev) {
  if (key !== null) {
    this._term.scrollToBottom();
  }
};

Terminal.prototype._handleUnknownKeyDown = function(ev) {
  this.emit('unknown-keydown', this, ev);
  return false;
};

/**
 * Handle when the embedded term.js enters start of application mode.
 *
 * @param {array} params The list of parameter which were specified in the
 *     escape sequence.
 */
Terminal.prototype._handleApplicationModeStart = function(params) {
  log("application-mode started! ",params);
  if (params.length === 1) {
    // Normal HTML mode.
    this._applicationMode = APPLICATION_MODE_HTML;

  } else if(params.length >= 2) {
    switch ("" + params[1]) {
      case "2":
      this._applicationMode = APPLICATION_MODE_OUTPUT_BRACKET_START;
      this._bracketStyle = params[2];
      break;

    case "3":
      this._applicationMode = APPLICATION_MODE_OUTPUT_BRACKET_END;
      log("Starting APPLICATION_MODE_OUTPUT_BRACKET_END");
      break;

    default:
      log("Unrecognized application escape parameters.");
      break;
    }
  }
  this._htmlData = "";
};

/**
 * Handle incoming data while in application mode.
 *
 * @param {string} data The new data.
 */
Terminal.prototype._handleApplicationModeData = function(data) {
//      console.log("html-mode data!", data);
  if (this._applicationMode !== APPLICATION_MODE_NONE) {
    this._htmlData = this._htmlData + data;
  }
};

/**
 * Handle the exit from application mode.
 */
Terminal.prototype._handleApplicationModeEnd = function() {
  var el;
  var cleancommand;
  var trimmed;
  var startdivs;
  var outputdiv;
  var node;
  var nodelist;

  switch (this._applicationMode) {
    case APPLICATION_MODE_HTML:
      el = this._getWindow().document.createElement("div");
      el.innerHTML = this._htmlData;
      this._term.appendElement(el);
      break;

    case APPLICATION_MODE_OUTPUT_BRACKET_START:
      if (this._lastBashBracket !== this._htmlData) {
        el = this._getWindow().document.createElement("et-commandframe");
        el.addEventListener('close-request', function() {
          el.remove();
        });
        cleancommand = this._htmlData;
        if (this._bracketStyle === "bash") {
          // Bash includes the history number. Remove it.
          trimmed = this._htmlData.trimLeft();
          cleancommand = trimmed.slice(trimmed.indexOf(" ")).trimLeft();
        }
        el.setAttribute('command-line', cleancommand);
        this._term.appendElement(el);
        this._lastBashBracket = this._htmlData;
      }
      break;

    case APPLICATION_MODE_OUTPUT_BRACKET_END:
      log("startdivs:", startdivs);
      startdivs = this._term.element.querySelectorAll("et-commandframe:not([return-code])");
      if (startdivs.length !== 0) {
        this._term.moveRowsToScrollback();
        outputdiv = startdivs[startdivs.length-1];
        node = outputdiv.nextSibling;

        nodelist = [];
        while (node !== null) {
          nodelist.push(node);
          node = node.nextSibling;
        }
        nodelist.forEach(function(node) {
          outputdiv.appendChild(node);
        });
        outputdiv.setAttribute('return-code', this._htmlData);
        outputdiv.className = "extraterm_output";
      }

      break;

    default:
      break;
  }
  this._applicationMode = APPLICATION_MODE_NONE;

  log("html-mode end!",this._htmlData);
  this._htmlData = null;
};

/**
 * Handle a click inside the terminal.
 *
 * @param {event} event
 */
Terminal.prototype._handleWindowClick = function(event) {
  var type;
  var value;

//      log("body on click!",event);
  type = event.srcElement.getAttribute(SEMANTIC_TYPE);
  value = event.srcElement.getAttribute(SEMANTIC_VALUE);
  this._handleMineTypeClick(type, value);
};

/**
 * Handle new stdout data from the pty.
 *
 * @param {string} data New data.
 */
Terminal.prototype._handlePtyStdoutData = function (data) {
  log("incoming data:",""+data);
  this._term.write("" + data);
};

/**
 * Handle new stderr data from the pty.
 *
 * @param {type} data New data.
 */
Terminal.prototype._handlePtyStderrData = function(data) {
  this._term.write(data);
};

/**
 * Handle a pty close event.
 *
 * @param {string} data
 */
Terminal.prototype._handlePtyClose = function(data) {
  this._ptyBridge = null;
  this.emit('ptyclose', this);
};

/**
 * Handle data coming from the user.
 *
 * This just pushes the keys from the user through to the pty.
 * @param {string} data The data to process.
 */
Terminal.prototype._handleTermData = function(data) {
  this._sendDataToPty(data);
};

/**
 * Send data to the pseudoterminal.
 *
 * @param {string} text
 * @param {function} callback (Optional) Callback to call once the data has
 *     been sent.
 */
Terminal.prototype._sendDataToPty = function(text, callback) {
  var jsonString = JSON.stringify({stream: text});
//      console.log("<<< json string is ",jsonString);
//      console.log("<<< json string length is ",jsonString.length);
  var sizeHeaderBuffer = new Buffer(4);
  sizeHeaderBuffer.writeUInt32BE(jsonString.length, 0);

  this._ptyBridge.stdin.write(sizeHeaderBuffer);
  this._ptyBridge.stdin.write(jsonString, callback);
};

/**
 * Send a resize message to the pty.
 *
 * @param {number} cols The new number of columns in the terminal.
 * @param {number} rows The new number of rows in the terminal.
 * @param {function} callback (Optional) Callback to call once the data has
 *     been sent.
 */
Terminal.prototype._sendResize = function(cols, rows, callback) {
  var jsonString = JSON.stringify({resize: [cols, rows]});
//      console.log("<<< json string is ",jsonString);
//      console.log("<<< json string length is ",jsonString.length);
  var sizeHeaderBuffer = new Buffer(4);
  sizeHeaderBuffer.writeUInt32BE(jsonString.length, 0);

  this._ptyBridge.stdin.write(sizeHeaderBuffer);
  this._ptyBridge.stdin.write(jsonString, callback);
};

/**
 * Process a click on a item of the given mimetype and value.
 *
 * @param {string} type
 * @param {string} value
 */
Terminal.prototype._handleMineTypeClick = function(type, value) {
  if (type === "directory") {
    this._sendDataToPty("cd " + value + "\n"); // FIXME escaping
  }
};

return {
  Terminal: Terminal
};

});
<|endoftext|>


<commit_before>require('dotenv').config();

const session = require('express-session');
const connectSQLite3 = require('connect-sqlite3');

exports.createExpressSession = () => {
  const SQLiteStore = connectSQLite3(session);
  const session_store = new SQLiteStore({
    table: 'sessions',
    db: process.env.DB_PATH
  });

  const sessionConfig = {
    secret: process.env.SESSION_SECRET,
    cookie: {
      maxAge: parseInt(process.env.SESSION_MAX_AGE, 10) * 1000,
    },
    resave: false,
    saveUninitialized: true,
    store: session_store
  };

  return session(sessionConfig);

};
<commit_msg>fix: Change default Layman cookie name so the auth doesn't interfere with other apps<commit_after>require('dotenv').config();

const session = require('express-session');
const connectSQLite3 = require('connect-sqlite3');

exports.createExpressSession = () => {
  const SQLiteStore = connectSQLite3(session);
  const session_store = new SQLiteStore({
    table: 'sessions',
    db: process.env.DB_PATH
  });

  const sessionConfig = {
    name: "connect-hsl.sid",
    secret: process.env.SESSION_SECRET,
    cookie: {
      maxAge: parseInt(process.env.SESSION_MAX_AGE, 10) * 1000,
    },
    resave: false,
    saveUninitialized: true,
    store: session_store
  };

  return session(sessionConfig);

};
<|endoftext|>


<commit_before><commit_msg>small typo fix<commit_after><|endoftext|>


<commit_before>var http = require('http');
var connect = require('connect');

var buildDir = 'dist';

var app = connect();

var staticDir = __dirname + '/' + buildDir;
app.use(connect.static(staticDir));

var server = http.createServer(app).listen(process.env.PORT || 3000, function() {
  console.log('Connect server started on port', server.address().port);
  console.log('Serving static directory "' + staticDir + '/"');
});<commit_msg>Serve config.js using the current environment variables in server.js<commit_after>var http = require('http');
var connect = require('connect');

var gulp = require('gulp');
var path = require('path');
var pkg = require('./package.json');
var send = require('./lib/gulp-send');
var template = require('gulp-template');

var buildDir = 'dist';
var ROOT = __dirname;

var app = connect();

var staticDir = __dirname + '/' + buildDir;

app.use('/config.js', function(req, res) {
  res.setHeader('Content-Type', 'text/javascript');

  gulp.src(path.join(ROOT, 'app/config.js'))
    .pipe(template({
                     process: {env: process.env},
                     pkg: pkg
                   }))
    .on('error', function(err) {
          next(err);
        })
    .pipe(send(res));
});

app.use(connect.static(staticDir));

var server = http.createServer(app).listen(process.env.PORT || 3000, function() {
  console.log('Connect server started on port', server.address().port);
  console.log('Serving static directory "' + staticDir + '/"');
});<|endoftext|>


<commit_before>(function() {
	'use strict';
	function Menu() {}

	Menu.prototype = {
		create: function() {
			game.stage.backgroundColor = '#fff';
			this.LIGHT_RADIUS = 350;
			this.highScore = 0;
			this.lastScore = 0;
			this.getScore();

			this.shadowTexture = this.game.add.bitmapData(this.game.width, this.game.height);
			this.shadowTexture.context.fillStyle = 'rgb(0, 0, 0)';
			this.shadowTexture.context.fillRect(0, 0, this.game.width, this.game.height);

			var gradient = this.shadowTexture.context.createRadialGradient(
				game.world.centerX + 10 , game.world.centerY + 10, this.LIGHT_RADIUS * 0.75,
				game.world.centerX + 10, game.world.centerY + 10, this.LIGHT_RADIUS);
			gradient.addColorStop(0, 'rgba(255, 255, 255, 1.0)');
			gradient.addColorStop(1, 'rgba(255, 255, 255, 0.0)');

			this.shadowTexture.context.beginPath();
			this.shadowTexture.context.fillStyle = gradient;
			this.shadowTexture.context.arc(game.world.centerX + 10, game.world.centerY + 10,
				this.LIGHT_RADIUS, 0, Math.PI*2);
			this.shadowTexture.context.fill();

			var light =  game.add.bitmapData(100, 100);
			light.context.beginPath();
			light.context.arc(10, 10 , 10, 0, 2 * Math.PI, false);
			light.context.fillStyle = 'rgba(0, 0, 0, 1.0)';
			light.context.fill();
			game.add.sprite(game.world.centerX, game.world.centerY,light);

			this.enterKey = game.input.keyboard.addKey(Phaser.Keyboard.ENTER);
			this.enterKey.onDown.add(this.startGame, this);

			this.lightSprite = game.add.image(0, 0, this.shadowTexture);
			this.lightSprite.blendMode = Phaser.blendModes.MULTIPLY;

			this.text = game.add.text(game.world.centerX, 150, "Drop the light", {
				font: "30px Source Code Pro",
				fill: "#0f0f0f",
				align: "center"
			});
			this.textTut = game.add.text(game.world.centerX, 200 , "Use the arroy keys & press enter to start", {
				font: "20px Source Code Pro",
				fill: "#0f0f0f",
				align: "center"
			});
			this.text.anchor.setTo(0.5, 0.5);
			this.textTut.anchor.setTo(0.5, 0.5);

			this.scoreTxt = game.add.text(game.world.centerX, 250, " High Score: " + this.highScore + "\n Last Score: " + this.lastScore, {
				font: "20px Source Code Pro",
				fill: "#0f0f0f",
				align: "left"
			});

			this.scoreTxt.anchor.setTo(0.5, 0.5);

			this.creditsTxt = game.add.text(game.world.centerX, this.world.height - 20, " Made with Phaser by Arlefreak ", {
				font: "14px Source Code Pro",
				fill: "#ffffff",
				align: "left"
			});

			this.creditsTxt.anchor.setTo(0.5, 0.5);
		},

		update: function() {
			if (game.input.activePointer.isDown){
				this.startGame();
			}
		},

		startGame: function() {
			game.state.start('play');
		},

		getScore: function(){
			this.lastScore = localStorage.getItem('lastScore');
			this.highScore = localStorage.getItem('highScore');
			if (typeof(this.highScore) == 'undefined' || this.highScore == null || isNaN(this.highScore)){
				this.highScore = 0;
				this.lastScore = 0;
				localStorage.setItem('highScore', this.highScore);
				localStorage.setItem('lastScore', this.lastScore);
			}
			this.highScore = parseInt(this.highScore,10);
			this.lastScore = parseInt(this.lastScore,10);
			if(this.highScore < this.lastScore ){
				this.highScore = this.lastScore;
				localStorage.setItem('highScore', this.lastScore);
			}
		}
	};
	MainMenuS = Menu;
}());<commit_msg>Fixed typo<commit_after>(function() {
	'use strict';
	function Menu() {}

	Menu.prototype = {
		create: function() {
			game.stage.backgroundColor = '#fff';
			this.LIGHT_RADIUS = 350;
			this.highScore = 0;
			this.lastScore = 0;
			this.getScore();

			this.shadowTexture = this.game.add.bitmapData(this.game.width, this.game.height);
			this.shadowTexture.context.fillStyle = 'rgb(0, 0, 0)';
			this.shadowTexture.context.fillRect(0, 0, this.game.width, this.game.height);

			var gradient = this.shadowTexture.context.createRadialGradient(
				game.world.centerX + 10 , game.world.centerY + 10, this.LIGHT_RADIUS * 0.75,
				game.world.centerX + 10, game.world.centerY + 10, this.LIGHT_RADIUS);
			gradient.addColorStop(0, 'rgba(255, 255, 255, 1.0)');
			gradient.addColorStop(1, 'rgba(255, 255, 255, 0.0)');

			this.shadowTexture.context.beginPath();
			this.shadowTexture.context.fillStyle = gradient;
			this.shadowTexture.context.arc(game.world.centerX + 10, game.world.centerY + 10,
				this.LIGHT_RADIUS, 0, Math.PI*2);
			this.shadowTexture.context.fill();

			var light =  game.add.bitmapData(100, 100);
			light.context.beginPath();
			light.context.arc(10, 10 , 10, 0, 2 * Math.PI, false);
			light.context.fillStyle = 'rgba(0, 0, 0, 1.0)';
			light.context.fill();
			game.add.sprite(game.world.centerX, game.world.centerY,light);

			this.enterKey = game.input.keyboard.addKey(Phaser.Keyboard.ENTER);
			this.enterKey.onDown.add(this.startGame, this);

			this.lightSprite = game.add.image(0, 0, this.shadowTexture);
			this.lightSprite.blendMode = Phaser.blendModes.MULTIPLY;

			this.text = game.add.text(game.world.centerX, 150, "Drop the light", {
				font: "30px Source Code Pro",
				fill: "#0f0f0f",
				align: "center"
			});
			this.textTut = game.add.text(game.world.centerX, 200 , "Use the arrow keys & press enter to start", {
				font: "20px Source Code Pro",
				fill: "#0f0f0f",
				align: "center"
			});
			this.text.anchor.setTo(0.5, 0.5);
			this.textTut.anchor.setTo(0.5, 0.5);

			this.scoreTxt = game.add.text(game.world.centerX, 250, " High Score: " + this.highScore + "\n Last Score: " + this.lastScore, {
				font: "20px Source Code Pro",
				fill: "#0f0f0f",
				align: "left"
			});

			this.scoreTxt.anchor.setTo(0.5, 0.5);

			this.creditsTxt = game.add.text(game.world.centerX, this.world.height - 20, " Made with Phaser by Arlefreak ", {
				font: "14px Source Code Pro",
				fill: "#ffffff",
				align: "left"
			});

			this.creditsTxt.anchor.setTo(0.5, 0.5);
		},

		update: function() {
			if (game.input.activePointer.isDown){
				this.startGame();
			}
		},

		startGame: function() {
			game.state.start('play');
		},

		getScore: function(){
			this.lastScore = localStorage.getItem('lastScore');
			this.highScore = localStorage.getItem('highScore');
			if (typeof(this.highScore) == 'undefined' || this.highScore == null || isNaN(this.highScore)){
				this.highScore = 0;
				this.lastScore = 0;
				localStorage.setItem('highScore', this.highScore);
				localStorage.setItem('lastScore', this.lastScore);
			}
			this.highScore = parseInt(this.highScore,10);
			this.lastScore = parseInt(this.lastScore,10);
			if(this.highScore < this.lastScore ){
				this.highScore = this.lastScore;
				localStorage.setItem('highScore', this.lastScore);
			}
		}
	};
	MainMenuS = Menu;
}());<|endoftext|>


<commit_before>var _ = require('lodash'),
    util = require('util');

/**
 * @module mongoose-stripe-customers
 * @example
 ```js
var mongooseStripeCustomers = require('mongoose-stripe-customers');

var schema = Schema({...});

schema.plugin(mongooseStripeCustomers, {
    stripeApiKey: 'XXXXXXXXXXXXXXXX',
    hook: 'save',
    firstNameField: 'first_name',
    lastNameField: 'last_name',
    emailField: 'email',
    metaData: [ '_id', 'phone', 'customerType' ]
});
 ```
 */

module.exports = function stripeCustomersPlugin(schema, options) {
    /**
     * @param {object} options
     * @param {string} options.stripeApiKey - The Stripe secret key used to access the Stripe API.
     * @param {string} [options.hook=save] - The document hook you want this to run before.
     * @param {object} [options.fieldNames] - Response field overrides.
     * @param {string} [options.stripeCustomerIdField=stripe_customer_id] - The field in which you want the Stripe customer ID value to be stored.
     * @param {string} [options.firstNameField] - The field in which the customer's first name is stored.
     * @param {string} [options.lastNameField] - The field in which the customer's last name is stored.
     * @param {string} [options.emailField] - The field in which the customer's email address is stored.
     * @param {string[]} [options.metaData[]] - If you want any extra data stored with the customer on Stripe, provide an array of field names.
     */
    options = _.merge({
        hook: 'save',
        stripeCustomerIdField: 'stripe_customer_id'
    }, options || {});

    if(!options.stripeApiKey) {
        throw new Error('Stripe API key must be provided to mongoose-stripe-customers.');
    }

    var stripe = require('stripe')(options.stripeApiKey);

    // Add the stripe customer id path to the schema.
    if(!schema.path(options.stripeCustomerIdField)) {
        schema.path(options.stripeCustomerIdField, {
            type: String,
            unique: true,
            trim: true
        });
    }

    schema.pre(options.hook, true, function createStripeCustomer(next, done) {
        next();

        var doc = this;

        // If the document is new, or the document doesn't have a stripe customer yet, create one.
        if(doc.isNew) {
            var customer = {
                metadata: {}
            };

            if(options.emailField) {
                customer.email = doc[options.emailField];
                customer.description = customer.email;
            }

            if(options.firstNameField && options.lastNameField) {
                var firstName = doc[options.firstNameField],
                    lastName = doc[options.lastNameField];
                customer.description = firstName + ' ' + lastName;
                customer.metadata[options.firstNameField] = firstName;
                customer.metadata[options.lastNameField] = lastName;
            }

            if(options.metaData instanceof Array && options.metaData.length) {
                options.metaData.forEach(function(key) {
                    if(doc[key]) {
                        customer.metadata[key] = (key === '_id') ? doc[key].toString() : doc[key];
                    }
                });
            }

            stripe.customers.create(customer)
                .then(function(customer) {
                    doc[options.stripeCustomerIdField] = customer.id;
                    done();
                }, done);

        // They already are a stripe customer, do nothing.
        } else {
            done();
        }
    });

};
<commit_msg>Allow embedded documents for path options<commit_after>var _ = require('lodash');
var util = require('util');

/**
 * @module mongoose-stripe-customers
 * @example
 ```js
var mongooseStripeCustomers = require('mongoose-stripe-customers');

var schema = Schema({...});

schema.plugin(mongooseStripeCustomers, {
    stripeApiKey: 'XXXXXXXXXXXXXXXX',
    hook: 'save',
    firstNameField: 'first_name',
    lastNameField: 'last_name',
    emailField: 'email',
    metaData: [ '_id', 'phone', 'customerType' ]
});
 ```
 */

module.exports = function stripeCustomersPlugin(schema, options) {
    /**
     * @param {object} options
     * @param {string} options.stripeApiKey - The Stripe secret key used to access the Stripe API.
     * @param {string} [options.hook=save] - The document hook you want this to run before.
     * @param {object} [options.fieldNames] - Response field overrides.
     * @param {string} [options.stripeCustomerIdField=stripe_customer_id] - The field in which you want the Stripe customer ID value to be stored.
     * @param {string} [options.firstNameField] - The field in which the customer's first name is stored.
     * @param {string} [options.lastNameField] - The field in which the customer's last name is stored.
     * @param {string} [options.emailField] - The field in which the customer's email address is stored.
     * @param {string[]} [options.metaData[]] - If you want any extra data stored with the customer on Stripe, provide an array of field names.
     */
    options = _.merge({
        hook: 'save',
        stripeCustomerIdField: 'stripe_customer_id'
    }, options || {});

    if(!options.stripeApiKey) {
        throw new Error('Stripe API key must be provided to mongoose-stripe-customers.');
    }

    var stripe = require('stripe')(options.stripeApiKey);

    // Add the stripe customer id path to the schema.
    if(!schema.path(options.stripeCustomerIdField)) {
        schema.path(options.stripeCustomerIdField, {
            type: String,
            unique: true,
            trim: true
        });
    }

    schema.pre(options.hook, true, function createStripeCustomer(next, done) {
        next();

        var doc = this;
        var customer = {
            metadata: {}
        };
        var firstName;
        var lastName;

        if(!doc.isNew) {
            // They already are a stripe customer, do nothing.
            return done();
        }

        // If the document is new, or the document doesn't have a stripe customer yet, create one.
        if(options.emailField) {
            customer.description = customer.email = doc.get(options.emailField]);
        }

        if(options.firstNameField && options.lastNameField) {
            firstName = doc.get(options.firstNameField);
            lastName = doc.get(options.lastNameField);

            customer.description = firstName + ' ' + lastName;
            _.set(customer.metadata, options.firstNameField, firstName);
            _.set(customer.metadata, options.lastNameField, lastName);
        }

        if(options.metaData instanceof Array && options.metaData.length) {
            options.metaData.forEach(function(key) {
                var val = doc.get(key);

                if(val) {
                    _.set(customer.metadata, key, (key === '_id') ? val.toString() : val);
                }
            });
        }

        stripe.customers.create(customer)
            .then(function(customer) {
                doc.set(options.stripeCustomerIdField, customer.id);
                done();
            }, done);
    });

};
<|endoftext|>


<commit_before>'use strict';

const config = require('../app/core/config.js');
const view = require('../app/lib/view.js');
const del = require('del');
const getPort = require('get-port');
const utils = require('./utils');
const tmpDirectory = utils.getTmpDirectory('views');

function getViews () {
	return view
		.getViews(config.nitro.base_path + config.nitro.view_directory)
		.map((view) => view.url);
}

module.exports = function (gulp, plugins) {
	return () => {
		return getPort()
			.then((port) => {
				const server = plugins.liveServer('server', {
					env: {
						PORT: port,
						NODE_ENV: 'production'
					}
				}, false);

				function dumpViews() {
					return del(tmpDirectory)
						.then(() => {
								return plugins.remoteSrc(getViews(), {
									base: `http://localhost:${port}/`,
									buffer: true
								})
									.pipe(plugins.rename({extname: '.html'}))
									.pipe(gulp.dest(tmpDirectory))
									.on('end', () => {
										server.stop();
									});
							}
						);
				}

				return server.start()
					.then(() => {},() => {}, () => dumpViews());
			});
	};
};
<commit_msg>Dump views in different languages<commit_after>'use strict';

const argv = require('yargs').argv;
const config = require('../app/core/config.js');
const view = require('../app/lib/view.js');
const del = require('del');
const getPort = require('get-port');
const utils = require('./utils');
const tmpDirectory = utils.getTmpDirectory('views');

function getViews () {
	return view
		.getViews(config.nitro.base_path + config.nitro.view_directory)
		.map((view) => view.url);
}

module.exports = function (gulp, plugins) {
	return () => {
		return getPort()
			.then((port) => {
				const server = plugins.liveServer('server', {
					env: {
						PORT: port,
						NODE_ENV: 'production'
					}
				}, false);

				function dumpViews() {
					return del(tmpDirectory)
						.then(() => {
								let views = getViews();
								const languages = (argv.locales === undefined) ? [] : argv.locales.split(',');

								if(languages.length) {
									const viewsAmount = views.length;
									languages.filter(lng => lng !== 'default').map(lng => {
										views = views.concat(views.map(v => v += `?lang=${lng}`));
									});
									if(!languages.includes('default')) {
										views.splice(0, viewsAmount);
									}
								}

								return plugins.remoteSrc(views, {
									base: `http://localhost:${port}/`,
									buffer: true
								})
									.pipe(plugins.rename(function (path) {
										const lang = path.basename.match(/\?lang=([a-z]+)/);
										path.extname = '.html';
										if(lang) {
											path.basename = path.basename.replace(/\?lang=[a-z]+/, '')
											path.basename += `-${lang[1]}`;
										}
									}))
									.pipe(gulp.dest(tmpDirectory))
									.on('end', () => {
										server.stop();
									});
							}
						);
				}

				return server.start()
					.then(() => {},() => {}, () => dumpViews());
			});
	};
};
<|endoftext|>


<commit_before>/*
    ***** BEGIN LICENSE BLOCK *****

    Copyright © 2009 Center for History and New Media
                     George Mason University, Fairfax, Virginia, USA
                     http://zotero.org

    This file is part of Zotero.

    Zotero is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Zotero is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with Zotero.  If not, see <http://www.gnu.org/licenses/>.

    ***** END LICENSE BLOCK *****
*/

Zotero.ItemFields = new function() {
	// Private members
	var _fields = {};
	var _fieldsFormats = [];
	var _fieldsLoaded;
	var _fieldFormats = [];
	var _itemTypeFields = [];
	var _baseTypeFields = [];
	var _typeFieldIDsByBase = {};
	var _typeFieldNamesByBase = {};

	var self = this;

	// Privileged methods
	this.getName = getName;
	this.getID = getID;
	this.getLocalizedString = getLocalizedString;
	this.isValidForType = isValidForType;
	this.isInteger = isInteger;
	this.getItemTypeFields = getItemTypeFields;
	this.isBaseField = isBaseField;
	this.isFieldOfBase = isFieldOfBase;
	this.getBaseMappedFields = getBaseMappedFields;
	this.getFieldIDFromTypeAndBase = getFieldIDFromTypeAndBase;
	this.getBaseIDFromTypeAndField = getBaseIDFromTypeAndField;
	this.getTypeFieldsFromBase = getTypeFieldsFromBase;

	/*
	 * Return the fieldID for a passed fieldID or fieldName
	 */
	function getID(field) {
		if (!_fieldsLoaded) {
			_loadFields();
		}

		if (typeof field == 'number') {
			return field;
		}

		return _fields[field] ? _fields[field]['id'] : false;
	}

	/*
	 * Return the fieldName for a passed fieldID or fieldName
	 */
	function getName(field) {
		if (!_fieldsLoaded) {
			_loadFields();
		}

		return _fields[field] ? _fields[field]['name'] : false;
	}

	function getLocalizedString(itemType, field) {
		// unused currently
		//var typeName = Zotero.ItemTypes.getName(itemType);
		var fieldName = Zotero.ItemFields.getName(field);

		// Fields in the items table are special cases
		switch (field) {
			case 'dateAdded':
			case 'dateModified':
			case 'itemType':
				return Zotero.getString("itemFields." + field);
		}

		// TODO: different labels for different item types

		try {
			_fieldCheck(field, 'getLocalizedString');
		}
		// TEMP
		catch (e) {
			try {
				asfasfa();
			}
			catch (e2) {
				Zotero.debug(e2);
			}
			Zotero.debug(e);
			throw (e);
		}

		if (_fields[field].label) {
			return _fields[field].label;
		}
		else {
			try {
				var loc = Zotero.getString("itemFields." + fieldName);
			}
			// If localized string not found, try base field
			catch (e) {
				Zotero.debug("Localized string not found for field '" + fieldName + "' -- trying base field");
				var baseFieldID = this.getBaseIDFromTypeAndField(itemType, field);
				fieldName = this.getName(baseFieldID);
				var loc = Zotero.getString("itemFields." + fieldName);
			}
			return loc;
		}
	}

	function isValidForType(fieldID, itemTypeID) {
		fieldID = getID(fieldID);
		if (!fieldID) return false;

		if (!_fields[fieldID]['itemTypes']) {
			return false;
		}

		return !!_fields[fieldID]['itemTypes'][itemTypeID];
	}

	function isInteger(fieldID) {
		_fieldCheck(fieldID, 'isInteger');

		var ffid = _fields[fieldID]['formatID'];
		return _fieldFormats[ffid] ? _fieldFormats[ffid]['isInteger'] : false;
	}

	this.isMultiline = function (fieldID) {
		_fieldCheck(fieldID, 'isMultiline');

		// TEMP: extra and abstractNote
		return 22 || 90;
	}

	this.isCustom = function (fieldID) {
		_fieldCheck(fieldID, 'isCustom');

		return _fields[fieldID].custom;
	}

	/*
	 * Returns an array of fieldIDs for a given item type
	 */
	function getItemTypeFields(itemTypeID) {
		if (!_fieldsLoaded) {
			_loadFields();
		}

		if (_itemTypeFields[itemTypeID]) {
			return _itemTypeFields[itemTypeID];
		}

		if (!itemTypeID) {
			throw("Invalid item type id '" + itemTypeID
				+ "' provided to getItemTypeFields()");
		}

		var sql = 'SELECT fieldID FROM itemTypeFieldsCombined '
			+ 'WHERE itemTypeID=' + itemTypeID + ' ORDER BY orderIndex';
		var fields = Zotero.DB.columnQuery(sql);

		_itemTypeFields[itemTypeID] = fields ? fields : [];
		return _itemTypeFields[itemTypeID];
	}

	function isBaseField(field) {
		_fieldCheck(field, arguments.callee.name);

		return _fields[field]['isBaseField'];
	}

	function isFieldOfBase(field, baseField) {
		var fieldID = _fieldCheck(field, 'isFieldOfBase');

		var baseFieldID = this.getID(baseField);
		if (!baseFieldID) {
			throw ("Invalid field '" + baseField + '" for base field in ItemFields.getFieldIDFromTypeAndBase()');
		}

		if (fieldID == baseFieldID) {
			return true;
		}

		var typeFields = this.getTypeFieldsFromBase(baseFieldID);
		return typeFields.indexOf(fieldID) != -1;
	}

	function getBaseMappedFields() {
		return Zotero.DB.columnQuery("SELECT DISTINCT fieldID FROM baseFieldMappingsCombined");
	}

	/*
	 * Returns the fieldID of a type-specific field for a given base field
	 * 		or false if none
	 *
	 * Examples:
	 *
	 * 'audioRecording' and 'publisher' returns label's fieldID
	 * 'book' and 'publisher' returns publisher's fieldID
	 * 'audioRecording' and 'number' returns false
	 *
	 * Accepts names or ids
	 */
	function getFieldIDFromTypeAndBase(itemType, baseField) {
		var itemTypeID = Zotero.ItemTypes.getID(itemType);
		if (!itemTypeID) {
			throw new Error("Invalid item type '" + itemType + "' in ItemFields.getFieldIDFromTypeAndBase()");
		}

		var baseFieldID = this.getID(baseField);
		if (!baseFieldID) {
			throw new Error("Invalid field '" + baseField + '" for base field in ItemFields.getFieldIDFromTypeAndBase()');
		}

		return _baseTypeFields[itemTypeID][baseFieldID];
	}

	/*
	 * Returns the fieldID of the base field for a given type-specific field
	 * 		or false if none
	 *
	 * Examples:
	 *
	 * 'audioRecording' and 'label' returns publisher's fieldID
	 * 'book' and 'publisher' returns publisher's fieldID
	 * 'audioRecording' and 'runningTime' returns false
	 *
	 * Accepts names or ids
	 */
	function getBaseIDFromTypeAndField(itemType, typeField) {
		var itemTypeID = Zotero.ItemTypes.getID(itemType);
		var typeFieldID = this.getID(typeField);

		if (!itemTypeID) {
			throw ("Invalid item type '" + itemType + "' in ItemFields.getBaseIDFromTypeAndField()");
		}

		_fieldCheck(typeField, 'getBaseIDFromTypeAndField');

		if (!this.isValidForType(typeFieldID, itemTypeID)) {
			throw ("'" + typeField + "' is not a valid field for '" + itemType + "' in ItemFields.getBaseIDFromTypeAndField()");
		}

		// If typeField is already a base field, just return that
		if (this.isBaseField(typeFieldID)) {
			return typeFieldID;
		}

		return Zotero.DB.valueQuery("SELECT baseFieldID FROM baseFieldMappingsCombined "
			+ "WHERE itemTypeID=? AND fieldID=?", [itemTypeID, typeFieldID]);
	}

	/*
	 * Returns an array of fieldIDs associated with a given base field
	 *
	 * e.g. 'publisher' returns fieldIDs for [university, studio, label, network]
	 */
	function getTypeFieldsFromBase(baseField, asNames) {
		var baseFieldID = this.getID(baseField);
		if (!baseFieldID) {
			throw ("Invalid base field '" + baseField + '" in ItemFields.getTypeFieldsFromBase()');
		}

		if (asNames) {
			return _typeFieldNamesByBase[baseFieldID] ?
				_typeFieldNamesByBase[baseFieldID] : false;
		}

		return _typeFieldIDsByBase[baseFieldID] ?
			_typeFieldIDsByBase[baseFieldID] : false;
	}

	this.isAutocompleteField = function (field) {
		field = this.getName(field);

		var autoCompleteFields = [
			'journalAbbreviation',
			'series',
			'seriesTitle',
			'seriesText',
			'libraryCatalog',
			'callNumber',
			'archive',
			'archiveLocation',
			'language',
			'programmingLanguage',
			'rights',

			// TEMP - NSF
			'programDirector',
			'institution',
			'discipline'
		];

		// Add the type-specific versions of these base fields
		var baseACFields = ['publisher', 'publicationTitle', 'type', 'medium', 'place'];
		autoCompleteFields = autoCompleteFields.concat(baseACFields);

		for (var i=0; i<baseACFields.length; i++) {
			var add = Zotero.ItemFields.getTypeFieldsFromBase(baseACFields[i], true)
			autoCompleteFields = autoCompleteFields.concat(add);
		}

		return autoCompleteFields.indexOf(field) != -1;
	}

	/**
	 * A long field expands into a multiline textbox while editing but displays
	 * as a single line in non-editing mode; newlines are not allowed
	 */
	this.isLong = function (field) {
		field = this.getName(field);
		var fields = [
			'title'
		];
		return fields.indexOf(field) != -1;
	}

	/**
	 * A multiline field displays as a multiline text box in editing mode
	 * and non-editing mode; newlines are allowed
	 */
	this.isMultiline = function (field) {
		field = this.getName(field);
		var fields = [
			'abstractNote',
			'extra',

			// TEMP - NSF
			'address'
		];
		return fields.indexOf(field) != -1;
	}

	this.reload = function () {
		_fieldsLoaded = false;
	}

	/**
	* Check whether a field is valid, throwing an exception if not
	* (since it should never actually happen)
	**/
	function _fieldCheck(field, func) {
		var fieldID = self.getID(field);
		if (!fieldID) {
			Zotero.debug((new Error).stack, 1);
			throw new Error("Invalid field '" + field + (func ? "' in ItemFields." + func + "()" : "'"));
		}
		return fieldID;
	}

	/*
	 * Returns hash array of itemTypeIDs for which a given field is valid
	 */
	function _getFieldItemTypes() {
		var sql = 'SELECT fieldID, itemTypeID FROM itemTypeFieldsCombined';

		var results = Zotero.DB.query(sql);

		if (!results) {
			throw ('No fields in itemTypeFields!');
		}
		var fields = new Array();
		for (var i=0; i<results.length; i++) {
			if (!fields[results[i]['fieldID']]) {
				fields[results[i]['fieldID']] = new Array();
			}
			fields[results[i]['fieldID']][results[i]['itemTypeID']] = true;
		}
		return fields;
	}

	/*
	 * Build a lookup table for base field mappings
	 */
	function _loadBaseTypeFields() {
		_typeFieldIDsByBase = {};
		_typeFieldNamesByBase = {};

		// Grab all fields, base field or not
		var sql = "SELECT IT.itemTypeID, F.fieldID AS baseFieldID, BFM.fieldID "
			+ "FROM itemTypesCombined IT LEFT JOIN fieldsCombined F "
			+ "LEFT JOIN baseFieldMappingsCombined BFM"
			+ " ON (IT.itemTypeID=BFM.itemTypeID AND F.fieldID=BFM.baseFieldID)";
		var rows = Zotero.DB.query(sql);

		var sql = "SELECT DISTINCT baseFieldID FROM baseFieldMappingsCombined";
		var baseFields = Zotero.DB.columnQuery(sql);

		var fields = [];
		for each(var row in rows) {
			if (!fields[row.itemTypeID]) {
				fields[row.itemTypeID] = [];
			}
			if (row.fieldID) {
				fields[row.itemTypeID][row.baseFieldID] = row.fieldID;
			}
			// If a base field and already valid for the type, just use that
			else if (isBaseField(row.baseFieldID) &&
					isValidForType(row.baseFieldID, row.itemTypeID)) {
				fields[row.itemTypeID][row.baseFieldID] = row.baseFieldID;
			}
			// Set false for other fields so that we don't need to test for
			// existence
			else {
				fields[row.itemTypeID][row.baseFieldID] = false;
			}
		}

		_baseTypeFields = fields;

		var sql = "SELECT baseFieldID, fieldID, fieldName "
			+ "FROM baseFieldMappingsCombined JOIN fieldsCombined USING (fieldID)";
		var rows = Zotero.DB.query(sql);
		for each(var row in rows) {
			if (!_typeFieldIDsByBase[row['baseFieldID']]) {
				_typeFieldIDsByBase[row['baseFieldID']] = [];
				_typeFieldNamesByBase[row['baseFieldID']] = [];
			}
			_typeFieldIDsByBase[row['baseFieldID']].push(row['fieldID']);
			_typeFieldNamesByBase[row['baseFieldID']].push(row['fieldName']);
		}
	}

	/*
	 * Load all fields into an internal hash array
	 */
	function _loadFields() {
		_fields = {};
		_fieldsFormats = [];
		_itemTypeFields = [];

		var result = Zotero.DB.query('SELECT * FROM fieldFormats');

		for (var i=0; i<result.length; i++) {
			_fieldFormats[result[i]['fieldFormatID']] = {
				regex: result[i]['regex'],
				isInteger: result[i]['isInteger']
			};
		}

		var fields = Zotero.DB.query('SELECT * FROM fieldsCombined');

		var fieldItemTypes = _getFieldItemTypes();

		var sql = "SELECT DISTINCT baseFieldID FROM baseFieldMappingsCombined";
		var baseFields = Zotero.DB.columnQuery(sql);

		for each(var field in fields) {
			_fields[field['fieldID']] = {
				id: field['fieldID'],
				name: field.fieldName,
				label: field.label,
				custom: !!field.custom,
				isBaseField: (baseFields.indexOf(field['fieldID']) != -1),
				formatID: field['fieldFormatID'],
				itemTypes: fieldItemTypes[field['fieldID']]
			};
			// Store by name as well as id
			_fields[field['fieldName']] = _fields[field['fieldID']];
		}

		_fieldsLoaded = true;

		_loadBaseTypeFields();
	}
}

<commit_msg>Fixes #890, Use text area for Book Title<commit_after>/*
    ***** BEGIN LICENSE BLOCK *****

    Copyright © 2009 Center for History and New Media
                     George Mason University, Fairfax, Virginia, USA
                     http://zotero.org

    This file is part of Zotero.

    Zotero is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Zotero is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with Zotero.  If not, see <http://www.gnu.org/licenses/>.

    ***** END LICENSE BLOCK *****
*/

Zotero.ItemFields = new function() {
	// Private members
	var _fields = {};
	var _fieldsFormats = [];
	var _fieldsLoaded;
	var _fieldFormats = [];
	var _itemTypeFields = [];
	var _baseTypeFields = [];
	var _typeFieldIDsByBase = {};
	var _typeFieldNamesByBase = {};

	var self = this;

	// Privileged methods
	this.getName = getName;
	this.getID = getID;
	this.getLocalizedString = getLocalizedString;
	this.isValidForType = isValidForType;
	this.isInteger = isInteger;
	this.getItemTypeFields = getItemTypeFields;
	this.isBaseField = isBaseField;
	this.isFieldOfBase = isFieldOfBase;
	this.getBaseMappedFields = getBaseMappedFields;
	this.getFieldIDFromTypeAndBase = getFieldIDFromTypeAndBase;
	this.getBaseIDFromTypeAndField = getBaseIDFromTypeAndField;
	this.getTypeFieldsFromBase = getTypeFieldsFromBase;

	/*
	 * Return the fieldID for a passed fieldID or fieldName
	 */
	function getID(field) {
		if (!_fieldsLoaded) {
			_loadFields();
		}

		if (typeof field == 'number') {
			return field;
		}

		return _fields[field] ? _fields[field]['id'] : false;
	}

	/*
	 * Return the fieldName for a passed fieldID or fieldName
	 */
	function getName(field) {
		if (!_fieldsLoaded) {
			_loadFields();
		}

		return _fields[field] ? _fields[field]['name'] : false;
	}

	function getLocalizedString(itemType, field) {
		// unused currently
		//var typeName = Zotero.ItemTypes.getName(itemType);
		var fieldName = Zotero.ItemFields.getName(field);

		// Fields in the items table are special cases
		switch (field) {
			case 'dateAdded':
			case 'dateModified':
			case 'itemType':
				return Zotero.getString("itemFields." + field);
		}

		// TODO: different labels for different item types

		try {
			_fieldCheck(field, 'getLocalizedString');
		}
		// TEMP
		catch (e) {
			try {
				asfasfa();
			}
			catch (e2) {
				Zotero.debug(e2);
			}
			Zotero.debug(e);
			throw (e);
		}

		if (_fields[field].label) {
			return _fields[field].label;
		}
		else {
			try {
				var loc = Zotero.getString("itemFields." + fieldName);
			}
			// If localized string not found, try base field
			catch (e) {
				Zotero.debug("Localized string not found for field '" + fieldName + "' -- trying base field");
				var baseFieldID = this.getBaseIDFromTypeAndField(itemType, field);
				fieldName = this.getName(baseFieldID);
				var loc = Zotero.getString("itemFields." + fieldName);
			}
			return loc;
		}
	}

	function isValidForType(fieldID, itemTypeID) {
		fieldID = getID(fieldID);
		if (!fieldID) return false;

		if (!_fields[fieldID]['itemTypes']) {
			return false;
		}

		return !!_fields[fieldID]['itemTypes'][itemTypeID];
	}

	function isInteger(fieldID) {
		_fieldCheck(fieldID, 'isInteger');

		var ffid = _fields[fieldID]['formatID'];
		return _fieldFormats[ffid] ? _fieldFormats[ffid]['isInteger'] : false;
	}

	this.isMultiline = function (fieldID) {
		_fieldCheck(fieldID, 'isMultiline');

		// TEMP: extra and abstractNote
		return 22 || 90;
	}

	this.isCustom = function (fieldID) {
		_fieldCheck(fieldID, 'isCustom');

		return _fields[fieldID].custom;
	}

	/*
	 * Returns an array of fieldIDs for a given item type
	 */
	function getItemTypeFields(itemTypeID) {
		if (!_fieldsLoaded) {
			_loadFields();
		}

		if (_itemTypeFields[itemTypeID]) {
			return _itemTypeFields[itemTypeID];
		}

		if (!itemTypeID) {
			throw("Invalid item type id '" + itemTypeID
				+ "' provided to getItemTypeFields()");
		}

		var sql = 'SELECT fieldID FROM itemTypeFieldsCombined '
			+ 'WHERE itemTypeID=' + itemTypeID + ' ORDER BY orderIndex';
		var fields = Zotero.DB.columnQuery(sql);

		_itemTypeFields[itemTypeID] = fields ? fields : [];
		return _itemTypeFields[itemTypeID];
	}

	function isBaseField(field) {
		_fieldCheck(field, arguments.callee.name);

		return _fields[field]['isBaseField'];
	}

	function isFieldOfBase(field, baseField) {
		var fieldID = _fieldCheck(field, 'isFieldOfBase');

		var baseFieldID = this.getID(baseField);
		if (!baseFieldID) {
			throw ("Invalid field '" + baseField + '" for base field in ItemFields.getFieldIDFromTypeAndBase()');
		}

		if (fieldID == baseFieldID) {
			return true;
		}

		var typeFields = this.getTypeFieldsFromBase(baseFieldID);
		return typeFields.indexOf(fieldID) != -1;
	}

	function getBaseMappedFields() {
		return Zotero.DB.columnQuery("SELECT DISTINCT fieldID FROM baseFieldMappingsCombined");
	}

	/*
	 * Returns the fieldID of a type-specific field for a given base field
	 * 		or false if none
	 *
	 * Examples:
	 *
	 * 'audioRecording' and 'publisher' returns label's fieldID
	 * 'book' and 'publisher' returns publisher's fieldID
	 * 'audioRecording' and 'number' returns false
	 *
	 * Accepts names or ids
	 */
	function getFieldIDFromTypeAndBase(itemType, baseField) {
		var itemTypeID = Zotero.ItemTypes.getID(itemType);
		if (!itemTypeID) {
			throw new Error("Invalid item type '" + itemType + "' in ItemFields.getFieldIDFromTypeAndBase()");
		}

		var baseFieldID = this.getID(baseField);
		if (!baseFieldID) {
			throw new Error("Invalid field '" + baseField + '" for base field in ItemFields.getFieldIDFromTypeAndBase()');
		}

		return _baseTypeFields[itemTypeID][baseFieldID];
	}

	/*
	 * Returns the fieldID of the base field for a given type-specific field
	 * 		or false if none
	 *
	 * Examples:
	 *
	 * 'audioRecording' and 'label' returns publisher's fieldID
	 * 'book' and 'publisher' returns publisher's fieldID
	 * 'audioRecording' and 'runningTime' returns false
	 *
	 * Accepts names or ids
	 */
	function getBaseIDFromTypeAndField(itemType, typeField) {
		var itemTypeID = Zotero.ItemTypes.getID(itemType);
		var typeFieldID = this.getID(typeField);

		if (!itemTypeID) {
			throw ("Invalid item type '" + itemType + "' in ItemFields.getBaseIDFromTypeAndField()");
		}

		_fieldCheck(typeField, 'getBaseIDFromTypeAndField');

		if (!this.isValidForType(typeFieldID, itemTypeID)) {
			throw ("'" + typeField + "' is not a valid field for '" + itemType + "' in ItemFields.getBaseIDFromTypeAndField()");
		}

		// If typeField is already a base field, just return that
		if (this.isBaseField(typeFieldID)) {
			return typeFieldID;
		}

		return Zotero.DB.valueQuery("SELECT baseFieldID FROM baseFieldMappingsCombined "
			+ "WHERE itemTypeID=? AND fieldID=?", [itemTypeID, typeFieldID]);
	}

	/*
	 * Returns an array of fieldIDs associated with a given base field
	 *
	 * e.g. 'publisher' returns fieldIDs for [university, studio, label, network]
	 */
	function getTypeFieldsFromBase(baseField, asNames) {
		var baseFieldID = this.getID(baseField);
		if (!baseFieldID) {
			throw ("Invalid base field '" + baseField + '" in ItemFields.getTypeFieldsFromBase()');
		}

		if (asNames) {
			return _typeFieldNamesByBase[baseFieldID] ?
				_typeFieldNamesByBase[baseFieldID] : false;
		}

		return _typeFieldIDsByBase[baseFieldID] ?
			_typeFieldIDsByBase[baseFieldID] : false;
	}

	this.isAutocompleteField = function (field) {
		field = this.getName(field);

		var autoCompleteFields = [
			'journalAbbreviation',
			'series',
			'seriesTitle',
			'seriesText',
			'libraryCatalog',
			'callNumber',
			'archive',
			'archiveLocation',
			'language',
			'programmingLanguage',
			'rights',

			// TEMP - NSF
			'programDirector',
			'institution',
			'discipline'
		];

		// Add the type-specific versions of these base fields
		var baseACFields = ['publisher', 'publicationTitle', 'type', 'medium', 'place'];
		autoCompleteFields = autoCompleteFields.concat(baseACFields);

		for (var i=0; i<baseACFields.length; i++) {
			var add = Zotero.ItemFields.getTypeFieldsFromBase(baseACFields[i], true)
			autoCompleteFields = autoCompleteFields.concat(add);
		}

		return autoCompleteFields.indexOf(field) != -1;
	}

	/**
	 * A long field expands into a multiline textbox while editing but displays
	 * as a single line in non-editing mode; newlines are not allowed
	 */
	this.isLong = function (field) {
		field = this.getName(field);
		var fields = [
			'title',
			'bookTitle'
		];
		return fields.indexOf(field) != -1;
	}

	/**
	 * A multiline field displays as a multiline text box in editing mode
	 * and non-editing mode; newlines are allowed
	 */
	this.isMultiline = function (field) {
		field = this.getName(field);
		var fields = [
			'abstractNote',
			'extra',

			// TEMP - NSF
			'address'
		];
		return fields.indexOf(field) != -1;
	}

	this.reload = function () {
		_fieldsLoaded = false;
	}

	/**
	* Check whether a field is valid, throwing an exception if not
	* (since it should never actually happen)
	**/
	function _fieldCheck(field, func) {
		var fieldID = self.getID(field);
		if (!fieldID) {
			Zotero.debug((new Error).stack, 1);
			throw new Error("Invalid field '" + field + (func ? "' in ItemFields." + func + "()" : "'"));
		}
		return fieldID;
	}

	/*
	 * Returns hash array of itemTypeIDs for which a given field is valid
	 */
	function _getFieldItemTypes() {
		var sql = 'SELECT fieldID, itemTypeID FROM itemTypeFieldsCombined';

		var results = Zotero.DB.query(sql);

		if (!results) {
			throw ('No fields in itemTypeFields!');
		}
		var fields = new Array();
		for (var i=0; i<results.length; i++) {
			if (!fields[results[i]['fieldID']]) {
				fields[results[i]['fieldID']] = new Array();
			}
			fields[results[i]['fieldID']][results[i]['itemTypeID']] = true;
		}
		return fields;
	}

	/*
	 * Build a lookup table for base field mappings
	 */
	function _loadBaseTypeFields() {
		_typeFieldIDsByBase = {};
		_typeFieldNamesByBase = {};

		// Grab all fields, base field or not
		var sql = "SELECT IT.itemTypeID, F.fieldID AS baseFieldID, BFM.fieldID "
			+ "FROM itemTypesCombined IT LEFT JOIN fieldsCombined F "
			+ "LEFT JOIN baseFieldMappingsCombined BFM"
			+ " ON (IT.itemTypeID=BFM.itemTypeID AND F.fieldID=BFM.baseFieldID)";
		var rows = Zotero.DB.query(sql);

		var sql = "SELECT DISTINCT baseFieldID FROM baseFieldMappingsCombined";
		var baseFields = Zotero.DB.columnQuery(sql);

		var fields = [];
		for each(var row in rows) {
			if (!fields[row.itemTypeID]) {
				fields[row.itemTypeID] = [];
			}
			if (row.fieldID) {
				fields[row.itemTypeID][row.baseFieldID] = row.fieldID;
			}
			// If a base field and already valid for the type, just use that
			else if (isBaseField(row.baseFieldID) &&
					isValidForType(row.baseFieldID, row.itemTypeID)) {
				fields[row.itemTypeID][row.baseFieldID] = row.baseFieldID;
			}
			// Set false for other fields so that we don't need to test for
			// existence
			else {
				fields[row.itemTypeID][row.baseFieldID] = false;
			}
		}

		_baseTypeFields = fields;

		var sql = "SELECT baseFieldID, fieldID, fieldName "
			+ "FROM baseFieldMappingsCombined JOIN fieldsCombined USING (fieldID)";
		var rows = Zotero.DB.query(sql);
		for each(var row in rows) {
			if (!_typeFieldIDsByBase[row['baseFieldID']]) {
				_typeFieldIDsByBase[row['baseFieldID']] = [];
				_typeFieldNamesByBase[row['baseFieldID']] = [];
			}
			_typeFieldIDsByBase[row['baseFieldID']].push(row['fieldID']);
			_typeFieldNamesByBase[row['baseFieldID']].push(row['fieldName']);
		}
	}

	/*
	 * Load all fields into an internal hash array
	 */
	function _loadFields() {
		_fields = {};
		_fieldsFormats = [];
		_itemTypeFields = [];

		var result = Zotero.DB.query('SELECT * FROM fieldFormats');

		for (var i=0; i<result.length; i++) {
			_fieldFormats[result[i]['fieldFormatID']] = {
				regex: result[i]['regex'],
				isInteger: result[i]['isInteger']
			};
		}

		var fields = Zotero.DB.query('SELECT * FROM fieldsCombined');

		var fieldItemTypes = _getFieldItemTypes();

		var sql = "SELECT DISTINCT baseFieldID FROM baseFieldMappingsCombined";
		var baseFields = Zotero.DB.columnQuery(sql);

		for each(var field in fields) {
			_fields[field['fieldID']] = {
				id: field['fieldID'],
				name: field.fieldName,
				label: field.label,
				custom: !!field.custom,
				isBaseField: (baseFields.indexOf(field['fieldID']) != -1),
				formatID: field['fieldFormatID'],
				itemTypes: fieldItemTypes[field['fieldID']]
			};
			// Store by name as well as id
			_fields[field['fieldName']] = _fields[field['fieldID']];
		}

		_fieldsLoaded = true;

		_loadBaseTypeFields();
	}
}

<|endoftext|>


<commit_before>'use strict';

$(document).ready(function () {
    var responsiveHelper = undefined;
    var breakpointDefinition = {
        tablet: 1024,
        phone : 480
    };
    var tableContainer;
    var destroyingDataTable = false;

    // Initialize buttons
    $('button').click(function (event) {
        var ajaxUrl = $(this).attr('data-ajax-url');
        createDataTable(ajaxUrl);
    });

    /**
     * Create the data table.
     * @param {String} ajaxUrl
     */
    function createDataTable(ajaxUrl) {
        tableContainer = $('#example');

        // If a data table already exists, disable the responsive helper.
        if ($.fn.DataTable.fnIsDataTable(tableContainer[0])) {
            // Set the destroying flag to prevent the responsive table from
            // being initialized during this phase.
            destroyingDataTable = true;

            // Get data table instance
            tableContainer.dataTable();

            // Since we are destroying the table, let's clear it to speed things
            // up.
            tableContainer.fnClearTable(false);

            // Disabling the helper will reset the the responsive changes to the
            // DOM.
            responsiveHelper.disable(true);

            // Remove the responsive helper.
            responsiveHelper = undefined;

            // Now that all things have been restored, let's destroy the table
            tableContainer.fnDestroy();

            // Clear flag
            destroyingDataTable = false;
        }

        // Create data table
        tableContainer.dataTable({
            sDom             : '<"row"<"span6"l><"span6"f>r>t<"row"<"span6"i><"span6"p>>',
            sPaginationType  : 'bootstrap',
            oLanguage        : {
                sLengthMenu: '_MENU_ records per page'
            },
            // disable sorting on the checkbox column
            aoColumnDefs     : [
                {
                    aTargets : [ 0 ],             // Column number which needs to be modified
                    bSortable: false,             // Column is not sortable
                    // Custom render function - add checkbox
                    mRender  : function (data, type) {
                        return '<input type="checkbox" name="id" value="' + data + '" class="checkbox"/>';
                    },
                    sClass   : 'centered-cell'    // Optional - class to be applied to this table cell
                },
                {
                    aTargets: [ 4 ],              // Column number which needs to be modified
                    sClass  : 'centered-cell'     // Optional - class to be applied to this table cell
                },
                {
                    aTargets: [ 5 ],              // Column number which needs to be modified
                    sClass  : 'centered-cell'     // Optional - class to be applied to this table cell
                }
            ],
            bProcessing      : true,
            bAutoWidth       : false,
            sAjaxSource      : ajaxUrl,
            bDestroy         : true,
            // Custom call back for AJAX
            fnServerData     : function (sSource, aoData, fnCallback, oSettings) {
                oSettings.jqXHR = $.ajax({
                    dataType: 'json',
                    type    : 'GET',
                    url     : sSource,
                    data    : aoData,
                    success : function (data) {
                        fnCallback(data);
                    }
                });
            },
            fnPreDrawCallback: function () {
                // Initialize the responsive data table helper once.
                if (!responsiveHelper && !destroyingDataTable) {
                    responsiveHelper = new ResponsiveDatatablesHelper(tableContainer, breakpointDefinition);
                }
            },
            fnRowCallback    : function (nRow) {
                if (responsiveHelper) {
                    responsiveHelper.createExpandIcon(nRow);
                }
            },
            fnDrawCallback   : function () {
                // This function will be called every the table redraws.
                // Specifically, we're interested when next/previous page
                // occurs.
                toggleMasterCheckBasedOnAllOtherCheckboxes();

                // Respond to windows resize.
                if (responsiveHelper) {
                    responsiveHelper.respond();
                }
            },
            fnInitComplete   : function () {
                initializeMasterCheckboxEventHandlers();
                initializeCheckboxEventHandlers();
                initializeTableRowEventHandlers();
                responsiveHelper.disable();
            }
        });
    }

    // NOTE: We did not add class="centered-cell" to the Engine version and CSS grade columns
    //       as in other examples.

    /**
     * Toggles the master checkbox if all checkboxes in the table that
     * are visible are checked.
     */
    function toggleMasterCheckBasedOnAllOtherCheckboxes() {
        // What we need to do here is check to see if every checkbox is checked.
        // If it is, the master checkbox in the header should be checked as well.
        var allCheckboxes = $('tbody input:checkbox', tableContainer);
        var totalCheckboxCount = allCheckboxes.length;
        if (totalCheckboxCount) {
            var checkedChecboxCount = allCheckboxes.filter(':checked').length;
            $('#masterCheck', tableContainer).prop('checked', totalCheckboxCount === checkedChecboxCount);
        }
    }

    /**
     * Initialize master checkbox event handlers.
     */
    function initializeMasterCheckboxEventHandlers() {
        // Enable master checkbox to check/uncheck all checkboxes
        $('#masterCheck', tableContainer).click(function () {
            // Toggle all checkboxes by triggering a click event on them.  The click
            // event will fire the changed event that we can handle.  Directly changing
            // the checked property like this
            //
            //    $('tbody input:checkbox', tableContainer).not(this).prop('checked', this.checked);
            //
            // toggles all checkboxes but does not trigger click events.  Because there's
            // no click event, there's no changed events on the checkboxes.  We need the
            // changed events so that we can keep track of the checked checkboxes.
            if (this.checked) {
                $('tbody input:checkbox:not(:checked)', tableContainer).not(this).trigger('click');
            } else {
                $('tbody input:checkbox:checked', tableContainer).not(this).trigger('click');
            }
        });
    }

    /**
     * Initialize checkbox event handlers.  elementCollection can
     * be one of the following:
     *     - jQuery collection of checkbox elements
     *     - jQuery selector
     *     - undefined
     *
     * If elementCollection is undefined, all checkboxes in DataTable
     * will be selected.
     *
     * @param {Object|String|undefined} elementCollection
     */
    function initializeCheckboxEventHandlers(elementCollection) {
        if (elementCollection === undefined) {
            elementCollection = $('input:checkbox', tableContainer.fnGetNodes())
        } else if (elementCollection === 'string') {
            elementCollection = $(elementCollection, tableContainer.fnGetNodes())
        }

        elementCollection.off('change').change(function (event) {
            // Keep track of the checked checkboxes.
            if (event.target.checked) {
                // Do something with the checked item
                // callSomeFunction(event.target.name, event.target.value);
            } else {
                // Do something with the unchecked item
                // callSomeFunction(event.target.name, event.target.value);
            }

            // Affect the other parts of the table/page...
            toggleMasterCheckBasedOnAllOtherCheckboxes();
        });
    }

    /**
     * Initialize table row event handler.  elementCollection can
     * be one of the following:
     *     - jQuery collection of checkbox elements
     *     - jQuery selector
     *     - undefined
     *
     * If elementCollection is undefined, all table rows in DataTable
     * will be selected.
     *
     * @param {Object|String|undefined} elementCollection
     */
    function initializeTableRowEventHandlers(elementCollection) {
        if (elementCollection === undefined) {
            elementCollection = $(tableContainer.fnGetNodes())
        } else if (elementCollection === 'string') {
            elementCollection = $(elementCollection, tableContainer.fnGetNodes())
        }

        // Do something with elementCollection as needed.
    }
});
<commit_msg>Renamed tableContainer to tableElement and improved comments.<commit_after>'use strict';

$(document).ready(function () {
    var responsiveHelper = undefined;
    var breakpointDefinition = {
        tablet: 1024,
        phone : 480
    };

    var tableElement;
    var destroyingDataTable = false;

    // Initialize buttons
    $('button').click(function (event) {
        var ajaxUrl = $(this).attr('data-ajax-url');
        createDataTable(ajaxUrl);
    });

    /**
     * Create the data table.
     * @param {String} ajaxUrl
     */
    function createDataTable(ajaxUrl) {
        tableElement = $('#example');

        // This next part helps to clean things up so we can recreate a data
        // table on the same table element.
        if ($.fn.DataTable.fnIsDataTable(tableElement[0])) {
            // Set the destroying flag to prevent the responsive table from
            // being initialized during this phase.
            destroyingDataTable = true;

            // Get data table instance
            tableElement.dataTable();

            // Since we are destroying the table, let's clear it to speed things
            // up.
            tableElement.fnClearTable(false);

            // Disabling the helper will reset the the responsive changes to the
            // DOM.
            responsiveHelper.disable(true);

            // Remove the responsive helper.
            responsiveHelper = undefined;

            // Now that all things have been restored, let's destroy the table
            tableElement.fnDestroy();

            // Clear flag
            destroyingDataTable = false;
        }

        // Create data table
        tableElement.dataTable({
            sDom             : '<"row"<"span6"l><"span6"f>r>t<"row"<"span6"i><"span6"p>>',
            sPaginationType  : 'bootstrap',
            oLanguage        : {
                sLengthMenu: '_MENU_ records per page'
            },
            // disable sorting on the checkbox column
            aoColumnDefs     : [
                {
                    aTargets : [ 0 ],             // Column number which needs to be modified
                    bSortable: false,             // Column is not sortable
                    // Custom render function - add checkbox
                    mRender  : function (data, type) {
                        return '<input type="checkbox" name="id" value="' + data + '" class="checkbox"/>';
                    },
                    sClass   : 'centered-cell'    // Optional - class to be applied to this table cell
                },
                {
                    aTargets: [ 4 ],              // Column number which needs to be modified
                    sClass  : 'centered-cell'     // Optional - class to be applied to this table cell
                },
                {
                    aTargets: [ 5 ],              // Column number which needs to be modified
                    sClass  : 'centered-cell'     // Optional - class to be applied to this table cell
                }
            ],
            bProcessing      : true,
            bAutoWidth       : false,
            sAjaxSource      : ajaxUrl,
            bDestroy         : true,
            // Custom call back for AJAX
            fnServerData     : function (sSource, aoData, fnCallback, oSettings) {
                oSettings.jqXHR = $.ajax({
                    dataType: 'json',
                    type    : 'GET',
                    url     : sSource,
                    data    : aoData,
                    success : function (data) {
                        fnCallback(data);
                    }
                });
            },
            fnPreDrawCallback: function () {
                // Initialize the responsive data table helper once.
                if (!responsiveHelper && !destroyingDataTable) {
                    responsiveHelper = new ResponsiveDatatablesHelper(tableElement, breakpointDefinition);
                }
            },
            fnRowCallback    : function (nRow) {
                if (responsiveHelper) {
                    responsiveHelper.createExpandIcon(nRow);
                }
            },
            fnDrawCallback   : function () {
                // This function will be called every the table redraws.
                // Specifically, we're interested when next/previous page
                // occurs.
                toggleMasterCheckBasedOnAllOtherCheckboxes();

                // Respond to windows resize.
                if (responsiveHelper) {
                    responsiveHelper.respond();
                }
            },
            fnInitComplete   : function () {
                initializeMasterCheckboxEventHandlers();
                initializeCheckboxEventHandlers();
                initializeTableRowEventHandlers();
                responsiveHelper.disable();
            }
        });
    }

    // NOTE: We did not add class="centered-cell" to the Engine version and CSS grade columns
    //       as in other examples.

    /**
     * Toggles the master checkbox if all checkboxes in the table that
     * are visible are checked.
     */
    function toggleMasterCheckBasedOnAllOtherCheckboxes() {
        // What we need to do here is check to see if every checkbox is checked.
        // If it is, the master checkbox in the header should be checked as well.
        var allCheckboxes = $('tbody input:checkbox', tableElement);
        var totalCheckboxCount = allCheckboxes.length;
        if (totalCheckboxCount) {
            var checkedChecboxCount = allCheckboxes.filter(':checked').length;
            $('#masterCheck', tableElement).prop('checked', totalCheckboxCount === checkedChecboxCount);
        }
    }

    /**
     * Initialize master checkbox event handlers.
     */
    function initializeMasterCheckboxEventHandlers() {
        // Enable master checkbox to check/uncheck all checkboxes
        $('#masterCheck', tableElement).click(function () {
            // Toggle all checkboxes by triggering a click event on them.  The click
            // event will fire the changed event that we can handle.  Directly changing
            // the checked property like this
            //
            //    $('tbody input:checkbox', tableContainer).not(this).prop('checked', this.checked);
            //
            // toggles all checkboxes but does not trigger click events.  Because there's
            // no click event, there's no changed events on the checkboxes.  We need the
            // changed events so that we can keep track of the checked checkboxes.
            if (this.checked) {
                $('tbody input:checkbox:not(:checked)', tableElement).not(this).trigger('click');
            } else {
                $('tbody input:checkbox:checked', tableElement).not(this).trigger('click');
            }
        });
    }

    /**
     * Initialize checkbox event handlers.  elementCollection can
     * be one of the following:
     *     - jQuery collection of checkbox elements
     *     - jQuery selector
     *     - undefined
     *
     * If elementCollection is undefined, all checkboxes in DataTable
     * will be selected.
     *
     * @param {Object|String|undefined} elementCollection
     */
    function initializeCheckboxEventHandlers(elementCollection) {
        if (elementCollection === undefined) {
            elementCollection = $('input:checkbox', tableElement.fnGetNodes())
        } else if (elementCollection === 'string') {
            elementCollection = $(elementCollection, tableElement.fnGetNodes())
        }

        elementCollection.off('change').change(function (event) {
            // Keep track of the checked checkboxes.
            if (event.target.checked) {
                // Do something with the checked item
                // callSomeFunction(event.target.name, event.target.value);
            } else {
                // Do something with the unchecked item
                // callSomeFunction(event.target.name, event.target.value);
            }

            // Affect the other parts of the table/page...
            toggleMasterCheckBasedOnAllOtherCheckboxes();
        });
    }

    /**
     * Initialize table row event handler.  elementCollection can
     * be one of the following:
     *     - jQuery collection of checkbox elements
     *     - jQuery selector
     *     - undefined
     *
     * If elementCollection is undefined, all table rows in DataTable
     * will be selected.
     *
     * @param {Object|String|undefined} elementCollection
     */
    function initializeTableRowEventHandlers(elementCollection) {
        if (elementCollection === undefined) {
            elementCollection = $(tableElement.fnGetNodes())
        } else if (elementCollection === 'string') {
            elementCollection = $(elementCollection, tableElement.fnGetNodes())
        }

        // Do something with elementCollection as needed.
    }
});
<|endoftext|>


<commit_before>
function checkListFunction(){
    var sumValues = 0.0;

//What is the impact of not doing this project?
    if(document.getElementById("sel1").value === "Low"){
        x = 5;
    }
    else if(document.getElementById("sel1").value === "Medium"){
        x = 15;
    }
    else if(document.getElementById("sel1").value === "High"){
        x = 30;
    }
    sumValues += Number(x);

//What is the project risk to our organization?
    if(document.getElementById("sel2").value === "Low"){
        x = -5;
    }
    else if(document.getElementById("sel2").value === "Medium"){
        x = -15;
    }
    else if(document.getElementById("sel2").value === "High"){
        x = -30;
    }
    sumValues += Number(x);

//Does the proposed project fit in our risk profile?
    if(document.getElementById("sel3").value === "No"){
        x = -10;
    }
    else if(document.getElementById("sel3").value === "Yes"){
        x = 10;
    }
    sumValues += Number(x);

//What is the value of the project organization?
    if(document.getElementById("sel4").value === "Low"){
        x = 10;
    }
    else if(document.getElementById("sel4").value === "Medium"){
        x = 15;
    }
    else if(document.getElementById("sel4").value === "High"){
        x = 25;
    }
    sumValues += Number(x);

//Is our organization culture right for this type of project?
    if(document.getElementById("sel5").value === "No"){
        x = -5;
    }
    else if(document.getElementById("sel5").value === "Yes"){
        x = 10;
    }
    sumValues += Number(x);

//Will internal resources be available for this project?
    if(document.getElementById("sel6").value === "No"){
        x = -15;
    }
    else if(document.getElementById("sel6").value === "Yes"){
        x = 10;
    }
    sumValues += Number(x);

//Will we have to build or buy?
    if(document.getElementById("sel7").value === "Buy"){
        x = -15;
    }
    else if(document.getElementById("sel7").value === "Rent"){
        x = -5;
    }
    else if(document.getElementById("sel7").value === "Build"){
        x = -10;
    }
    else if(document.getElementById("sel7").value === "Nothing"){
        x = 20;
    }
    sumValues += Number(x);

//Is the timeline realistic?
    if(document.getElementById("sel8").value === "No"){
        x = -15;
    }
    else if(document.getElementById("sel8").value === "Yes"){
        x = 10;
    }
    sumValues += Number(x);

//Will staff training be required?
    if(document.getElementById("sel9").value === "No"){
        x = -10;
    }
    else if(document.getElementById("sel9").value === "Yes"){
        x = 10;
    }
    sumValues += Number(x);

//Is this a new initiative or path of an existing initiative?
    if(document.getElementById("sel10").value === "New Initiative"){
        x = 15;
    }
    else if(document.getElementById("sel10").value === "A path"){
        x = 10;
    }
    sumValues += Number(x);

//How does this project interact with current projects?
    if(document.getElementById("sel11").value === "Overlaps with other projects"){
        x = -50;
    }
    else if(document.getElementById("sel11").value === "They have perfect sinergy"){
        x = 25;
    }
    else if(document.getElementById("sel11").value === "They are mutually exclusive"){
        x = 15;
    }
    sumValues += Number(x);

//Is the technology available or new?
    if(document.getElementById("sel12").value === "It´s available"){
        x = 15;
    }
    else if(document.getElementById("sel12").value === "It´s a new technology"){
        x = -5;
    }
    sumValues += Number(x);

    if(sumValues <55){
        $("#txtResultCheckList").html('
Not accepted
');
    }
        else if(sumValues>=55 && sumValues<70){
        $("#txtResultCheckList").html('
Can consider
');
    }
        else
    {
        $("#txtResultCheckList").html('
Project Accepted
');
    }
}

function printpdf(){
  var url ="http://generatepdf-ddnsnet.rhcloud.com/third.php?";
  var contenedorrespuesta = "&respuestas[]=";
  var contenedorpregunta = "&preguntas[]=";
  var contendorfinal;
  for(i=1;i<20;i++){
    contendorfinal += contenedorrespuesta+ $("#txtRespuesta"+i).val()+contenedorpregunta+$("#txtPregunta"+i).text();
  }
  url +=contendorfinal;

  window.open(url);
}<commit_msg>Actualizando<commit_after>
function checkListFunction(){
    var sumValues = 0.0;

//What is the impact of not doing this project?
    if(document.getElementById("sel1").value === "Low"){
        x = 5;
    }
    else if(document.getElementById("sel1").value === "Medium"){
        x = 15;
    }
    else if(document.getElementById("sel1").value === "High"){
        x = 30;
    }
    sumValues += Number(x);

//What is the project risk to our organization?
    if(document.getElementById("sel2").value === "Low"){
        x = -5;
    }
    else if(document.getElementById("sel2").value === "Medium"){
        x = -15;
    }
    else if(document.getElementById("sel2").value === "High"){
        x = -30;
    }
    sumValues += Number(x);

//Does the proposed project fit in our risk profile?
    if(document.getElementById("sel3").value === "No"){
        x = -10;
    }
    else if(document.getElementById("sel3").value === "Yes"){
        x = 10;
    }
    sumValues += Number(x);

//What is the value of the project organization?
    if(document.getElementById("sel4").value === "Low"){
        x = 10;
    }
    else if(document.getElementById("sel4").value === "Medium"){
        x = 15;
    }
    else if(document.getElementById("sel4").value === "High"){
        x = 25;
    }
    sumValues += Number(x);

//Is our organization culture right for this type of project?
    if(document.getElementById("sel5").value === "No"){
        x = -5;
    }
    else if(document.getElementById("sel5").value === "Yes"){
        x = 10;
    }
    sumValues += Number(x);

//Will internal resources be available for this project?
    if(document.getElementById("sel6").value === "No"){
        x = -15;
    }
    else if(document.getElementById("sel6").value === "Yes"){
        x = 10;
    }
    sumValues += Number(x);

//Will we have to build or buy?
    if(document.getElementById("sel7").value === "Buy"){
        x = -15;
    }
    else if(document.getElementById("sel7").value === "Rent"){
        x = -5;
    }
    else if(document.getElementById("sel7").value === "Build"){
        x = -10;
    }
    else if(document.getElementById("sel7").value === "Nothing"){
        x = 20;
    }
    sumValues += Number(x);

//Is the timeline realistic?
    if(document.getElementById("sel8").value === "No"){
        x = -15;
    }
    else if(document.getElementById("sel8").value === "Yes"){
        x = 10;
    }
    sumValues += Number(x);

//Will staff training be required?
    if(document.getElementById("sel9").value === "No"){
        x = -10;
    }
    else if(document.getElementById("sel9").value === "Yes"){
        x = 10;
    }
    sumValues += Number(x);

//Is this a new initiative or path of an existing initiative?
    if(document.getElementById("sel10").value === "New Initiative"){
        x = 15;
    }
    else if(document.getElementById("sel10").value === "A path"){
        x = 10;
    }
    sumValues += Number(x);

//How does this project interact with current projects?
    if(document.getElementById("sel11").value === "Overlaps with other projects"){
        x = -50;
    }
    else if(document.getElementById("sel11").value === "They have perfect sinergy"){
        x = 25;
    }
    else if(document.getElementById("sel11").value === "They are mutually exclusive"){
        x = 15;
    }
    sumValues += Number(x);

//Is the technology available or new?
    if(document.getElementById("sel12").value === "It´s available"){
        x = 15;
    }
    else if(document.getElementById("sel12").value === "It´s a new technology"){
        x = -5;
    }
    sumValues += Number(x);

    if(sumValues <55){
        $("#txtResultCheckList").html('
Not accepted
');
    }
        else if(sumValues>=55 && sumValues<70){
        $("#txtResultCheckList").html('
Can consider
');
    }
        else
    {
        $("#txtResultCheckList").html('
Project Accepted
');
    }
}

function printpdf(){
  var url ="http://generatepdf-ddnsnet.rhcloud.com/third.php?";
  var contenedorrespuesta = "&respuestas[]=";
  var contenedorpregunta = "&preguntas[]=";
  var contendorfinal;
  for(i=1;i<20;i++){
    contendorfinal += contenedorrespuesta+ $("#txtRespuesta"+i).val()+contenedorpregunta+$("#txtPregunta"+i).text();
  }
  url +=contendorfinal+"&result="+$("#txtResultCheckList"+i).text();

  window.open(url);
}<|endoftext|>


<commit_before>import OrientDbSingleton from '../OrientDbSingleton.es6';

let db = OrientDbSingleton.getInstance();

exports.HobbySchema = null; //FIXME

exports.getHobbyById = (root, {id}) => {
  return db.record.get(id);
};

exports.getListOfHobbies = () => {
  return db.select().from("Hobby").all();
};

exports.addHobby = (obj, {title, description}) => {
  var newHobby = new Hobby({title: title, description: description});

  return new Promise((resolve, reject) => {
    newHobby.save((err, res) => {
      err ? reject(err) : resolve(res);
    });
  });
};

exports.updateHobby = (root, {title, description, id}) => {
  let modify = {};
  title ? modify.title = title : null;
  description ? modify.description = description : null;

  return new Promise((resolve, reject) => {
    Hobby.update({id: id}, modify, (err, res) => {
      if (err) {
        reject(err)
      } else {
        Hobby.find({id: id}, (err, res) => {
          err || res.length != 1 ? reject(err) : resolve(res[0]);
        });
      }
    });
  });
};<commit_msg>Hobby Updated<commit_after>import OrientDbSingleton from '../OrientDbSingleton.es6';

let db = OrientDbSingleton.getInstance();

exports.HobbySchema = null; //FIXME

exports.getHobbyById = (root, {id}) => {
  return db.select()
    .from('Hobby')
    .where({"@rid":id})
    .transform(record => {
      record.id = OrientDbSingleton.parseRidResponse(record["@rid"]);
      return record;
    })
    .one()
};

exports.getListOfHobbies = () => {
  return db.select().from("Hobby").all();
};

exports.addHobby = (obj, {title, description}) => {
  var newHobby = new Hobby({title: title, description: description});

  return new Promise((resolve, reject) => {
    newHobby.save((err, res) => {
      err ? reject(err) : resolve(res);
    });
  });
};

exports.updateHobby = (root, {title, description, id}) => {
  let modify = {};
  title ? modify.title = title : null;
  description ? modify.description = description : null;

  return new Promise((resolve, reject) => {
    Hobby.update({id: id}, modify, (err, res) => {
      if (err) {
        reject(err)
      } else {
        Hobby.find({id: id}, (err, res) => {
          err || res.length != 1 ? reject(err) : resolve(res[0]);
        });
      }
    });
  });
};<|endoftext|>