<commit_before>"use strict";

var _ = require("underscore");
var util = require("substance-util");

function _attachListener(el, type, callback) {
  if (el.addEventListener) {
    el.addEventListener(type, callback, true);
  } else {
    el.attachEvent('on' + type, callback);
  }
}

function _detachListener(el, type, callback) {
  if (el.removeEventListener) {
    el.removeEventListener(type, callback, true);
  } else {
    el.detachEvent('on' + type, callback);
  }
}

var ChromeKeyboard = function(map, keytable) {

  this.keytable = keytable;
  this.map = map;

  this.registry = {};

  if (!keytable) {
    var DefaultKeyTable =  require("./default_keytable.js");
    this.keytable = new DefaultKeyTable();
  }

  // to detect if there is a candidate for a given key
  this.__registeredKeyCodes = {"keypress": {}, "keyup": {}, "keydown": {}};

  this.defaultHandlers = {
    "keypress": this.PASS,
    "keyup": this.BLOCK,
    "keydown": this.PASS
  };
};

ChromeKeyboard.Prototype = function() {

  // handler to pass events (does not call prevent default)
  this.PASS = function() {
    // console.log('Keyboard: passing event to parent.');
  };

  this.BLOCK = function(e) {
    //console.log('Keyboard: blocking event.', e);
    e.preventDefault();
    e.stopPropagation();
  };

  var _mods = ['ctrlKey', 'metaKey', 'shiftKey', 'altKey', 'altGraphKey'];

  // for sorting modifiers
  var _modPos = {};
  for (var i = 0; i < _mods.length; i++) {
    _modPos[_mods[i]] = i;
  }

  var _modName = {
    'ctrl': 'ctrlKey',
    'command': 'metaKey',
    'shift': 'shiftKey',
    'alt': 'altKey',
    'alt-gr': 'altGraphKey'
  };

  var _inverseModNames = {};
  _.each(_modName, function(mod, name) {
    _inverseModNames[mod] = name;
  });

  //console.log("_inverseModNames", _inverseModNames);

  this.defaultHandler = function(e) {
    // console.log("Default handler: preventing event", e);
    e.preventDefault();
  };

  var _lookupHandler = function(self, e, start) {
    if (!start) return null;

    var reg = start;
    // traverse to the particular registry for the present modifiers
    for (var i = 0; i < _mods.length; i++) {
      var mod = _mods[i];
      if (e[mod]) {
        reg = reg[mod];
      }
      if (!reg) return null;
    }

    if (reg) {
      return reg[e.keyCode];
    } else {
      return null;
    }
  };

  this.handleKeyPress = function(e) {
    var type = "keypress";
    //console.log("Keyboard keypress", e, this.describeEvent(e));
    // do not handle events without a character...
    if (String.fromCharCode(e.which)) {
      var handler = _lookupHandler(this, e, this.registry[type]);
      if (handler) {
        try {
          handler(e);
        } catch (err) {
          this.BLOCK(e);
          console.error(err.message);
          util.printStackTrace(err);
          throw err;
        }
      } else if (this.defaultHandlers[type]) {
        this.defaultHandlers[type](e);
      }
    } else if (this.defaultHandlers[type]) {
      this.defaultHandlers[type](e);
    } else {
      throw new Error("No default handler for: " + type);
    }

  };

  this.handleKey = function(type, e) {
    // console.log("Keyboard handleKey", type, this.describeEvent(e));
    if (this.__registeredKeyCodes[type][e.keyCode]) {
      //console.log("Keyboard.handleKey", type, this.describeEvent(e));

      var handler = _lookupHandler(this, e, this.registry[type]);

      if (handler) {
        //console.log("... found handler", handler);
        try {
          handler(e);
        } catch (err) {
          this.BLOCK(e);
          console.error(err.message);
          util.printStackTrace(err);
          throw err;
        }
      }
    } else if (this.defaultHandlers[type]) {
      this.defaultHandlers[type](e);
    } else {
      throw new Error("No default handler for: " + type);
    }
  };

  this.connect = function(el) {
    this.el = el;
    this.__onKeyPress = this.handleKeyPress.bind(this);
    this.__onKeyUp = this.handleKey.bind(this, "keyup");
    this.__onKeyDown = this.handleKey.bind(this, "keydown");
    _attachListener(el, 'keypress', this.__onKeyPress);
    _attachListener(el, 'keydown', this.__onKeyDown);
    _attachListener(el, 'keyup', this.__onKeyUp);

    // console.log("Attaching keyboard to", el, "bindings:", this.registry);
  };

  this.disconnect = function() {
    _detachListener(this.el, 'keypress', this.__onKeyPress);
    _detachListener(this.el, 'keydown', this.__onKeyDown);
    _detachListener(this.el, 'keyup', this.__onKeyUp);
  };

  this.setDefaultHandler = function(type, handler) {
    if (arguments.length === 1) {
      _.each(this.defaultHandlers, function(__, name) {
        this.defaultHandlers[name] = arguments[0];
      }, this);
    } else {
      this.defaultHandlers[type] = handler;
    }
  };

  // Bind a handler for a key combination.
  // -----
  // Only key combinations with modifiers and a regular key.
  // Examples:
  // bind('ctrl', 'shift', 'r', myhandler);
  // TODO: I want to get rid of the type. Instead introduce an abstraction
  // that triggers key repetition using only one handler
  this.bindSingle = function(combination, type, handler) {

    if (["keypress", "keydown", "keyup"].indexOf(type) < 0) {
      throw new Error("Expecting keyboard event type as second argument.");
    }
    if (!_.isFunction(handler)) {
      throw new Error("Expecting function handler as third argument.");
    }

    // Note: extract modifiers from the combination.
    // They can be provided in arbitrary order.
    var i;
    var mods = [];
    var mod, modName;
    for (i = 0; i < combination.length-1; i++) {
      modName = combination[i];
      mod = _modName[modName];
      if (!mod) {
        throw new Error("Unknown modifier: " + modName);
      }
      mods.push(mod);
    }
    var key = _.last(combination);
    var keyCode = this.keytable.getKeyCode(key);

    // if the name implies extra modifiers the map can return an array
    if (_.isArray(keyCode)) {
      for (i = 0; i < keyCode.length-1; i++) {
        modName = keyCode[i];
        mod = _modName[modName];
        if (!mod) {
          throw new Error("Unknown modifier: " + modName);
        }
        mods.push(mod);
      }
      keyCode = _.last(keyCode);
    }

    mods.sort(function(a, b) {
      return _modPos[a] - _modPos[b];
    });

    this.registry[type] = this.registry[type] || {};
    var reg = this.registry[type];
    for (i = 0; i < mods.length; i++) {
      mod = mods[i];
      reg[mod] = reg[mod] || {};
      reg = reg[mod];
    }

    reg[keyCode] = handler;

    this.__registeredKeyCodes[type][keyCode] = true;
  };

  this.bindAll = function(combinations, type, handler) {
    for (var i = 0; i < combinations.length; i++) {
      this.bindSingle(combinations[i], type, handler);
    }
  };

  this.bind = function(combination, type, handler) {
    var combinations;
    if (_.isString(combination)) {
      combinations = this.compileMapping(combination);
      this.bindAll(combinations, type, handler);
    } else {
      this.bindSingle(combination, type, handler);
    }
  };

  this.pass = function(combination) {
    var combinations;
    if (_.isString(combination)) {
      combinations = this.compileMapping(combination);
    } else {
      combinations = [combination];
    }
    this.bindAll(combinations, "keyup", this.PASS);
    this.bindAll(combinations, "keydown", this.PASS);
    this.bindAll(combinations, "keypress", this.PASS);
  };

  this.compileMapping = function(name) {
    var combinations = [];
    var specs = this.map[name];
    for (var i = 0; i < specs.length; i++) {
      var spec = specs[i];
      var combination = spec.split("+");
      combinations.push(combination);
    }
    return combinations;
  };

  this.describeEvent = function(e) {
    var names = [];
    for (var i = 0; i < _mods.length; i++) {
      var mod = _mods[i];
      if (e[mod] === true) {
        names.push(_inverseModNames[mod]);
      }
    }
    names.push(this.keytable.getKeyName(e.keyCode));

    return names.join("+");
  };
};
ChromeKeyboard.prototype = new ChromeKeyboard.Prototype();

module.exports = ChromeKeyboard;
<commit_msg>Fixing keypress handling.<commit_after>"use strict";

var _ = require("underscore");
var util = require("substance-util");

function _attachListener(el, type, callback) {
  if (el.addEventListener) {
    el.addEventListener(type, callback, true);
  } else {
    el.attachEvent('on' + type, callback);
  }
}

function _detachListener(el, type, callback) {
  if (el.removeEventListener) {
    el.removeEventListener(type, callback, true);
  } else {
    el.detachEvent('on' + type, callback);
  }
}

var ChromeKeyboard = function(map, keytable) {

  this.keytable = keytable;
  this.map = map;

  this.registry = {};

  if (!keytable) {
    var DefaultKeyTable =  require("./default_keytable.js");
    this.keytable = new DefaultKeyTable();
  }

  // to detect if there is a candidate for a given key
  this.__registeredKeyCodes = {"keypress": {}, "keyup": {}, "keydown": {}};

  this.defaultHandlers = {
    "keypress": this.PASS,
    "keyup": this.BLOCK,
    "keydown": this.PASS
  };
};

ChromeKeyboard.Prototype = function() {

  // handler to pass events (does not call prevent default)
  this.PASS = function() {
    // console.log('Keyboard: passing event to parent.');
  };

  this.BLOCK = function(e) {
    //console.log('Keyboard: blocking event.', e);
    e.preventDefault();
    e.stopPropagation();
  };

  var _mods = ['ctrlKey', 'metaKey', 'shiftKey', 'altKey', 'altGraphKey'];

  // for sorting modifiers
  var _modPos = {};
  for (var i = 0; i < _mods.length; i++) {
    _modPos[_mods[i]] = i;
  }

  var _modName = {
    'ctrl': 'ctrlKey',
    'command': 'metaKey',
    'shift': 'shiftKey',
    'alt': 'altKey',
    'alt-gr': 'altGraphKey'
  };

  var _inverseModNames = {};
  _.each(_modName, function(mod, name) {
    _inverseModNames[mod] = name;
  });

  //console.log("_inverseModNames", _inverseModNames);

  this.defaultHandler = function(e) {
    // console.log("Default handler: preventing event", e);
    e.preventDefault();
  };

  var _lookupHandler = function(self, e, start) {
    if (!start) return null;

    var reg = start;
    // traverse to the particular registry for the present modifiers
    for (var i = 0; i < _mods.length; i++) {
      var mod = _mods[i];
      if (e[mod]) {
        reg = reg[mod];
      }
      if (!reg) return null;
    }

    if (reg) {
      var keyCode = e.keyCode;
      if (e.type === "keypress") {
         keyCode = e.keyCode || self.keytable.table[String.fromCharCode(e.which)];
      }
      return reg[keyCode];
    } else {
      return null;
    }
  };

  this.handleKeyPress = function(e) {
    var type = "keypress";
    //console.log("Keyboard keypress", e, this.describeEvent(e));
    // do not handle events without a character...
    if (String.fromCharCode(e.which)) {
      var handler = _lookupHandler(this, e, this.registry[type]);
      if (handler) {
        try {
          handler(e);
        } catch (err) {
          this.BLOCK(e);
          console.error(err.message);
          util.printStackTrace(err);
          throw err;
        }
      } else if (this.defaultHandlers[type]) {
        this.defaultHandlers[type](e);
      }
    } else if (this.defaultHandlers[type]) {
      this.defaultHandlers[type](e);
    } else {
      throw new Error("No default handler for: " + type);
    }

  };

  this.handleKey = function(type, e) {
    // console.log("Keyboard handleKey", type, this.describeEvent(e));
    if (this.__registeredKeyCodes[type][e.keyCode]) {
      //console.log("Keyboard.handleKey", type, this.describeEvent(e));

      var handler = _lookupHandler(this, e, this.registry[type]);

      if (handler) {
        //console.log("... found handler", handler);
        try {
          handler(e);
        } catch (err) {
          this.BLOCK(e);
          console.error(err.message);
          util.printStackTrace(err);
          throw err;
        }
      }
    } else if (this.defaultHandlers[type]) {
      this.defaultHandlers[type](e);
    } else {
      throw new Error("No default handler for: " + type);
    }
  };

  this.connect = function(el) {
    this.el = el;
    this.__onKeyPress = this.handleKeyPress.bind(this);
    this.__onKeyUp = this.handleKey.bind(this, "keyup");
    this.__onKeyDown = this.handleKey.bind(this, "keydown");
    _attachListener(el, 'keypress', this.__onKeyPress);
    _attachListener(el, 'keydown', this.__onKeyDown);
    _attachListener(el, 'keyup', this.__onKeyUp);

    // console.log("Attaching keyboard to", el, "bindings:", this.registry);
  };

  this.disconnect = function() {
    _detachListener(this.el, 'keypress', this.__onKeyPress);
    _detachListener(this.el, 'keydown', this.__onKeyDown);
    _detachListener(this.el, 'keyup', this.__onKeyUp);
  };

  this.setDefaultHandler = function(type, handler) {
    if (arguments.length === 1) {
      _.each(this.defaultHandlers, function(__, name) {
        this.defaultHandlers[name] = arguments[0];
      }, this);
    } else {
      this.defaultHandlers[type] = handler;
    }
  };

  // Bind a handler for a key combination.
  // -----
  // Only key combinations with modifiers and a regular key.
  // Examples:
  // bind('ctrl', 'shift', 'r', myhandler);
  // TODO: I want to get rid of the type. Instead introduce an abstraction
  // that triggers key repetition using only one handler
  this.bindSingle = function(combination, type, handler) {

    if (["keypress", "keydown", "keyup"].indexOf(type) < 0) {
      throw new Error("Expecting keyboard event type as second argument.");
    }
    if (!_.isFunction(handler)) {
      throw new Error("Expecting function handler as third argument.");
    }

    // Note: extract modifiers from the combination.
    // They can be provided in arbitrary order.
    var i;
    var mods = [];
    var mod, modName;
    for (i = 0; i < combination.length-1; i++) {
      modName = combination[i];
      mod = _modName[modName];
      if (!mod) {
        throw new Error("Unknown modifier: " + modName);
      }
      mods.push(mod);
    }
    var key = _.last(combination);
    var keyCode = this.keytable.getKeyCode(key);

    // if the name implies extra modifiers the map can return an array
    if (_.isArray(keyCode)) {
      for (i = 0; i < keyCode.length-1; i++) {
        modName = keyCode[i];
        mod = _modName[modName];
        if (!mod) {
          throw new Error("Unknown modifier: " + modName);
        }
        mods.push(mod);
      }
      keyCode = _.last(keyCode);
    }

    mods.sort(function(a, b) {
      return _modPos[a] - _modPos[b];
    });

    this.registry[type] = this.registry[type] || {};
    var reg = this.registry[type];
    for (i = 0; i < mods.length; i++) {
      mod = mods[i];
      reg[mod] = reg[mod] || {};
      reg = reg[mod];
    }

    reg[keyCode] = handler;

    this.__registeredKeyCodes[type][keyCode] = true;
  };

  this.bindAll = function(combinations, type, handler) {
    for (var i = 0; i < combinations.length; i++) {
      this.bindSingle(combinations[i], type, handler);
    }
  };

  this.bind = function(combination, type, handler) {
    var combinations;
    if (_.isString(combination)) {
      combinations = this.compileMapping(combination);
      this.bindAll(combinations, type, handler);
    } else {
      this.bindSingle(combination, type, handler);
    }
  };

  this.pass = function(combination) {
    var combinations;
    if (_.isString(combination)) {
      combinations = this.compileMapping(combination);
    } else {
      combinations = [combination];
    }
    this.bindAll(combinations, "keyup", this.PASS);
    this.bindAll(combinations, "keydown", this.PASS);
    this.bindAll(combinations, "keypress", this.PASS);
  };

  this.compileMapping = function(name) {
    var combinations = [];
    var specs = this.map[name];
    for (var i = 0; i < specs.length; i++) {
      var spec = specs[i];
      var combination = spec.split("+");
      combinations.push(combination);
    }
    return combinations;
  };

  this.describeEvent = function(e) {
    var names = [];
    for (var i = 0; i < _mods.length; i++) {
      var mod = _mods[i];
      if (e[mod] === true) {
        names.push(_inverseModNames[mod]);
      }
    }
    names.push(this.keytable.getKeyName(e.keyCode));

    return names.join("+");
  };
};
ChromeKeyboard.prototype = new ChromeKeyboard.Prototype();

module.exports = ChromeKeyboard;
<|endoftext|>


<commit_before>'use strict';

String.prototype.repeat = function (num) {
  return new Array(num + 1).join(this);
};

function getData(url, callback) {
  var xhr = new XMLHttpRequest();
  xhr.open('GET', url, true);
  xhr.responseType = 'arraybuffer';
  xhr.onload = (function() {
    var data = new Uint8Array(xhr.response || xhr.mozResponseArrayBuffer);
    callback(data);
  }).bind(this);
  xhr.send(null);
}

function StreamContents(stream) {
  this.stream = stream;
}

function walker(root) {
  var xref = root.xref;

  function Node(obj, name, depth, ref) {
    this.obj = obj;
    this.name = name;
    this.depth = depth;
    this.ref = ref;
  }

  Node.prototype = {
    get children() {
      var depth = this.depth + 1;
      var obj = this.obj;
      var children = [];
      if (isDict(obj) || isStream(obj)) {
        var map;
        if (isDict(obj)) {
          map = obj.map;
        } else {
          map = obj.dict.map;
        }
        for (var key in map) {
          var value = map[key];
          children.push(new Node(value, key, depth));
        }
        if (isStream(obj)) {
          children.push(new Node(new StreamContents(obj), 'Contents', depth));
        }
      } else if (isArray(obj)) {
        for (var i = 0, ii = obj.length; i < ii; i++) {
          var value = obj[i];
          children.push(new Node(value, i, depth));
        }
      }
      return children;
    }
  };

  function addChildren(node, nodesToVisit) {
    var children = node.children;
    for (var i = children.length - 1; i >= 0; i--) {
      nodesToVisit.push(children[i]);
    }
  }

  function walk(nodesToVisit, visit) {
    while (nodesToVisit.length) {
      var currentNode = nodesToVisit.pop();
      if (currentNode.depth > 20) {
        throw new Error('Depth too big.');
      }

      if (isRef(currentNode.obj)) {
        var fetched = xref.fetch(currentNode.obj);
        currentNode = new Node(fetched, currentNode.name, currentNode.depth, currentNode.obj);
      }
      var visitChildren = visit(currentNode);
      if (visitChildren) {
        addChildren(currentNode, nodesToVisit);
      }
    }
  }

  return {
    start: function (visit) {
      walk([new Node(root, 'Trailer', 0)], visit);
    },
    walk: walk
  };
}

function toText(node) {
  var name = node.name;
  var obj = node.obj;
  var description = '';
  if (isDict(obj)) {
    description = name + ' (dict)';
  } else if (isArray(obj)) {
    description = name + ' (array)';
  } else if (isStream(obj)) {
    description = name + ' (stream)';
  } else if (isName(obj)) {
    description = name + ' = /' + obj.name;
  } else if (isNum(obj)) {
    description = name + ' = ' + obj;
  } else if (isBool(obj)) {
    description = name + ' = ' + obj;
  } else if (isString(obj)) {
    description = name + ' = ' + JSON.stringify(obj) + '';
  } else if (obj instanceof StreamContents) {
    description = '<contents>';
  } else {
    console.log(obj);
    throw new Error('Unknown obj');
  }

  if (node.ref) {
    description += ' [id: ' + node.ref.num + ', gen: ' + node.ref.gen + ']';
  }
  return description;
}

function PrettyPrint() {
  this.out = '';
  this.refSet = new RefSet();
}

PrettyPrint.prototype.visit = function (node) {
  var depth = node.depth;
  this.out += ' '.repeat(depth) + toText(node);
  if (node.ref) {
    if (this.refSet.has(node.ref)) {
      return false;
    }
    this.refSet.put(node.ref);
  }
  this.out += '\n';
  return true;
}

function expando(clickEl, li, element, loadCallback) {
  li.style.listStyleType = 'disc';
  li.appendChild(element);
  clickEl.style.cursor = 'pointer';
  var expanded = false;
  var loaded = false;
  clickEl.addEventListener('click', function () {
    expanded = !expanded;
    element.style.display = expanded ? 'block' : 'none';
    li.style.listStyleType = expanded ? 'circle' : 'disc';
    if (!loaded) {
      loadCallback();
      loaded = true;
      return;
    }
  }.bind(this));
}

function HtmlPrint() {
  this.ul = document.createElement('ul');
  this.ul.id = 'main';
  document.body.appendChild(this.ul);
}

HtmlPrint.prototype.visit = function (ul, node) {
  var obj = node.obj;

  var description = toText(node);

  var li = document.createElement('li');
  li.style.listStyleType = 'none';
  var span = document.createElement('span');
  span.textContent = description;
  li.appendChild(span);

  if (isDict(obj) || isStream(obj) || isArray(obj)) {
    var newUl = document.createElement('ul');
    expando(span, li, newUl, function () {
      this.walk(node.children.reverse(), this.visit.bind(this, newUl));
    }.bind(this));
  } else if (obj instanceof StreamContents) {
    var pre = document.createElement('pre');
    pre.style.marginTop = 0;
    pre.style.marginBottom = 0;
    expando(span, li, pre, function () {
      var bytes = obj.stream.getBytes();
      var string = '';
      for (var i = 0; i < bytes.length; i++) {
        string += String.fromCharCode(bytes[i]);
      }
      pre.textContent = string;
    });
  }
  ul.appendChild(li);

  return false;
};

window.addEventListener('change', function webViewerChange(evt) {
  var files = evt.target.files;
  if (!files || files.length === 0)
    return;

  // Read the local file into a Uint8Array.
  var fileReader = new FileReader();
  fileReader.onload = function webViewerChangeFileReaderOnload(evt) {
    var main = document.querySelector('#main');
    if (main) {
      document.body.removeChild(main);
    }
    var buffer = evt.target.result;
    var uint8Array = new Uint8Array(buffer);

    var pdf = new PDFDocument(null, uint8Array);
    pdf.parseStartXRef();
    pdf.parse();
    var w = walker(pdf.xref.trailer);
    var hp = new HtmlPrint();
    hp.walk = w.walk;
    w.start(hp.visit.bind(hp, hp.ul));
  };

  var file = files[0];
  fileReader.readAsArrayBuffer(file);

}, true);

// getData('/mine/pdf.js/test/pdfs/annotation-tx.pdf', function(data) {
//   var pdf = new PDFDocument(null, data);
//   pdf.parseStartXRef();
//   pdf.parse();
//   var w = walker(pdf.xref.trailer);
//   // var pp = new PrettyPrint();
//   // w.start(pp.visit.bind(pp));
//   // console.log(pp.out);
//   var hp = new HtmlPrint();
//   hp.walk = w.walk;
//   w.start(hp.visit.bind(hp, hp.ul));
//   window.pdf = pdf;
// });
<commit_msg>Add border to stream contents.<commit_after>'use strict';

String.prototype.repeat = function (num) {
  return new Array(num + 1).join(this);
};

function getData(url, callback) {
  var xhr = new XMLHttpRequest();
  xhr.open('GET', url, true);
  xhr.responseType = 'arraybuffer';
  xhr.onload = (function() {
    var data = new Uint8Array(xhr.response || xhr.mozResponseArrayBuffer);
    callback(data);
  }).bind(this);
  xhr.send(null);
}

function StreamContents(stream) {
  this.stream = stream;
}

function walker(root) {
  var xref = root.xref;

  function Node(obj, name, depth, ref) {
    this.obj = obj;
    this.name = name;
    this.depth = depth;
    this.ref = ref;
  }

  Node.prototype = {
    get children() {
      var depth = this.depth + 1;
      var obj = this.obj;
      var children = [];
      if (isDict(obj) || isStream(obj)) {
        var map;
        if (isDict(obj)) {
          map = obj.map;
        } else {
          map = obj.dict.map;
        }
        for (var key in map) {
          var value = map[key];
          children.push(new Node(value, key, depth));
        }
        if (isStream(obj)) {
          children.push(new Node(new StreamContents(obj), 'Contents', depth));
        }
      } else if (isArray(obj)) {
        for (var i = 0, ii = obj.length; i < ii; i++) {
          var value = obj[i];
          children.push(new Node(value, i, depth));
        }
      }
      return children;
    }
  };

  function addChildren(node, nodesToVisit) {
    var children = node.children;
    for (var i = children.length - 1; i >= 0; i--) {
      nodesToVisit.push(children[i]);
    }
  }

  function walk(nodesToVisit, visit) {
    while (nodesToVisit.length) {
      var currentNode = nodesToVisit.pop();
      if (currentNode.depth > 20) {
        throw new Error('Depth too big.');
      }

      if (isRef(currentNode.obj)) {
        var fetched = xref.fetch(currentNode.obj);
        currentNode = new Node(fetched, currentNode.name, currentNode.depth, currentNode.obj);
      }
      var visitChildren = visit(currentNode);
      if (visitChildren) {
        addChildren(currentNode, nodesToVisit);
      }
    }
  }

  return {
    start: function (visit) {
      walk([new Node(root, 'Trailer', 0)], visit);
    },
    walk: walk
  };
}

function toText(node) {
  var name = node.name;
  var obj = node.obj;
  var description = '';
  if (isDict(obj)) {
    description = name + ' (dict)';
  } else if (isArray(obj)) {
    description = name + ' (array)';
  } else if (isStream(obj)) {
    description = name + ' (stream)';
  } else if (isName(obj)) {
    description = name + ' = /' + obj.name;
  } else if (isNum(obj)) {
    description = name + ' = ' + obj;
  } else if (isBool(obj)) {
    description = name + ' = ' + obj;
  } else if (isString(obj)) {
    description = name + ' = ' + JSON.stringify(obj) + '';
  } else if (obj instanceof StreamContents) {
    description = '<contents>';
  } else {
    console.log(obj);
    throw new Error('Unknown obj');
  }

  if (node.ref) {
    description += ' [id: ' + node.ref.num + ', gen: ' + node.ref.gen + ']';
  }
  return description;
}

function PrettyPrint() {
  this.out = '';
  this.refSet = new RefSet();
}

PrettyPrint.prototype.visit = function (node) {
  var depth = node.depth;
  this.out += ' '.repeat(depth) + toText(node);
  if (node.ref) {
    if (this.refSet.has(node.ref)) {
      return false;
    }
    this.refSet.put(node.ref);
  }
  this.out += '\n';
  return true;
}

function expando(clickEl, li, element, loadCallback) {
  element.style.display = 'none';
  li.style.listStyleType = 'disc';
  li.appendChild(element);
  clickEl.style.cursor = 'pointer';
  var expanded = false;
  var loaded = false;
  clickEl.addEventListener('click', function () {
    expanded = !expanded;
    element.style.display = expanded ? 'block' : 'none';
    li.style.listStyleType = expanded ? 'circle' : 'disc';
    if (!loaded) {
      loadCallback();
      loaded = true;
      return;
    }
  }.bind(this));
}

function HtmlPrint() {
  this.ul = document.createElement('ul');
  this.ul.id = 'main';
  document.body.appendChild(this.ul);
}

HtmlPrint.prototype.visit = function (ul, node) {
  var obj = node.obj;

  var description = toText(node);

  var li = document.createElement('li');
  li.style.listStyleType = 'none';
  var span = document.createElement('span');
  span.textContent = description;
  li.appendChild(span);

  if (isDict(obj) || isStream(obj) || isArray(obj)) {
    var newUl = document.createElement('ul');
    expando(span, li, newUl, function () {
      this.walk(node.children.reverse(), this.visit.bind(this, newUl));
    }.bind(this));
  } else if (obj instanceof StreamContents) {
    var pre = document.createElement('pre');
    pre.style.marginTop = 0;
    pre.style.marginBottom = 0;
    pre.style.border = '1px solid black';
    expando(span, li, pre, function () {
      var bytes = obj.stream.getBytes();
      var string = '';
      for (var i = 0; i < bytes.length; i++) {
        string += String.fromCharCode(bytes[i]);
      }
      pre.textContent = string;
    });
  }
  ul.appendChild(li);

  return false;
};

window.addEventListener('change', function webViewerChange(evt) {
  var files = evt.target.files;
  if (!files || files.length === 0)
    return;

  // Read the local file into a Uint8Array.
  var fileReader = new FileReader();
  fileReader.onload = function webViewerChangeFileReaderOnload(evt) {
    var main = document.querySelector('#main');
    if (main) {
      document.body.removeChild(main);
    }
    var buffer = evt.target.result;
    var uint8Array = new Uint8Array(buffer);

    var pdf = new PDFDocument(null, uint8Array);
    pdf.parseStartXRef();
    pdf.parse();
    var w = walker(pdf.xref.trailer);
    var hp = new HtmlPrint();
    hp.walk = w.walk;
    w.start(hp.visit.bind(hp, hp.ul));
  };

  var file = files[0];
  fileReader.readAsArrayBuffer(file);

}, true);

// getData('/mine/pdf.js/test/pdfs/annotation-tx.pdf', function(data) {
//   var pdf = new PDFDocument(null, data);
//   pdf.parseStartXRef();
//   pdf.parse();
//   var w = walker(pdf.xref.trailer);
//   // var pp = new PrettyPrint();
//   // w.start(pp.visit.bind(pp));
//   // console.log(pp.out);
//   var hp = new HtmlPrint();
//   hp.walk = w.walk;
//   w.start(hp.visit.bind(hp, hp.ul));
//   window.pdf = pdf;
// });
<|endoftext|>


<commit_before>/**
 * TopicController
 *
 * @description :: Server-side logic for managing topics
 * @help        :: See http://sailsjs.org/#!/documentation/concepts/Controllers
 */
var Promise = require('bluebird');
var _ = require('lodash');

module.exports = {
  /**
  * @api {post} /packages/:name/versions/:version/topics Create a new topic
  * @apiName Create Topic
  * @apiGroup Topic
  *
  * @apiDescription Create a new Topic from a parsed Rd file, for more information
  * about the fields and their semantic, visit https://developer.r-project.org/parseRd.pdf
  * Note: the Location header of the response is set to the url pointing to the newly created resource
  *
  * @apiParam {String}   name                 `Name` of the topic.
  * @apiParam {String}   title                `Title` of the topic
  * @apiParam {String}   [description]        `Description` section of the topic
  * @apiParam {String}   [usage]              `Usage` section of the topic
  * @apiParam {String}   [details]            `Details` section of the topic
  * @apiParam {String}   [value]              `Value` section of the topic
  * @apiParam {String}   [references]         `References` section of the topic
  * @apiParam {String}   [note]               `Note` section of the topic
  * @apiParam {String}   [seealso]            `See Also` section of the topic
  * @apiParam {String}   [examples]           `Examples` section of the topic
  * @apiParam {String}   [author]              `Author` section about this topic
  * @apiParam {Object[]} [arguments]           List of topic arguments (optional)
  * @apiParam {String}   arguments.name        Name of the argument
  * @apiParam {String}   arguments.description Description of the argument
  * @apiParam {String[]} [keywords]            List of topic keywords, either a array of string or a comma separated list, or a combination of both
  * @apiParam {String[]} [alias]               List of topic aliases, either a array of string or a comma separated list, or a combination of both
  * @apiParam {Object}   [sectionName]         One or more 'section attributes', the key will be the name of the section, and the value will be the description (must be a string)

  @apiError 400 ValidationError
  @apiError 404 The specified package version does not exists
  @apiError 409 ConflictError A topic version with the same name already exists within that package version.

  */
  postRdFile: function(req, res) {
    var packageName = req.param('name');
    var packageVersion = req.param('version');
    var result = Topic.createWithRdFile({input: req.body, packageName: packageName, packageVersion: packageVersion});
    result.then(function(value) {
      res.json(value);
    })
    .catch(Sequelize.UniqueConstraintError, function (err) {
      return res.send(409, err);
    }).catch(Sequelize.ValidationError, function (err) {
      return res.send(400, err);
    }).catch(function(err){
        return res.negotiate(err);
    });
  },

  /**
  * @api {get} /packages/:name/versions/:version/topics/:topic Request Topic information
  * @apiName Get Topic
  * @apiGroup Topic
  *
  * @apiParam {String} name Name of the package
  * @apiParam {String} version Version of the package
  * @apiParam {String} topic Name of the topic to get

  *
  * @apiUse Timestamps
  * @apiSuccess {Number}   id                            id of this topic
  * @apiSuccess {Number}   package_version_id            id of the PackageVersion
  * @apiSuccess {Number}   uri                           Uri to `self`
  * @apiSuccess {String}   name                          Name of this topic
  * @apiSuccess {String}   title                         Title of this topic
  * @apiSuccess {String}   description                   `Description` section of this topic
  * @apiSuccess {String}   usage                         `Usage` section of this topic
  * @apiSuccess {String}   details                       `Details` section of this topic
  * @apiSuccess {String}   value                         `Value` section of this topic
  * @apiSuccess {String}   references                    `References` section of this topic
  * @apiSuccess {String}   author                        `Author` section about this topic
  * @apiSuccess {String}   note                          `Note` section about this topic
  * @apiSuccess {String}   seealso                       `See also` section about this topic
  * @apiSuccess {String}   examples                      `Examples` section about this topic
  * @apiSuccess {Object[]} arguments                     List of topic arguments
  * @apiSuccess {String}   arguments.name                Name of the argument
  * @apiSuccess {String}   arguments.description         Description of the argument
  * @apiSuccess {Object[]} keywords                      List of topic keywords
  * @apiSuccess {String}   keywords.name                 Name of the keyword
  * @apiSuccess {Object[]} aliases                       List of topic aliases
  * @apiSuccess {String}   aliases.name                  Name of the alias
  * @apiSuccess {Object[]} section                       List of topic custom sections
  * @apiSuccess {String}   section.name                  Title of the section
  * @apiSuccess {String}   section.description           Description of the section
  * @apiSuccess {Object}   package_version               Informations about the version of the package
  * @apiSuccess {String}   package_version.url           Url to this version
  * @apiSuccess {String}   package_version.package_url   Url to the package of this version
  * @apiSuccess {String}   package_version.id            Id of this version
  * @apiSuccess {String}   package_version.package_name  Name of the package of this version
  * @apiSuccess {String}   package_version.version       String describing the version of the package
  * @apiSuccess {String}   package_version.title         Title of the version
  * @apiSuccess {String}   package_version.description   Description of the package version
  * @apiSuccess {Date}     package_version.release_date  Release date of the package version
  * @apiSuccess {String}   package_version.license       License of the package version
  * @apiSuccess {String}   package_version.maintainer_id Id of the maintainer of the package version
  */

  findByName: function(req, res) {
    var packageName = req.param('name');
    var packageVersion = req.param('version');
    var topic = req.param('topic');

    Topic.findOnePopulated({name: topic}, {
      include: [{
        model: PackageVersion,
        as: 'package_version',
        where: { package_name: packageName, version: packageVersion }
      }]
    }).then(function(topic) {
      if(topic === null) return res.notFound();
      else return TopicService.computeLinks('/link/', topic)
        .then(function(topic) {
          topic.pageTitle = topic.name;
          return res.ok(topic, 'topic/show.ejs');
        });
    }).catch(function(err) {
      return res.negotiate(err);
    });
  },

   /**
  * @api {get} /topics/:id Request Topic information
  * @apiName Get Topic
  * @apiGroup Topic
  *
  * @apiParam {String} id Id of the package

  *
  * @apiUse Timestamps
  * @apiSuccess {Number}   id                            id of this topic
  * @apiSuccess {Number}   uri                           Uri to `self`
  * @apiSuccess {Number}   package_version_id            id of the PackageVersion
  * @apiSuccess {String}   name                          Name of this topic
  * @apiSuccess {String}   title                         Title of this topic
  * @apiSuccess {String}   description                   `Description` section of this topic
  * @apiSuccess {String}   usage                         `Usage` section of this topic
  * @apiSuccess {String}   details                       `Details` section of this topic
  * @apiSuccess {String}   value                         `Value` section of this topic
  * @apiSuccess {String}   references                    `References` section of this topic
  * @apiSuccess {String}   author                        `Author` section about this topic
  * @apiSuccess {String}   note                          `Note` section about this topic
  * @apiSuccess {String}   seealso                       `See also` section about this topic
  * @apiSuccess {String}   examples                      `Examples` section about this topic
  * @apiSuccess {Object[]} arguments                     List of topic arguments
  * @apiSuccess {String}   arguments.name                Name of the argument
  * @apiSuccess {String}   arguments.description         Description of the argument
  * @apiSuccess {Object[]} keywords                      List of topic keywords
  * @apiSuccess {String}   keywords.name                 Name of the keyword
  * @apiSuccess {Object[]} aliases                       List of topic aliases
  * @apiSuccess {String}   aliases.name                  Name of the alias
  * @apiSuccess {Object[]} section                       List of topic custom sections
  * @apiSuccess {String}   section.name                  Title of the section
  * @apiSuccess {String}   section.description           Description of the section
  * @apiSuccess {Object}   package_version               Informations about the version of the package
  * @apiSuccess {String}   package_version.url           Url to this version
  * @apiSuccess {String}   package_version.package_url   Url to the package of this version
  * @apiSuccess {String}   package_version.id            Id of this version
  * @apiSuccess {String}   package_version.package_name  Name of the package of this version
  * @apiSuccess {String}   package_version.version       String describing the version of the package
  * @apiSuccess {String}   package_version.title         Title of the version
  * @apiSuccess {String}   package_version.description   Description of the package version
  * @apiSuccess {Date}     package_version.release_date  Release date of the package version
  * @apiSuccess {String}   package_version.license       License of the package version
  * @apiSuccess {String}   package_version.maintainer_id Id of the maintainer of the package version
  */

  findById: function(req, res) {
    var id = req.param('id');

    Topic.findOnePopulated({id: id}, {
      include: [{
        model: PackageVersion,
        as: 'package_version',
        attributes: ['package_name', 'version']
      }]
    }).then(function(topic) {
      if(topic === null) return res.notFound();
      else {
        return TopicService.computeLinks('/link/', topic)
          .then(function(topic) {
            topic.pageTitle = topic.name;
            return res.ok(topic, 'topic/show.ejs');
          });
      }
    }).catch(function(err) {
      return res.negotiate(err);
    });
  },

  /**
  * @api {get} /link/:alias?[package=][version=] Redirect to a topic
  * @apiName Redirect to topic
  * @apiGroup Topic
  *
  * @apiParam {String} alias Alias to search for
  * @apiParam {String} package Package name from which we refer to this topic
  * @apiParam {String} version Package version (string) from which we refer to this topic
  */
  findByAlias: function(req, res) {
    var fromPackageName = req.param('package');
    var fromPackageVersion = req.param('version');
    var alias = req.param('alias');
    var toPackage = req.param('to');
    var fromPackage = { package_name: fromPackageName, version: fromPackageVersion };
    var packageCriteria = toPackage ? {package_name: toPackage} : fromPackage;

    RedisService.getJSONFromCache(req.url, RedisService.WEEKLY, function() {

      return Topic.findOne({
        include: [{
          model: Alias,
          as: 'aliases',
          attributes: ['name'],
          where: {
            name: alias
          }
        },
        {
          model: PackageVersion,
          as: 'package_version',
          where: packageCriteria
        }]
      }).then(function(topic) {
        if(topic !== null) return {uri: topic.uri};
        else {
          Alias.findByNameInLatestVersions(alias).then(function(aliases) {
            if (aliases.length === 0) return null; //no match found anywhere, 404
            if (aliases.length === 1) { //if there is only 1 match, redirect to this one
              return {uri: aliases[0].topic.uri};
            } else {
              var searchInDependencies = function(packages, level) {
                if (level >= 3) return Promise.reject('too deep');
                var depsPromises = _.map(packages, function(package_name) {
                  return Dependency.findByDependant(package_name).then(function(deps) {
                    var depsNameArray = _.map(deps, 'dependency_name');
                    var alias = _.find(aliases, function(alias) {
                      return _.includes(depsNameArray, alias.topic.package_version.package_name);
                    });
                    if (alias) {
                      console.info("link found in " + alias.topic.package_version.package_name);
                      return alias.topic.uri;
                    } else throw {dependencies: depsNameArray};
                  });
                });

                return Promise.any(depsPromises).catch(Promise.AggregateError, function(errors) {
                  //not found in this level of dependency, search in next level
                  var deps = _.reduce(errors, function(acc, val) { // collect thrown dependencies
                    return acc.concat(val.dependencies);
                  }, []);
                  return searchInDependencies(deps, level + 1); // recurse to next level of dependency
                });

              };
              searchInDependencies([fromPackage.package_name], 0).then(function(uri) {
                return {uri: uri};
              }).catch(function(err) {
                console.info(err);
                console.info("link not found, go to: " + aliases[0].topic.uri);
                return { uri: aliases[0].topic.uri }; // no match in dependencies, just redirect to first one
              });

            }
          });
        }
      });

    }).then(function(json) {
      if(json !== null) {
        return res.notFound();
      } else {
        return res.redirect(json.uri);
      }
    }).catch(function(err) {
      return res.negotiate(err);
    });
  },

  redirect: function(req,res) {
    var packageName = req.param('name'),
        functionName = req.param('function');

    Package.findOne({
      where: {
        name: packageName,
      },
      include: [
        { model: PackageVersion, as: 'latest_version' },
      ]
    }).then(function(package) {
      if(package === null) {
        return res.notFound();
      } else {
        return res.redirect(package.latest_version.uri + '/topics/' + functionName);
      }
    }).catch(function(err) {
      return res.negotiate(err);
    });
  }

};

<commit_msg>fix typo<commit_after>/**
 * TopicController
 *
 * @description :: Server-side logic for managing topics
 * @help        :: See http://sailsjs.org/#!/documentation/concepts/Controllers
 */
var Promise = require('bluebird');
var _ = require('lodash');

module.exports = {
  /**
  * @api {post} /packages/:name/versions/:version/topics Create a new topic
  * @apiName Create Topic
  * @apiGroup Topic
  *
  * @apiDescription Create a new Topic from a parsed Rd file, for more information
  * about the fields and their semantic, visit https://developer.r-project.org/parseRd.pdf
  * Note: the Location header of the response is set to the url pointing to the newly created resource
  *
  * @apiParam {String}   name                 `Name` of the topic.
  * @apiParam {String}   title                `Title` of the topic
  * @apiParam {String}   [description]        `Description` section of the topic
  * @apiParam {String}   [usage]              `Usage` section of the topic
  * @apiParam {String}   [details]            `Details` section of the topic
  * @apiParam {String}   [value]              `Value` section of the topic
  * @apiParam {String}   [references]         `References` section of the topic
  * @apiParam {String}   [note]               `Note` section of the topic
  * @apiParam {String}   [seealso]            `See Also` section of the topic
  * @apiParam {String}   [examples]           `Examples` section of the topic
  * @apiParam {String}   [author]              `Author` section about this topic
  * @apiParam {Object[]} [arguments]           List of topic arguments (optional)
  * @apiParam {String}   arguments.name        Name of the argument
  * @apiParam {String}   arguments.description Description of the argument
  * @apiParam {String[]} [keywords]            List of topic keywords, either a array of string or a comma separated list, or a combination of both
  * @apiParam {String[]} [alias]               List of topic aliases, either a array of string or a comma separated list, or a combination of both
  * @apiParam {Object}   [sectionName]         One or more 'section attributes', the key will be the name of the section, and the value will be the description (must be a string)

  @apiError 400 ValidationError
  @apiError 404 The specified package version does not exists
  @apiError 409 ConflictError A topic version with the same name already exists within that package version.

  */
  postRdFile: function(req, res) {
    var packageName = req.param('name');
    var packageVersion = req.param('version');
    var result = Topic.createWithRdFile({input: req.body, packageName: packageName, packageVersion: packageVersion});
    result.then(function(value) {
      res.json(value);
    })
    .catch(Sequelize.UniqueConstraintError, function (err) {
      return res.send(409, err);
    }).catch(Sequelize.ValidationError, function (err) {
      return res.send(400, err);
    }).catch(function(err){
        return res.negotiate(err);
    });
  },

  /**
  * @api {get} /packages/:name/versions/:version/topics/:topic Request Topic information
  * @apiName Get Topic
  * @apiGroup Topic
  *
  * @apiParam {String} name Name of the package
  * @apiParam {String} version Version of the package
  * @apiParam {String} topic Name of the topic to get

  *
  * @apiUse Timestamps
  * @apiSuccess {Number}   id                            id of this topic
  * @apiSuccess {Number}   package_version_id            id of the PackageVersion
  * @apiSuccess {Number}   uri                           Uri to `self`
  * @apiSuccess {String}   name                          Name of this topic
  * @apiSuccess {String}   title                         Title of this topic
  * @apiSuccess {String}   description                   `Description` section of this topic
  * @apiSuccess {String}   usage                         `Usage` section of this topic
  * @apiSuccess {String}   details                       `Details` section of this topic
  * @apiSuccess {String}   value                         `Value` section of this topic
  * @apiSuccess {String}   references                    `References` section of this topic
  * @apiSuccess {String}   author                        `Author` section about this topic
  * @apiSuccess {String}   note                          `Note` section about this topic
  * @apiSuccess {String}   seealso                       `See also` section about this topic
  * @apiSuccess {String}   examples                      `Examples` section about this topic
  * @apiSuccess {Object[]} arguments                     List of topic arguments
  * @apiSuccess {String}   arguments.name                Name of the argument
  * @apiSuccess {String}   arguments.description         Description of the argument
  * @apiSuccess {Object[]} keywords                      List of topic keywords
  * @apiSuccess {String}   keywords.name                 Name of the keyword
  * @apiSuccess {Object[]} aliases                       List of topic aliases
  * @apiSuccess {String}   aliases.name                  Name of the alias
  * @apiSuccess {Object[]} section                       List of topic custom sections
  * @apiSuccess {String}   section.name                  Title of the section
  * @apiSuccess {String}   section.description           Description of the section
  * @apiSuccess {Object}   package_version               Informations about the version of the package
  * @apiSuccess {String}   package_version.url           Url to this version
  * @apiSuccess {String}   package_version.package_url   Url to the package of this version
  * @apiSuccess {String}   package_version.id            Id of this version
  * @apiSuccess {String}   package_version.package_name  Name of the package of this version
  * @apiSuccess {String}   package_version.version       String describing the version of the package
  * @apiSuccess {String}   package_version.title         Title of the version
  * @apiSuccess {String}   package_version.description   Description of the package version
  * @apiSuccess {Date}     package_version.release_date  Release date of the package version
  * @apiSuccess {String}   package_version.license       License of the package version
  * @apiSuccess {String}   package_version.maintainer_id Id of the maintainer of the package version
  */

  findByName: function(req, res) {
    var packageName = req.param('name');
    var packageVersion = req.param('version');
    var topic = req.param('topic');

    Topic.findOnePopulated({name: topic}, {
      include: [{
        model: PackageVersion,
        as: 'package_version',
        where: { package_name: packageName, version: packageVersion }
      }]
    }).then(function(topic) {
      if(topic === null) return res.notFound();
      else return TopicService.computeLinks('/link/', topic)
        .then(function(topic) {
          topic.pageTitle = topic.name;
          return res.ok(topic, 'topic/show.ejs');
        });
    }).catch(function(err) {
      return res.negotiate(err);
    });
  },

   /**
  * @api {get} /topics/:id Request Topic information
  * @apiName Get Topic
  * @apiGroup Topic
  *
  * @apiParam {String} id Id of the package

  *
  * @apiUse Timestamps
  * @apiSuccess {Number}   id                            id of this topic
  * @apiSuccess {Number}   uri                           Uri to `self`
  * @apiSuccess {Number}   package_version_id            id of the PackageVersion
  * @apiSuccess {String}   name                          Name of this topic
  * @apiSuccess {String}   title                         Title of this topic
  * @apiSuccess {String}   description                   `Description` section of this topic
  * @apiSuccess {String}   usage                         `Usage` section of this topic
  * @apiSuccess {String}   details                       `Details` section of this topic
  * @apiSuccess {String}   value                         `Value` section of this topic
  * @apiSuccess {String}   references                    `References` section of this topic
  * @apiSuccess {String}   author                        `Author` section about this topic
  * @apiSuccess {String}   note                          `Note` section about this topic
  * @apiSuccess {String}   seealso                       `See also` section about this topic
  * @apiSuccess {String}   examples                      `Examples` section about this topic
  * @apiSuccess {Object[]} arguments                     List of topic arguments
  * @apiSuccess {String}   arguments.name                Name of the argument
  * @apiSuccess {String}   arguments.description         Description of the argument
  * @apiSuccess {Object[]} keywords                      List of topic keywords
  * @apiSuccess {String}   keywords.name                 Name of the keyword
  * @apiSuccess {Object[]} aliases                       List of topic aliases
  * @apiSuccess {String}   aliases.name                  Name of the alias
  * @apiSuccess {Object[]} section                       List of topic custom sections
  * @apiSuccess {String}   section.name                  Title of the section
  * @apiSuccess {String}   section.description           Description of the section
  * @apiSuccess {Object}   package_version               Informations about the version of the package
  * @apiSuccess {String}   package_version.url           Url to this version
  * @apiSuccess {String}   package_version.package_url   Url to the package of this version
  * @apiSuccess {String}   package_version.id            Id of this version
  * @apiSuccess {String}   package_version.package_name  Name of the package of this version
  * @apiSuccess {String}   package_version.version       String describing the version of the package
  * @apiSuccess {String}   package_version.title         Title of the version
  * @apiSuccess {String}   package_version.description   Description of the package version
  * @apiSuccess {Date}     package_version.release_date  Release date of the package version
  * @apiSuccess {String}   package_version.license       License of the package version
  * @apiSuccess {String}   package_version.maintainer_id Id of the maintainer of the package version
  */

  findById: function(req, res) {
    var id = req.param('id');

    Topic.findOnePopulated({id: id}, {
      include: [{
        model: PackageVersion,
        as: 'package_version',
        attributes: ['package_name', 'version']
      }]
    }).then(function(topic) {
      if(topic === null) return res.notFound();
      else {
        return TopicService.computeLinks('/link/', topic)
          .then(function(topic) {
            topic.pageTitle = topic.name;
            return res.ok(topic, 'topic/show.ejs');
          });
      }
    }).catch(function(err) {
      return res.negotiate(err);
    });
  },

  /**
  * @api {get} /link/:alias?[package=][version=] Redirect to a topic
  * @apiName Redirect to topic
  * @apiGroup Topic
  *
  * @apiParam {String} alias Alias to search for
  * @apiParam {String} package Package name from which we refer to this topic
  * @apiParam {String} version Package version (string) from which we refer to this topic
  */
  findByAlias: function(req, res) {
    var fromPackageName = req.param('package');
    var fromPackageVersion = req.param('version');
    var alias = req.param('alias');
    var toPackage = req.param('to');
    var fromPackage = { package_name: fromPackageName, version: fromPackageVersion };
    var packageCriteria = toPackage ? {package_name: toPackage} : fromPackage;

    RedisService.getJSONFromCache(req.url, RedisService.WEEKLY, function() {

      return Topic.findOne({
        include: [{
          model: Alias,
          as: 'aliases',
          attributes: ['name'],
          where: {
            name: alias
          }
        },
        {
          model: PackageVersion,
          as: 'package_version',
          where: packageCriteria
        }]
      }).then(function(topic) {
        if(topic !== null) return {uri: topic.uri};
        else {
          Alias.findByNameInLatestVersions(alias).then(function(aliases) {
            if (aliases.length === 0) return null; //no match found anywhere, 404
            if (aliases.length === 1) { //if there is only 1 match, redirect to this one
              return {uri: aliases[0].topic.uri};
            } else {
              var searchInDependencies = function(packages, level) {
                if (level >= 3) return Promise.reject('too deep');
                var depsPromises = _.map(packages, function(package_name) {
                  return Dependency.findByDependant(package_name).then(function(deps) {
                    var depsNameArray = _.map(deps, 'dependency_name');
                    var alias = _.find(aliases, function(alias) {
                      return _.includes(depsNameArray, alias.topic.package_version.package_name);
                    });
                    if (alias) {
                      console.info("link found in " + alias.topic.package_version.package_name);
                      return alias.topic.uri;
                    } else throw {dependencies: depsNameArray};
                  });
                });

                return Promise.any(depsPromises).catch(Promise.AggregateError, function(errors) {
                  //not found in this level of dependency, search in next level
                  var deps = _.reduce(errors, function(acc, val) { // collect thrown dependencies
                    return acc.concat(val.dependencies);
                  }, []);
                  return searchInDependencies(deps, level + 1); // recurse to next level of dependency
                });

              };
              searchInDependencies([fromPackage.package_name], 0).then(function(uri) {
                return {uri: uri};
              }).catch(function(err) {
                console.info(err);
                console.info("link not found, go to: " + aliases[0].topic.uri);
                return { uri: aliases[0].topic.uri }; // no match in dependencies, just redirect to first one
              });

            }
          });
        }
      });

    }).then(function(json) {
      if(json === null) {
        return res.notFound();
      } else {
        return res.redirect(json.uri);
      }
    }).catch(function(err) {
      return res.negotiate(err);
    });
  },

  redirect: function(req,res) {
    var packageName = req.param('name'),
        functionName = req.param('function');

    Package.findOne({
      where: {
        name: packageName,
      },
      include: [
        { model: PackageVersion, as: 'latest_version' },
      ]
    }).then(function(package) {
      if(package === null) {
        return res.notFound();
      } else {
        return res.redirect(package.latest_version.uri + '/topics/' + functionName);
      }
    }).catch(function(err) {
      return res.negotiate(err);
    });
  }

};

<|endoftext|>


<commit_before>const searchFiltersList = {
  method: [
    {
      sectionKey: "Type & Purpose",
      sectionLabel: "Type & Purpose",
      fieldNameKeys: ["method_types", "purpose_method", "public_spectrum"],
    },
    {
      sectionKey: "Participants",
      sectionLabel: "Participants",
      fieldNameKeys: [
        "open_limited",
        "recruitment_method",
        "number_of_participants",
      ],
    },
    {
      sectionKey: "Process",
      sectionLabel: "Process",
      fieldNameKeys: [
        "facetoface_online_or_both",
        "facilitators",
        "participants_interactions",
        "decision_methods",
      ],
    },
    {
      sectionKey: "Suitable For",
      sectionLabel: "Suitable For",
      fieldNameKeys: [
        "scope_of_influence",
        "level_polarization",
        "level_complexity",
      ],
    },
    {
      sectionKey: "Entry Completeness",
      sectionLabel: "Entry Completeness",
      fieldNameKeys: ["completeness"],
    },
    {
      sectionKey: "collections",
      sectionLabel: "Collections",
      fieldNameKeys: ["collections"],
    },
  ],
  organizations: [
    {
      sectionKey: "Country",
      sectionLabel: "Country",
      fieldNameKeys: ["country"],
    },
    {
      sectionKey: "Scope of Operations",
      sectionLabel: "Scope of Operations",
      fieldNameKeys: ["scope_of_influence"],
    },
    {
      sectionKey: "Focus Area",
      sectionLabel: "Focus Area",
      fieldNameKeys: ["sector", "general_issues"],
    },
    {
      sectionKey: "Process",
      sectionLabel: "Process",
      fieldNameKeys: ["type_method", "type_tool"],
    },
    {
      sectionKey: "Entry Completeness",
      sectionLabel: "Entry Completeness",
      fieldNameKeys: ["completeness"],
    },
    {
      sectionKey: "collections",
      sectionLabel: "Collections",
      fieldNameKeys: ["collections"],
    },
  ],
  case: [
    {
      sectionKey: "issues",
      sectionLabel: "Issues",
      fieldNameKeys: ["general_issues"],
    },
    {
      sectionKey: "location",
      sectionLabel: "Location",
      fieldNameKeys: ["country", "scope_of_influence"],
    },
    {
      sectionKey: "purpose_and_approach",
      sectionLabel: "Purpose & Approach",
      fieldNameKeys: ["purposes", "approaches", "public_spectrum"],
    },
    {
      sectionKey: "participants",
      sectionLabel: "Participants",
      fieldNameKeys: ["open_limited", "recruitment_method"],
    },
    {
      sectionKey: "process",
      sectionLabel: "Process",
      fieldNameKeys: [
        "method_types",
        "tools_techniques_types",
        "facetoface_online_or_both",
      ],
    },
    {
      sectionKey: "organizers_supporters",
      sectionLabel: "Organizers & Supporters",
      fieldNameKeys: ["organizer_types", "funder_types"],
    },
    {
      sectionKey: "evidence_of_impact",
      sectionLabel: "Evidence of Impact",
      fieldNameKeys: ["change_types"],
    },
    {
      sectionKey: "collections",
      sectionLabel: "Collections",
      fieldNameKeys: ["collections"],
    },
    {
      sectionKey: "Entry Completeness",
      sectionLabel: "Entry Completeness",
      fieldNameKeys: ["completeness"],
    },
  ],
};

module.exports = searchFiltersList;
<commit_msg>remove collection filter for cases, methods and organizations<commit_after>const searchFiltersList = {
  method: [
    {
      sectionKey: "Type & Purpose",
      sectionLabel: "Type & Purpose",
      fieldNameKeys: ["method_types", "purpose_method", "public_spectrum"],
    },
    {
      sectionKey: "Participants",
      sectionLabel: "Participants",
      fieldNameKeys: [
        "open_limited",
        "recruitment_method",
        "number_of_participants",
      ],
    },
    {
      sectionKey: "Process",
      sectionLabel: "Process",
      fieldNameKeys: [
        "facetoface_online_or_both",
        "facilitators",
        "participants_interactions",
        "decision_methods",
      ],
    },
    {
      sectionKey: "Suitable For",
      sectionLabel: "Suitable For",
      fieldNameKeys: [
        "scope_of_influence",
        "level_polarization",
        "level_complexity",
      ],
    },
    {
      sectionKey: "Entry Completeness",
      sectionLabel: "Entry Completeness",
      fieldNameKeys: ["completeness"],
    },
  ],
  organizations: [
    {
      sectionKey: "Country",
      sectionLabel: "Country",
      fieldNameKeys: ["country"],
    },
    {
      sectionKey: "Scope of Operations",
      sectionLabel: "Scope of Operations",
      fieldNameKeys: ["scope_of_influence"],
    },
    {
      sectionKey: "Focus Area",
      sectionLabel: "Focus Area",
      fieldNameKeys: ["sector", "general_issues"],
    },
    {
      sectionKey: "Process",
      sectionLabel: "Process",
      fieldNameKeys: ["type_method", "type_tool"],
    },
    {
      sectionKey: "Entry Completeness",
      sectionLabel: "Entry Completeness",
      fieldNameKeys: ["completeness"],
    }
  ],
  case: [
    {
      sectionKey: "issues",
      sectionLabel: "Issues",
      fieldNameKeys: ["general_issues"],
    },
    {
      sectionKey: "location",
      sectionLabel: "Location",
      fieldNameKeys: ["country", "scope_of_influence"],
    },
    {
      sectionKey: "purpose_and_approach",
      sectionLabel: "Purpose & Approach",
      fieldNameKeys: ["purposes", "approaches", "public_spectrum"],
    },
    {
      sectionKey: "participants",
      sectionLabel: "Participants",
      fieldNameKeys: ["open_limited", "recruitment_method"],
    },
    {
      sectionKey: "process",
      sectionLabel: "Process",
      fieldNameKeys: [
        "method_types",
        "tools_techniques_types",
        "facetoface_online_or_both",
      ],
    },
    {
      sectionKey: "organizers_supporters",
      sectionLabel: "Organizers & Supporters",
      fieldNameKeys: ["organizer_types", "funder_types"],
    },
    {
      sectionKey: "evidence_of_impact",
      sectionLabel: "Evidence of Impact",
      fieldNameKeys: ["change_types"],
    },
    {
      sectionKey: "Entry Completeness",
      sectionLabel: "Entry Completeness",
      fieldNameKeys: ["completeness"],
    },
  ],
};

module.exports = searchFiltersList;
<|endoftext|>


<commit_before>RT = RT || {};
ReactTemplate = {};

React.Component.createFromBlaze = function(type, className, renderFunc) {
  ReactTemplate[className] = renderFunc;

  Template[className] = class extends BlazeReact {
    constructor(props) {
      super(props, className);
    }
  }

  if (type === 'body') {
    if (Package['kadira:flow-router-ssr'] && Meteor.isClient) {
      // Disable warnings of missing "/" route.
      Package['kadira:flow-router-ssr'].FlowRouter.route('/');
    }

    // Wait for DOM is loaded.
    Meteor.startup(function() {
      let body = React.createElement(Template[className]);
      if (Meteor.isClient) {
        ReactDOM.render(body, Template._getRootNode());
      }
      else if (Package['kadira:flow-router-ssr']) {
        // Enable fast page loads using flow-router-ssr.
        var FlowRouter = Package['kadira:flow-router-ssr'].FlowRouter;
        FlowRouter.setDeferScriptLoading(true);
        FlowRouter.route('/', {
          action: function() {
            var rootNodeHtml = Template._buildRootNode();
            let elHtml = ReactDOMServer.renderToString(body);
            let html = rootNodeHtml.replace('', elHtml + '');

            var ssrContext = FlowRouter.ssrContext.get();
            ssrContext.setHtml(html);
          }
        });
      }
    });
  }
}

// Build out Handlebars basic SafeString type
RT.SafeString = function(string) {
  this.string = string;
};
RT.SafeString.prototype.toString = RT.SafeString.prototype.toHTML = function() {
  return '' + this.string;
};

RT.classNames = function(obj) {
  this.obj = obj;
};
RT.classNames.prototype.toString = RT.classNames.prototype.toHTML = function() {
  return '' + new RT.SafeString(RT._classNames(this.obj));
};

RT.lookup = function(context, string) {
  const tests = string.split('.');
  if (!context) {
    return false;
  }
  // Look in the context for a matching dot-object pattern.
  let obj = context;
  for (let i in tests) {
    let test = tests[i];
    if (typeof obj === 'undefined') {
      return false;
    }
    // If we're running through an each-in loop pass on the context.
    if (i == tests.length - 1 && context.__context) {
      props = Object.getOwnPropertyDescriptor(obj, test);
      if (props.hasOwnProperty('get')) {
        obj = props.get.call(context.__context);
      }
      else {
        obj = props.value;
      }
    }
    else {
      // Iterate on to next child in dot-object pattern.
      obj = obj[test];
    }
  }
  // Last check if undefined.
  if (typeof obj === 'undefined') {
    return false;
  }
  return obj;
};

RT.string = function(context, string) {
  let value = RT.lookup(context, string);
  if (value !== false) {
    return "" + new RT.SafeString(value);
  }
  return "";
}

RT.get = function(props) {
  // A template component exists.
  if (Template && Template[props.__name]) {
    return React.createElement(Template[props.__name], _.omit(props, '__name'));
  }
  // A template exists.
  else if (ReactTemplate[props.__name]) {
    return React.createElement(ReactTemplate[props.__name], _.omit(props, '__name'));
  }
  return "";
}

RT.event = function(component, key, context) {
  if (component && component.events && component.events[key]) {
    return component.events[key].bind(component, context);
  }
}
<commit_msg>Removing default FlowRouter.setDeferScriptLoading.<commit_after>RT = RT || {};
ReactTemplate = {};

React.Component.createFromBlaze = function(type, className, renderFunc) {
  ReactTemplate[className] = renderFunc;

  Template[className] = class extends BlazeReact {
    constructor(props) {
      super(props, className);
    }
  }

  if (type === 'body') {
    if (Package['kadira:flow-router-ssr'] && Meteor.isClient) {
      // Disable warnings of missing "/" route.
      Package['kadira:flow-router-ssr'].FlowRouter.route('/');
    }

    // Wait for DOM is loaded.
    Meteor.startup(function() {
      let body = React.createElement(Template[className]);
      if (Meteor.isClient) {
        ReactDOM.render(body, Template._getRootNode());
      }
      else if (Package['kadira:flow-router-ssr']) {
        // Enable fast page loads using flow-router-ssr.
        var FlowRouter = Package['kadira:flow-router-ssr'].FlowRouter;
        FlowRouter.route('/', {
          action: function() {
            var rootNodeHtml = Template._buildRootNode();
            let elHtml = ReactDOMServer.renderToString(body);
            let html = rootNodeHtml.replace('', elHtml + '');

            var ssrContext = FlowRouter.ssrContext.get();
            ssrContext.setHtml(html);
          }
        });
      }
    });
  }
}

// Build out Handlebars basic SafeString type
RT.SafeString = function(string) {
  this.string = string;
};
RT.SafeString.prototype.toString = RT.SafeString.prototype.toHTML = function() {
  return '' + this.string;
};

RT.classNames = function(obj) {
  this.obj = obj;
};
RT.classNames.prototype.toString = RT.classNames.prototype.toHTML = function() {
  return '' + new RT.SafeString(RT._classNames(this.obj));
};

RT.lookup = function(context, string) {
  const tests = string.split('.');
  if (!context) {
    return false;
  }
  // Look in the context for a matching dot-object pattern.
  let obj = context;
  for (let i in tests) {
    let test = tests[i];
    if (typeof obj === 'undefined') {
      return false;
    }
    // If we're running through an each-in loop pass on the context.
    if (i == tests.length - 1 && context.__context) {
      props = Object.getOwnPropertyDescriptor(obj, test);
      if (props.hasOwnProperty('get')) {
        obj = props.get.call(context.__context);
      }
      else {
        obj = props.value;
      }
    }
    else {
      // Iterate on to next child in dot-object pattern.
      obj = obj[test];
    }
  }
  // Last check if undefined.
  if (typeof obj === 'undefined') {
    return false;
  }
  return obj;
};

RT.string = function(context, string) {
  let value = RT.lookup(context, string);
  if (value !== false) {
    return "" + new RT.SafeString(value);
  }
  return "";
}

RT.get = function(props) {
  // A template component exists.
  if (Template && Template[props.__name]) {
    return React.createElement(Template[props.__name], _.omit(props, '__name'));
  }
  // A template exists.
  else if (ReactTemplate[props.__name]) {
    return React.createElement(ReactTemplate[props.__name], _.omit(props, '__name'));
  }
  return "";
}

RT.event = function(component, key, context) {
  if (component && component.events && component.events[key]) {
    return component.events[key].bind(component, context);
  }
}
<|endoftext|>


<commit_before>//$counters = new Array();
$counters = {};
//$box = new Array();
$abnormal = false;
$undo = false;
$keyboard_active = false;
$img_displayed = false;

$(document).ready(function() {

    $("#myCounts").tablesorter();

    $('.count').each(
        function(){
            //access to element via $(this)
            $key = $(this).find('div#key').text();
            $name = $(this).find('font2').text();
            $img = $(this).find('a#img').text();
            $counters[$name] = {};
            $counters[$name]["key"] = $key.toUpperCase();
            $counters[$name]["count"] = 0;
            $counters[$name]["abnormal"] = 0;
            $counters[$name]["box"] = $(this);
            $counters[$name]["img"] = $img;

            //$count[$key] = 0;
            //$count[$key + "_abnormal"] = 0;
            //$box[$key] = $(this);
            //$box[$key + "_abnormal"] = $(this);
        }
    );

$('#openkeyboard').click(function() {
  $('#fuzz').fadeIn('slow', function() {
    $('#counterbox').slideDown('slow', function() {
      // Animation complete.
      $("#fuzz").css("height", $(document).height());
      $keyboard_active = true;
    });
  });
});

  $('#fuzz').click(function() {
     if($keyboard_active) {
       $keyboard_active = false;

       $output = {};
       $total = 0;
       for (var prop in $counters) {
         if ($counters.hasOwnProperty(prop)) {
           // or if (Object.prototype.hasOwnProperty.call(obj,prop)) for safety...
           $output[prop] = {}
           $output[prop]["normal"] = $counters[prop]["count"];
           $output[prop]["abnormal"] = $counters[prop]["abnormal"];

           $total += $counters[prop]["count"];
           $total += $counters[prop]["abnormal"];
         }
       }

    // Put counts into the ModelForms
    for (var cell in $output) {
        if ($output.hasOwnProperty(cell)) {
            $("#"+cell+"").children()[1].value=$output[cell]["normal"]
            $("#"+cell+"").children()[2].value=$output[cell]["abnormal"]
        }
    }

    $percent = {};
    $per = "";
       for (var prop in $counters) {
         if ($counters.hasOwnProperty(prop)) {
           // or if (Object.prototype.hasOwnProperty.call(obj,prop)) for safety...
           $percent[prop] = ($counters[prop]["count"] + $counters[prop]["abnormal"]) / $total * 100;
    $per += '
' + prop + '	' + parseFloat($percent[prop]).toFixed(2) + "%
";
         }
       }

    if($total > 0) {
         $('div#statistics').empty().append('
Count statistics

' + $per + '
');
    }

       $('#counterbox').slideUp('slow', function() {
         $('#fuzz').fadeOut('slow', function() {
         });
       });
     }
  });

//Adjust height of overlay to fill screen when browser gets resized
$(window).bind("resize", function(){
   $("#fuzz").css("height", $(document).height());
   //$("#fuzz").css("top", $(window).top());
});
   //$("#fuzz").css("height", $(document).height());

$('#submit').click(function() {
  $results = $.toJSON($output);
  $("#results").text($results);
});

    //$(document).keypress(function(e) {
    jQuery(document).bind('keydown', function (e){
        //Event.stop(e);
      if($keyboard_active) {
      $key = String.fromCharCode(e.which).toUpperCase();
      $code = e.which;
      $shift_pressed = e.shiftKey;
      if($code == 188) $key = ","; // XXX: WTF
      if($code == 173) $key = "-"; // XXX: WTF

      if($key == " ") {
        $abnormal = true;
        //Event.stop(e);
        return false;
        //$("div#imagebox").css("background-image", "");
      }
      else if($code == 8) {
        $undo = true;
        return false;
      }
      else {
        if($shift_pressed) {
          for (var prop in $counters) {
            if($counters[prop]["key"] == $key) {
              $el = $("div#imagebox");
              $el.css("display", "block");
              $el.find("div#imgdisplay").css("background-image", "url(" + $counters[prop]["img"] + ")");
              $img_displayed = true;
            }
          }
        }
        else {
          if($img_displayed) {
              $("div#imagebox").css("display", "none");
              $img_displayed = false;
              return;
          }
          $count_total = 0;
          $abnormal_total = 0;
          for (var prop in $counters) {
          if($counters[prop]["key"] == $key) {
            if($abnormal) {
              if($undo) {
                if($counters[prop]["abnormal"] > 0)
                  $counters[prop]["abnormal"]--;
              }
              else
                $counters[prop]["abnormal"]++;
              $($counters[prop]["box"]).find("span#abnormal").text($counters[prop]["abnormal"]);
            }
            else {
              if($undo) {
                if($counters[prop]["count"] > 0)
                  $counters[prop]["count"]--;
              }
              else
                $counters[prop]["count"]++;
              $($counters[prop]["box"]).find("span#countval").text($counters[prop]["count"]);
            }
          }
          $count_total += $counters[prop]["abnormal"];
          $count_total += $counters[prop]["count"];

          }
        $("#total").text($count_total);

        }
      }
      }
    });

    jQuery(document).bind('keyup', function (e){
      if($keyboard_active) {
        $code = e.which;
        $key = String.fromCharCode($code).toUpperCase();
        if($code == 173) $key = "-"; // XXX: WTF

        if($key == " ")
          $abnormal = false;
        if($code == 8)
          $undo = false;
      }
    });

});

/*window.onkeydown=function(e){
if(e.keyCode==32){
return false;
}
}; */
<commit_msg>Updated counter to disable elements on IronStain form<commit_after>//$counters = new Array();
$counters = {};
//$box = new Array();
$abnormal = false;
$undo = false;
$keyboard_active = false;
$img_displayed = false;

$(document).ready(function() {

    $("#myCounts").tablesorter();

    $('.count').each(
        function(){
            //access to element via $(this)
            $key = $(this).find('div#key').text();
            $name = $(this).find('font2').text();
            $img = $(this).find('a#img').text();
            $counters[$name] = {};
            $counters[$name]["key"] = $key.toUpperCase();
            $counters[$name]["count"] = 0;
            $counters[$name]["abnormal"] = 0;
            $counters[$name]["box"] = $(this);
            $counters[$name]["img"] = $img;

            //$count[$key] = 0;
            //$count[$key + "_abnormal"] = 0;
            //$box[$key] = $(this);
            //$box[$key + "_abnormal"] = $(this);
        }
    );

$('#openkeyboard').click(function() {
  $('#fuzz').fadeIn('slow', function() {
    $('#counterbox').slideDown('slow', function() {
      // Animation complete.
      $("#fuzz").css("height", $(document).height());
      $keyboard_active = true;
    });
  });
});

  $('#fuzz').click(function() {
     if($keyboard_active) {
       $keyboard_active = false;

       $output = {};
       $total = 0;
       for (var prop in $counters) {
         if ($counters.hasOwnProperty(prop)) {
           // or if (Object.prototype.hasOwnProperty.call(obj,prop)) for safety...
           $output[prop] = {}
           $output[prop]["normal"] = $counters[prop]["count"];
           $output[prop]["abnormal"] = $counters[prop]["abnormal"];

           $total += $counters[prop]["count"];
           $total += $counters[prop]["abnormal"];
         }
       }

    // Put counts into the ModelForms
    for (var cell in $output) {
        if ($output.hasOwnProperty(cell)) {
            $("#"+cell+"").children()[1].value=$output[cell]["normal"]
            $("#"+cell+"").children()[2].value=$output[cell]["abnormal"]
        }
    }

    $percent = {};
    $per = "";
       for (var prop in $counters) {
         if ($counters.hasOwnProperty(prop)) {
           // or if (Object.prototype.hasOwnProperty.call(obj,prop)) for safety...
           $percent[prop] = ($counters[prop]["count"] + $counters[prop]["abnormal"]) / $total * 100;
    $per += '
' + prop + '	' + parseFloat($percent[prop]).toFixed(2) + "%
";
         }
       }

    if($total > 0) {
         $('div#statistics').empty().append('
Count statistics

' + $per + '
');
    }

       $('#counterbox').slideUp('slow', function() {
         $('#fuzz').fadeOut('slow', function() {
         });
       });
     }
  });

//Adjust height of overlay to fill screen when browser gets resized
$(window).bind("resize", function(){
   $("#fuzz").css("height", $(document).height());
   //$("#fuzz").css("top", $(window).top());
});
   //$("#fuzz").css("height", $(document).height());

$('#submit').click(function() {
  $results = $.toJSON($output);
  $("#results").text($results);
});

    //$(document).keypress(function(e) {
    jQuery(document).bind('keydown', function (e){
        //Event.stop(e);
      if($keyboard_active) {
      $key = String.fromCharCode(e.which).toUpperCase();
      $code = e.which;
      $shift_pressed = e.shiftKey;
      if($code == 188) $key = ","; // XXX: WTF
      if($code == 173) $key = "-"; // XXX: WTF

      if($key == " ") {
        $abnormal = true;
        //Event.stop(e);
        return false;
        //$("div#imagebox").css("background-image", "");
      }
      else if($code == 8) {
        $undo = true;
        return false;
      }
      else {
        if($shift_pressed) {
          for (var prop in $counters) {
            if($counters[prop]["key"] == $key) {
              $el = $("div#imagebox");
              $el.css("display", "block");
              $el.find("div#imgdisplay").css("background-image", "url(" + $counters[prop]["img"] + ")");
              $img_displayed = true;
            }
          }
        }
        else {
          if($img_displayed) {
              $("div#imagebox").css("display", "none");
              $img_displayed = false;
              return;
          }
          $count_total = 0;
          $abnormal_total = 0;
          for (var prop in $counters) {
          if($counters[prop]["key"] == $key) {
            if($abnormal) {
              if($undo) {
                if($counters[prop]["abnormal"] > 0)
                  $counters[prop]["abnormal"]--;
              }
              else
                $counters[prop]["abnormal"]++;
              $($counters[prop]["box"]).find("span#abnormal").text($counters[prop]["abnormal"]);
            }
            else {
              if($undo) {
                if($counters[prop]["count"] > 0)
                  $counters[prop]["count"]--;
              }
              else
                $counters[prop]["count"]++;
              $($counters[prop]["box"]).find("span#countval").text($counters[prop]["count"]);
            }
          }
          $count_total += $counters[prop]["abnormal"];
          $count_total += $counters[prop]["count"];

          }
        $("#total").text($count_total);

        }
      }
      }
    });

    jQuery(document).bind('keyup', function (e){
      if($keyboard_active) {
        $code = e.which;
        $key = String.fromCharCode($code).toUpperCase();
        if($code == 173) $key = "-"; // XXX: WTF

        if($key == " ")
          $abnormal = false;
        if($code == 8)
          $undo = false;
      }
    });

});

/*window.onkeydown=function(e){
if(e.keyCode==32){
return false;
}
}; */

function ironstain() {
    if (document.getElementById("id_ironstain-stain_performed").checked == true) {
        document.getElementById("id_ironstain-ringed_sideroblasts").disabled = false;
        document.getElementById("id_ironstain-iron_content").disabled = false;
        document.getElementById("id_ironstain-comment").disabled = false;
    } else {
        document.getElementById("id_ironstain-ringed_sideroblasts").disabled = true;
        document.getElementById("id_ironstain-iron_content").disabled = true;
        document.getElementById("id_ironstain-comment").disabled = true;
    }
}

<|endoftext|>