<commit_before>"use strict";

Option.saveOptions = function() {
  for (var arr = Option.all, i = arr.length; 0 <= --i; ) {
    arr[i].saved || arr[i].save();
  }
};

Option.needSaveOptions = function() {
  for (var arr = Option.all, i = arr.length; 0 <= --i; ) {
    if (!arr[i].saved) {
      return true;
    }
  }
  return false;
};

Option.prototype.areEqual = function(a, b) {
  return this.saved = a === b;
};

function NumberOption() {
  NumberOption.__super__.constructor.apply(this, arguments);
  this.element.addEventListener("input", this.onUpdated);
}
__extends(NumberOption, Option);

NumberOption.prototype.populateElement = function(value) {
  return this.element.value = value;
};

NumberOption.prototype.readValueFromElement = function() {
  return parseFloat(this.element.value);
};

function TextOption() {
  TextOption.__super__.constructor.apply(this, arguments);
  this.element.addEventListener("input", this.onUpdated);
}
__extends(TextOption, Option);

TextOption.prototype.headWhiteRe = /\n /g;
TextOption.prototype.whiteMaskRe = /\xa0/g;
TextOption.prototype.populateElement = function(value) {
  return this.element.value = value.replace(this.headWhiteRe, '\n\xa0');
};

TextOption.prototype.readValueFromElement = function() {
  return this.element.value.trim().replace(this.whiteMaskRe, ' ');
};

function NonEmptyTextOption(element) {
  NonEmptyTextOption.__super__.constructor.apply(this, arguments);
}
__extends(NonEmptyTextOption, TextOption);

NonEmptyTextOption.prototype.readValueFromElement = function() {
  var value = NonEmptyTextOption.__super__.readValueFromElement.call(this);
  if (!value) {
    value = bgSettings.defaults[this.field];
    this.populateElement(value);
  }
  return value;
};

function JSONOption() {
  JSONOption.__super__.constructor.apply(this, arguments);
}
__extends(JSONOption, TextOption);

JSONOption.prototype.populateElement = function(obj) {
  return JSONOption.__super__.populateElement.call(this, JSON.stringify(obj, null, 2));
};

JSONOption.prototype.readValueFromElement = function() {
  var value = JSONOption.__super__.readValueFromElement.call(this), obj;
  if (value) {
    try {
      obj = JSON.parse(value);
    } catch (e) {
      obj = null;
    }
  } else {
    obj = bgSettings.defaults[this.field];
    this.populateElement(obj);
  }
  return obj;
};

JSONOption.prototype.areEqual = Option.areJSONEqual;

function CheckBoxOption() {
  CheckBoxOption.__super__.constructor.apply(this, arguments);
  this.element.addEventListener("change", this.onUpdated);
}
__extends(CheckBoxOption, Option);

CheckBoxOption.prototype.populateElement = function(value) {
  return this.element.checked = value;
};

CheckBoxOption.prototype.readValueFromElement = function() {
  return this.element.checked;
};

(function() {
  var advancedMode, element, name, onUpdated, saveOptions, type, _i, _ref, status = 0;

  onUpdated = function() {
    var saveBtn;
    if (this.areEqual(this.readValueFromElement(), this.previous)) {
      if (status == 1 && !Option.needSaveOptions()) {
        saveBtn = $("saveOptions");
        saveBtn.disabled = true;
        saveBtn.textContent = "No Changes";
        $("exportButton").disabled = false;
        status = 0;
      }
      return;
    } else if (status == 1) {
      return;
    }
    status = 1;
    saveBtn = $("saveOptions");
    saveBtn.disabled = false;
    saveBtn.textContent = "Save Changes";
    $("exportButton").disabled = true;
  };

  $("showCommands").onclick = function(event) {
    var node, root = DomUtils.UI.root;
    event && event.preventDefault();
    if (root && (node = root.querySelector('.HelpCommandName'))) {
      node.click();
      return;
    }
    MainPort.sendMessage({
      handler: "initHelp",
      unbound: true,
      names: true,
      title: "Command Listing"
    }, function(response) {
      var node, root = DomUtils.UI.root;
      if (root && (node = root.getElementById("HelpDialog"))) {
        MainPort.Listener({
          name: "execute",
          command: "showHelp",
          count: 1,
          options: {}
        });
      }
      MainPort.Listener(response);
    });
  };

  saveOptions = function(virtually) {
    var btn = $("saveOptions"), toSync;
    if (virtually !== false) {
      Option.saveOptions();
    }
    toSync = Option.syncToFrontend;
    Option.syncToFrontend = [];
    btn.disabled = true;
    btn.textContent = "No Changes";
    $("exportButton").disabled = false;
    status = 0;
    setTimeout(function () {
      var event = new FocusEvent("focus"), i, key, ref, obj;
      window.dispatchEvent(event);
      i = toSync.length;
      if (i === 0) { return; }
      ref = bgSettings.bufferToLoad;
      obj = {name: "settingsUpdate"};
      while (0 <= --i) {
        key = toSync[i];
        obj[key] = ref[key] = bgSettings.get(key);
      }
      bgSettings.postUpdate("broadcast", obj);
    }, 100);
  };
  $("saveOptions").onclick = saveOptions;

  _ref = document.getElementsByClassName("nonEmptyTextOption");
  for (_i = _ref.length; 0 <= --_i; ) {
    element = _ref[_i];
    element.className = element.className + " example info";
    element.textContent = "Leave empty to reset this option.";
  }

  window.onbeforeunload = function() {
    if (status !== 0 && Option.needSaveOptions()) {
      return "You have unsaved changes to options.";
    }
  };
  document.addEventListener("keyup", function(event) {
    if ((event.ctrlKey || event.metaKey) && event.keyCode === 13) {
      document.activeElement.blur();
      if (status != 0) {
        saveOptions();
      }
    }
  });

  _ref = document.querySelectorAll("[data-model]");
  for (_i = _ref.length; 0 <= --_i; ) {
    element = _ref[_i];
    type = window[element.getAttribute("data-model") + "Option"];
    new type(element, onUpdated);
  }

  advancedMode = bgSettings.get("showAdvancedOptions");
  element = $("advancedOptionsButton");
  element.onclick = function(_0, init) {
    if (init == null || (init === "hash" && advancedMode === false)) {
      advancedMode = !advancedMode;
      bgSettings.set("showAdvancedOptions", advancedMode);
    }
    if (advancedMode) {
      $("advancedOptions").style.display = "";
      this.textContent = "Hide Advanced Options";
    } else {
      $("advancedOptions").style.display = "none";
      this.textContent = "Show Advanced Options";
    }
  };
  element.onclick(null, true);

  element = null;
})();

var formatDate = function(time) {
  return new Date(time - new Date().getTimezoneOffset() * 1000 * 60
    ).toJSON().substring(0, 19).replace('T', ' ');
};

$("exportButton").onclick = function() {
  var exported_object, exported_data, file_name, force2, d, nodeA;
  exported_object = Object.create(null);
  exported_object.name = "Vimium++";
  exported_object.time = 0;
  (function() {
    var storage = localStorage, i, len, key, mark_head, all = bgSettings.defaults
      , strArr = bgSettings.NonJSON, arr1;
    mark_head = BG.Marks.getMarkKey("");
    for (i = 0, len = storage.length; i < len; i++) {
      key = storage.key(i);
      if (key === "name" || key === "time" || key.startsWith(mark_head)) {
        continue;
      }
      exported_object[key] = (key in strArr) && storage.getItem(key).indexOf("\n") > 0
        ? storage.getItem(key).split("\n")
        : (key in all) ? bgSettings.get(key) : storage.getItem(key);
    }
  })();
  delete exported_object.findModeRawQuery;
  delete exported_object.newTabUrl_f;
  d = new Date();
  exported_object.time = d.getTime();
  exported_data = JSON.stringify(exported_object, null, '\t');
  exported_object = null;
  force2 = function(i) { return ((i <= 9) ? '0'  : '') + i; }
  file_name = 'vimium++_' + d.getFullYear() + force2(d.getMonth() + 1) + force2(d.getDate())
    + '_' + force2(d.getHours()) + force2(d.getMinutes()) + force2(d.getSeconds()) + '.json';

  nodeA = document.createElement("a");
  nodeA.download = file_name;
  nodeA.href = URL.createObjectURL(new Blob([exported_data]));
  nodeA.click();
  URL.revokeObjectURL(nodeA.href);
  console.log("EXPORT settings to", file_name, "at", formatDate(d));
};

var importSettings = function(time, event) {
  var new_data, fileReader = event.target;
  try {
    new_data = JSON.parse(fileReader.result);
    time = new_data.time < 0 ? time : (new_data.time || 0);
  } catch (e) {}
  if (!new_data || new_data.name !== "Vimium++" || (time < 10000 && time > 0)) {
    VHUD.showForDuration("No settings data found!", 2000);
    return;
  } else if (!confirm(
    "You are loading a settings copy exported" + (time ? " at:\n        "
    + formatDate(time) : " before.")
    + "\n\nAre you sure you want to continue?"
  )) {
    VHUD.showForDuration("You cancelled importing.", 1000);
    return;
  }

  var storage = localStorage, i, key, new_value, func, all = bgSettings.defaults
    , strArr = bgSettings.NonJSON;
  func = function(val) {
    return typeof val !== "string" || val.length <= 72 ? val
      : val.substring(0, 68).trimRight() + " ...";
  };
  console.log("IMPORT settings at", new Date(time));
  delete new_data.name;
  delete new_data.time;
  Object.setPrototypeOf(new_data, null);
  for (i = storage.length; 0 <= --i; ) {
    key = storage.key(i);
    if (!(key in new_data)) {
      new_data[key] = null;
    }
  }
  delete new_data.findModeRawQuery;
  delete new_data.newTabUrl_f;
  Option.all.forEach(function(item) {
    var key = item.field, new_value = new_data[key];
    delete new_data[key];
    if (new_value == null) {
      // NOTE: we assume all nullable settings have the same default value: null
      new_value = all[key];
    } else if (new_value.join && (key in strArr)) {
      new_value = new_value.join("\n");
    }
    if (!item.areEqual(bgSettings.get(key), new_value)) {
      console.log("import", key, func(new_value));
      bgSettings.set(key, new_value);
      if (key in bgSettings.bufferToLoad) {
        Option.syncToFrontend.push(key);
      }
    }
    item.fetch();
  });
  for (key in new_data) {
    new_value = new_data[key];
    if (new_value == null) {
      if (key in all) {
        new_value = all[key];
        if (bgSettings.get(key) !== new_value) {
          bgSettings.set(key, new_value);
          console.log("reset", key, func(new_value));
          continue;
        }
        new_value = bgSettings.get(key);
      } else {
        new_value = storage.getItem(key);
      }
      storage.removeItem(key);
      console.log("remove", key, ":=", func(new_value));
      continue;
    }
    if (new_value.join && (key in strArr)) {
      new_value = new_value.join("\n");
    }
    if (key in all) {
      if (bgSettings.get(key) !== new_value) {
        bgSettings.set(key, new_value);
        console.log("update", key, func(new_value));
      }
    } else {
      storage.setItem(key, new_value);
      console.log("save", key, func(new_value));
    }
  }
  var btn = $("saveOptions");
  btn.onclick(false);
  VHUD.showForDuration("Import settings data: OK!", 1000);
};

$("settingsFile").onchange = function() {
  var file = this.files[0], reader;
  this.value = "";
  if (!file) { return; }
  reader = new FileReader();
  reader.onload = importSettings.bind(null, file.lastModified);
  reader.readAsText(file);
};
$("importButton").onclick = function() {
  $("settingsFile").click();
};

(function() {
  var arr = document.querySelectorAll("[data-auto-scale]"), i, func;
  func = function() {
    var target = $(this.getAttribute("data-auto-scale")), delta;
    if (target.scrollHeight <= target.clientHeight) { return; }
    target.style.maxWidth = Math.min(window.innerWidth, 1024) - 120 + "px";
    delta = target.offsetHeight - target.clientHeight;
    target.style.width = target.scrollWidth + 3 +
      (target.offsetWidth - target.clientWidth) + "px";
    target.style.height = target.scrollHeight + 20 + delta + "px";
  };
  for (i = arr.length; 0 <= --i; ) {
    arr[i].onclick = func;
  }
})();

BG.Commands.setStrict && BG.Commands.setStrict(KeyRe.source);

(function() {
  var onhash = function(event) {
    var hash = window.location.hash.substring(1), node;
    event && event.preventDefault();
    if (hash && (node = document.querySelector('[data-hash="' + hash + '"]'))) {
      node.onclick && node.onclick(null, "hash");
    }
  }
  window.addEventListener("hashchange", onhash);
  if (window.location.hash.length <= 4) { return; }
  window.onload = function() {
    window.onload = null;
    setTimeout(onhash, 33);
  };
})();
<commit_msg>populateElement: don't need to return anything<commit_after>"use strict";

Option.saveOptions = function() {
  for (var arr = Option.all, i = arr.length; 0 <= --i; ) {
    arr[i].saved || arr[i].save();
  }
};

Option.needSaveOptions = function() {
  for (var arr = Option.all, i = arr.length; 0 <= --i; ) {
    if (!arr[i].saved) {
      return true;
    }
  }
  return false;
};

Option.prototype.areEqual = function(a, b) {
  return this.saved = a === b;
};

function NumberOption() {
  NumberOption.__super__.constructor.apply(this, arguments);
  this.element.addEventListener("input", this.onUpdated);
}
__extends(NumberOption, Option);

NumberOption.prototype.populateElement = function(value) {
  this.element.value = value;
};

NumberOption.prototype.readValueFromElement = function() {
  return parseFloat(this.element.value);
};

function TextOption() {
  TextOption.__super__.constructor.apply(this, arguments);
  this.element.addEventListener("input", this.onUpdated);
}
__extends(TextOption, Option);

TextOption.prototype.headWhiteRe = /\n /g;
TextOption.prototype.whiteMaskRe = /\xa0/g;
TextOption.prototype.populateElement = function(value) {
  this.element.value = value.replace(this.headWhiteRe, '\n\xa0');
};

TextOption.prototype.readValueFromElement = function() {
  return this.element.value.trim().replace(this.whiteMaskRe, ' ');
};

function NonEmptyTextOption(element) {
  NonEmptyTextOption.__super__.constructor.apply(this, arguments);
}
__extends(NonEmptyTextOption, TextOption);

NonEmptyTextOption.prototype.readValueFromElement = function() {
  var value = NonEmptyTextOption.__super__.readValueFromElement.call(this);
  if (!value) {
    value = bgSettings.defaults[this.field];
    this.populateElement(value);
  }
  return value;
};

function JSONOption() {
  JSONOption.__super__.constructor.apply(this, arguments);
}
__extends(JSONOption, TextOption);

JSONOption.prototype.populateElement = function(obj) {
  JSONOption.__super__.populateElement.call(this, JSON.stringify(obj, null, 2));
};

JSONOption.prototype.readValueFromElement = function() {
  var value = JSONOption.__super__.readValueFromElement.call(this), obj;
  if (value) {
    try {
      obj = JSON.parse(value);
    } catch (e) {
      obj = null;
    }
  } else {
    obj = bgSettings.defaults[this.field];
    this.populateElement(obj);
  }
  return obj;
};

JSONOption.prototype.areEqual = Option.areJSONEqual;

function CheckBoxOption() {
  CheckBoxOption.__super__.constructor.apply(this, arguments);
  this.element.addEventListener("change", this.onUpdated);
}
__extends(CheckBoxOption, Option);

CheckBoxOption.prototype.populateElement = function(value) {
  this.element.checked = value;
};

CheckBoxOption.prototype.readValueFromElement = function() {
  return this.element.checked;
};

(function() {
  var advancedMode, element, name, onUpdated, saveOptions, type, _i, _ref, status = 0;

  onUpdated = function() {
    var saveBtn;
    if (this.areEqual(this.readValueFromElement(), this.previous)) {
      if (status == 1 && !Option.needSaveOptions()) {
        saveBtn = $("saveOptions");
        saveBtn.disabled = true;
        saveBtn.textContent = "No Changes";
        $("exportButton").disabled = false;
        status = 0;
      }
      return;
    } else if (status == 1) {
      return;
    }
    status = 1;
    saveBtn = $("saveOptions");
    saveBtn.disabled = false;
    saveBtn.textContent = "Save Changes";
    $("exportButton").disabled = true;
  };

  $("showCommands").onclick = function(event) {
    var node, root = DomUtils.UI.root;
    event && event.preventDefault();
    if (root && (node = root.querySelector('.HelpCommandName'))) {
      node.click();
      return;
    }
    MainPort.sendMessage({
      handler: "initHelp",
      unbound: true,
      names: true,
      title: "Command Listing"
    }, function(response) {
      var node, root = DomUtils.UI.root;
      if (root && (node = root.getElementById("HelpDialog"))) {
        MainPort.Listener({
          name: "execute",
          command: "showHelp",
          count: 1,
          options: {}
        });
      }
      MainPort.Listener(response);
    });
  };

  saveOptions = function(virtually) {
    var btn = $("saveOptions"), toSync;
    if (virtually !== false) {
      Option.saveOptions();
    }
    toSync = Option.syncToFrontend;
    Option.syncToFrontend = [];
    btn.disabled = true;
    btn.textContent = "No Changes";
    $("exportButton").disabled = false;
    status = 0;
    setTimeout(function () {
      var event = new FocusEvent("focus"), i, key, ref, obj;
      window.dispatchEvent(event);
      i = toSync.length;
      if (i === 0) { return; }
      ref = bgSettings.bufferToLoad;
      obj = {name: "settingsUpdate"};
      while (0 <= --i) {
        key = toSync[i];
        obj[key] = ref[key] = bgSettings.get(key);
      }
      bgSettings.postUpdate("broadcast", obj);
    }, 100);
  };
  $("saveOptions").onclick = saveOptions;

  _ref = document.getElementsByClassName("nonEmptyTextOption");
  for (_i = _ref.length; 0 <= --_i; ) {
    element = _ref[_i];
    element.className = element.className + " example info";
    element.textContent = "Leave empty to reset this option.";
  }

  window.onbeforeunload = function() {
    if (status !== 0 && Option.needSaveOptions()) {
      return "You have unsaved changes to options.";
    }
  };
  document.addEventListener("keyup", function(event) {
    if ((event.ctrlKey || event.metaKey) && event.keyCode === 13) {
      document.activeElement.blur();
      if (status != 0) {
        saveOptions();
      }
    }
  });

  _ref = document.querySelectorAll("[data-model]");
  for (_i = _ref.length; 0 <= --_i; ) {
    element = _ref[_i];
    type = window[element.getAttribute("data-model") + "Option"];
    new type(element, onUpdated);
  }

  advancedMode = bgSettings.get("showAdvancedOptions");
  element = $("advancedOptionsButton");
  element.onclick = function(_0, init) {
    if (init == null || (init === "hash" && advancedMode === false)) {
      advancedMode = !advancedMode;
      bgSettings.set("showAdvancedOptions", advancedMode);
    }
    if (advancedMode) {
      $("advancedOptions").style.display = "";
      this.textContent = "Hide Advanced Options";
    } else {
      $("advancedOptions").style.display = "none";
      this.textContent = "Show Advanced Options";
    }
  };
  element.onclick(null, true);

  element = null;
})();

var formatDate = function(time) {
  return new Date(time - new Date().getTimezoneOffset() * 1000 * 60
    ).toJSON().substring(0, 19).replace('T', ' ');
};

$("exportButton").onclick = function() {
  var exported_object, exported_data, file_name, force2, d, nodeA;
  exported_object = Object.create(null);
  exported_object.name = "Vimium++";
  exported_object.time = 0;
  (function() {
    var storage = localStorage, i, len, key, mark_head, all = bgSettings.defaults
      , strArr = bgSettings.NonJSON, arr1;
    mark_head = BG.Marks.getMarkKey("");
    for (i = 0, len = storage.length; i < len; i++) {
      key = storage.key(i);
      if (key === "name" || key === "time" || key.startsWith(mark_head)) {
        continue;
      }
      exported_object[key] = (key in strArr) && storage.getItem(key).indexOf("\n") > 0
        ? storage.getItem(key).split("\n")
        : (key in all) ? bgSettings.get(key) : storage.getItem(key);
    }
  })();
  delete exported_object.findModeRawQuery;
  delete exported_object.newTabUrl_f;
  d = new Date();
  exported_object.time = d.getTime();
  exported_data = JSON.stringify(exported_object, null, '\t');
  exported_object = null;
  force2 = function(i) { return ((i <= 9) ? '0'  : '') + i; }
  file_name = 'vimium++_' + d.getFullYear() + force2(d.getMonth() + 1) + force2(d.getDate())
    + '_' + force2(d.getHours()) + force2(d.getMinutes()) + force2(d.getSeconds()) + '.json';

  nodeA = document.createElement("a");
  nodeA.download = file_name;
  nodeA.href = URL.createObjectURL(new Blob([exported_data]));
  nodeA.click();
  URL.revokeObjectURL(nodeA.href);
  console.log("EXPORT settings to", file_name, "at", formatDate(d));
};

var importSettings = function(time, event) {
  var new_data, fileReader = event.target;
  try {
    new_data = JSON.parse(fileReader.result);
    time = new_data.time < 0 ? time : (new_data.time || 0);
  } catch (e) {}
  if (!new_data || new_data.name !== "Vimium++" || (time < 10000 && time > 0)) {
    VHUD.showForDuration("No settings data found!", 2000);
    return;
  } else if (!confirm(
    "You are loading a settings copy exported" + (time ? " at:\n        "
    + formatDate(time) : " before.")
    + "\n\nAre you sure you want to continue?"
  )) {
    VHUD.showForDuration("You cancelled importing.", 1000);
    return;
  }

  var storage = localStorage, i, key, new_value, func, all = bgSettings.defaults
    , strArr = bgSettings.NonJSON;
  func = function(val) {
    return typeof val !== "string" || val.length <= 72 ? val
      : val.substring(0, 68).trimRight() + " ...";
  };
  console.log("IMPORT settings at", new Date(time));
  delete new_data.name;
  delete new_data.time;
  Object.setPrototypeOf(new_data, null);
  for (i = storage.length; 0 <= --i; ) {
    key = storage.key(i);
    if (!(key in new_data)) {
      new_data[key] = null;
    }
  }
  delete new_data.findModeRawQuery;
  delete new_data.newTabUrl_f;
  Option.all.forEach(function(item) {
    var key = item.field, new_value = new_data[key];
    delete new_data[key];
    if (new_value == null) {
      // NOTE: we assume all nullable settings have the same default value: null
      new_value = all[key];
    } else if (new_value.join && (key in strArr)) {
      new_value = new_value.join("\n");
    }
    if (!item.areEqual(bgSettings.get(key), new_value)) {
      console.log("import", key, func(new_value));
      bgSettings.set(key, new_value);
      if (key in bgSettings.bufferToLoad) {
        Option.syncToFrontend.push(key);
      }
    }
    item.fetch();
  });
  for (key in new_data) {
    new_value = new_data[key];
    if (new_value == null) {
      if (key in all) {
        new_value = all[key];
        if (bgSettings.get(key) !== new_value) {
          bgSettings.set(key, new_value);
          console.log("reset", key, func(new_value));
          continue;
        }
        new_value = bgSettings.get(key);
      } else {
        new_value = storage.getItem(key);
      }
      storage.removeItem(key);
      console.log("remove", key, ":=", func(new_value));
      continue;
    }
    if (new_value.join && (key in strArr)) {
      new_value = new_value.join("\n");
    }
    if (key in all) {
      if (bgSettings.get(key) !== new_value) {
        bgSettings.set(key, new_value);
        console.log("update", key, func(new_value));
      }
    } else {
      storage.setItem(key, new_value);
      console.log("save", key, func(new_value));
    }
  }
  var btn = $("saveOptions");
  btn.onclick(false);
  VHUD.showForDuration("Import settings data: OK!", 1000);
};

$("settingsFile").onchange = function() {
  var file = this.files[0], reader;
  this.value = "";
  if (!file) { return; }
  reader = new FileReader();
  reader.onload = importSettings.bind(null, file.lastModified);
  reader.readAsText(file);
};
$("importButton").onclick = function() {
  $("settingsFile").click();
};

(function() {
  var arr = document.querySelectorAll("[data-auto-scale]"), i, func;
  func = function() {
    var target = $(this.getAttribute("data-auto-scale")), delta;
    if (target.scrollHeight <= target.clientHeight) { return; }
    target.style.maxWidth = Math.min(window.innerWidth, 1024) - 120 + "px";
    delta = target.offsetHeight - target.clientHeight;
    target.style.width = target.scrollWidth + 3 +
      (target.offsetWidth - target.clientWidth) + "px";
    target.style.height = target.scrollHeight + 20 + delta + "px";
  };
  for (i = arr.length; 0 <= --i; ) {
    arr[i].onclick = func;
  }
})();

BG.Commands.setStrict && BG.Commands.setStrict(KeyRe.source);

(function() {
  var onhash = function(event) {
    var hash = window.location.hash.substring(1), node;
    event && event.preventDefault();
    if (hash && (node = document.querySelector('[data-hash="' + hash + '"]'))) {
      node.onclick && node.onclick(null, "hash");
    }
  }
  window.addEventListener("hashchange", onhash);
  if (window.location.hash.length <= 4) { return; }
  window.onload = function() {
    window.onload = null;
    setTimeout(onhash, 33);
  };
})();
<|endoftext|>


<commit_before>import {teammemberTemplate} from "./templates"
import {deleteMemberDialog} from "./manage"
import {addDropdownBox, postJson, addAlert, OverviewMenuView} from "../common"
import {SiteMenu} from "../menu"
import {menuModel} from "./menu"

export class ContactsOverview {
    constructor() {
        let smenu = new SiteMenu("") // Nothing highlighted.
        smenu.init()
        this.menu = new OverviewMenuView(this, menuModel)
        this.menu.init()
        this.bind()
        this.getList()
    }

    getList() {

        postJson('/user/team/list/').then(
            json => {
                jQuery('#team-table tbody').append(teammemberTemplate({members: json.team_members}))
            }
        ).catch(
            () => addAlert('error', gettext('Could not obtain contacts list'))
        )
    }

    bind() {
        jQuery(document).ready(function() {

            //delete single user
            jQuery(document).on('click', '.delete-single-member', function() {
                deleteMemberDialog([jQuery(this).attr('data-id')])
            })

        })
    }

    // get IDs of selected contacts
    getSelected() {
        return [].slice.call(
            document.querySelectorAll('.entry-select:checked:not(:disabled)')
        ).map(el => parseInt(el.getAttribute('data-id')))
    }

}
<commit_msg>remove some jQuery<commit_after>import {teammemberTemplate} from "./templates"
import {deleteMemberDialog} from "./manage"
import {addDropdownBox, postJson, addAlert, OverviewMenuView} from "../common"
import {SiteMenu} from "../menu"
import {menuModel} from "./menu"

export class ContactsOverview {
    constructor() {
        let smenu = new SiteMenu("") // Nothing highlighted.
        smenu.init()
        this.menu = new OverviewMenuView(this, menuModel)
        this.menu.init()
        this.bind()
        this.getList()
    }

    getList() {

        postJson('/user/team/list/').then(
            json => {
                document.querySelector('#team-table tbody').innerHTML += teammemberTemplate({members: json.team_members})
            }
        ).catch(
            () => addAlert('error', gettext('Could not obtain contacts list'))
        )
    }

    bind() {
        jQuery(document).ready(function() {

            //delete single user
            jQuery(document).on('click', '.delete-single-member', function() {
                deleteMemberDialog([jQuery(this).attr('data-id')])
            })

        })
    }

    // get IDs of selected contacts
    getSelected() {
        return [].slice.call(
            document.querySelectorAll('.entry-select:checked:not(:disabled)')
        ).map(el => parseInt(el.getAttribute('data-id')))
    }

}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// @flow

import * as React from 'react';
import classNames from 'classnames';
import {
  formatNumber,
  formatPercent,
  formatBytes,
  formatMicroseconds,
  formatMilliseconds,
  formatValueTotal,
} from '../../utils/format-numbers';
import explicitConnect from '../../utils/connect';
import { selectorsForThread } from '../../reducers/profile-view';
import { getImplementationFilter } from '../../reducers/url-state';

import Backtrace from './Backtrace';

import { bailoutTypeInformation } from '../../profile-logic/marker-info';
import type { TracingMarker } from '../../types/profile-derived';
import type { NotVoidOrNull } from '../../types/utils';
import type { ImplementationFilter } from '../../types/actions';
import type { Thread, ThreadIndex } from '../../types/profile';
import type {
  DOMEventMarkerPayload,
  PaintProfilerMarkerTracing,
  StyleMarkerPayload,
} from '../../types/markers';
import type {
  ExplicitConnectOptions,
  ConnectedProps,
} from '../../utils/connect';

function _markerDetail<T: NotVoidOrNull>(
  key: string,
  label: string,
  value: T,
  fn: T => string = String
): React.Node {
  return [

      {label}:

,
    fn(value),
  ];
}

function _markerDetailNullable<T: NotVoidOrNull>(
  key: string,
  label: string,
  value: T | void | null,
  fn: T => string = String
): React.Node {
  if (value === undefined || value === null) {
    return null;
  }
  return _markerDetail(key, label, value, fn);
}

function _markerDetailDeltaTimeNullable(
  key: string,
  label: string,
  value1?: number,
  value2?: number
): React.Node {
  if (
    value1 === undefined ||
    value2 === undefined ||
    value1 === null ||
    value2 === null
  ) {
    return null;
  }
  return _markerDetail(key, label, value1 - value2);
}

function _markerBacktrace(
  marker: TracingMarker,
  data: StyleMarkerPayload | PaintProfilerMarkerTracing | DOMEventMarkerPayload,
  thread: Thread,
  implementationFilter: ImplementationFilter
): React.Node {
  if (data.category === 'DOMEvent') {
    const latency =
      data.timeStamp === undefined
        ? null
        : formatMilliseconds(marker.start - data.timeStamp);
    return (

        {_markerDetail('type', 'Type', data.eventType)}
        {latency === null ? null : _markerDetail('latency', 'Latency', latency)}

    );
  }
  if ('cause' in data && data.cause) {
    const { cause } = data;
    const causeAge = marker.start - cause.time;
    return (

          First invalidated {formatNumber(causeAge)}ms before the flush, at:

        <Backtrace
          cause={cause}
          thread={thread}
          implementationFilter={implementationFilter}
        />

    );
  }
  return null;
}

function getMarkerDetails(
  marker: TracingMarker,
  thread: Thread,
  implementationFilter: ImplementationFilter
): React.Node {
  const data = marker.data;
  if (data) {
    switch (data.type) {
      case 'UserTiming': {
        return (

            {_markerDetail('name', 'Name', data.name)}

        );
      }
      case 'GCMinor': {
        if (data.nursery) {
          const nursery = data.nursery;
          switch (nursery.status) {
            case 'complete': {
              return (

                  {_markerDetail('gcreason', 'Reason', nursery.reason)}
                  {_markerDetail(
                    'gcpromotion',
                    'Bytes tenured',
                    formatValueTotal(
                      nursery.bytes_tenured,
                      nursery.bytes_used,
                      formatBytes
                    )
                  )}
                  {nursery.cur_capacity === undefined
                    ? null
                    : _markerDetail(
                        'gcnurseryusage',
                        'Bytes used',
                        formatValueTotal(
                          nursery.bytes_used,
                          nursery.cur_capacity,
                          formatBytes
                        )
                      )}
                  {nursery.new_capacity === undefined
                    ? null
                    : _markerDetail(
                        'gcnewnurserysize',
                        'New nursery size',
                        nursery.new_capacity,
                        formatBytes
                      )}
                  {nursery.lazy_capacity === undefined
                    ? null
                    : _markerDetail(
                        'gclazynurserysize',
                        'Lazy-allocated size',
                        nursery.lazy_capacity,
                        formatBytes
                      )}
                  {nursery.chunk_alloc_us === undefined
                    ? null
                    : _markerDetail(
                        'gctimeinchunkalloc',
                        'Time spent allocating chunks in mutator',
                        nursery.chunk_alloc_us,
                        formatMicroseconds
                      )}

              );
            }
            case 'nursery disabled':
              return (

                  {_markerDetail('gcstatus', 'Status', 'Nursery disabled')}

              );
            case 'nursery empty':
              return (

                  {_markerDetail('gcstatus', 'Status', 'Nursery empty')}

              );
            default:
              return null;
          }
        } else {
          return null;
        }
      }
      case 'GCMajor': {
        const timings = data.timings;
        switch (timings.status) {
          case 'aborted':
            return (

                {_markerDetail('status', 'Status', 'Aborted (OOM)')}

            );
          case 'completed': {
            let nonIncrementalReason;
            if (
              timings.nonincremental_reason &&
              timings.nonincremental_reason !== 'None'
            ) {
              nonIncrementalReason = _markerDetail(
                'gcnonincrementalreason',
                'Non-incremental reason',
                timings.nonincremental_reason
              );
            }
            return (

                {_markerDetail('gcreason', 'Reason', timings.reason)}
                {nonIncrementalReason}
                {_markerDetail(
                  'gctime',
                  'Total slice times',
                  timings.total_time,
                  x =>
                    formatMilliseconds(
                      x,
                      /* significantDigits */ 3,
                      /* maxFractionalDigits */ 2
                    )
                )}
                {_markerDetail(
                  'gcmaxpause',
                  'Max Pause',
                  timings.max_pause,
                  x =>
                    formatMilliseconds(
                      x,
                      /* significantDigits */ 3,
                      /* maxFractionalDigits */ 2
                    )
                )}
                {_markerDetail(
                  'gcusage',
                  'Heap usage',
                  timings.allocated_bytes,
                  formatBytes
                )}
                {_markerDetail(
                  'gcmmu20ms',
                  'MMU 20ms',
                  timings.mmu_20ms,
                  formatPercent
                )}
                {_markerDetail(
                  'gcmmu50ms',
                  'MMU 50ms',
                  timings.mmu_50ms,
                  formatPercent
                )}
                {_markerDetail('gcnumminors', 'Minor GCs', timings.minor_gcs)}
                {_markerDetail('gcnumslices', 'Slices', timings.slices)}
                {_markerDetail(
                  'gcnumzones',
                  'Zones',
                  formatValueTotal(
                    timings.zones_collected,
                    timings.total_zones,
                    String
                  )
                )}
                {_markerDetail(
                  'gcnumcompartments',
                  'Compartments',
                  timings.total_compartments
                )}

            );
          }
          default:
            return null;
        }
      }
      case 'GCSlice': {
        const timings = data.timings;
        let triggers;
        if (timings.trigger_amount && timings.trigger_threshold) {
          triggers = _markerDetail(
            'gctrigger',
            'Trigger (amt/trig)',
            formatValueTotal(
              timings.trigger_amount,
              timings.trigger_threshold,
              formatBytes,
              false
            )
          );
        }
        return (

            {_markerDetail('gcreason', 'Reason', timings.reason)}
            {_markerDetail('gcbudget', 'Budget', timings.budget)}
            {_markerDetail(
              'gcstate',
              'States',
              timings.initial_state + ' – ' + timings.final_state
            )}
            {triggers}
            {timings.page_faults === undefined
              ? null
              : _markerDetail('gcfaults', 'Page faults', timings.page_faults)}

        );
      }
      case 'Bailout': {
        return (

            {_markerDetail('bailoutType', 'Type', data.bailoutType)}
            {_markerDetail('where', 'Where', data.where)}
            {_markerDetail('script', 'Script', data.script)}
            {_markerDetail('functionLine', 'Function Line', data.functionLine)}
            {_markerDetail('bailoutLine', 'Bailout Line', data.bailoutLine)}

Description:

              {bailoutTypeInformation['Bailout_' + data.bailoutType]}

        );
      }
      case 'Invalidation': {
        return (

            {_markerDetail('url', 'URL', data.url)}
            {_markerDetail('line', 'Line', data.line)}

        );
      }
      case 'Network': {
        if (
          data.status !== 'STATUS_STOP' &&
          data.status !== 'STATUS_REDIRECT'
        ) {
          return (

              {_markerDetailNullable('url', 'URL', data.URI)}
              {_markerDetail('pri', 'pri', data.pri)}
              {_markerDetailNullable('count', 'count', data.count)}
              {_markerDetail('status', 'Status', data.status)}

          );
        } else {
          return (

              {_markerDetail('status', 'Status', data.status)}
              {_markerDetailNullable('url', 'URL', data.URI)}
              {_markerDetailNullable(
                'redirect_url',
                'Redirect URL',
                data.RedirectURI
              )}
              {_markerDetail('pri', 'pri', data.pri)}
              {_markerDetailNullable('count', 'count', data.count)}
              {_markerDetailDeltaTimeNullable(
                'domainLookup',
                'domainLookup',
                data.domainLookupEnd,
                data.domainLookupStart
              )}
              {_markerDetailDeltaTimeNullable(
                'tcpConnect',
                'tcpConnect',
                data.tcpConnectEnd,
                data.connectStart
              )}
              {_markerDetailNullable(
                'secureConnectionStart',
                'secureConnectionStart',
                data.secureConnectionStart
              )}
              {_markerDetailDeltaTimeNullable(
                'connect',
                'connect',
                data.connectEnd,
                data.connectStart
              )}
              {_markerDetailDeltaTimeNullable(
                'requestStart',
                'requestStart @',
                data.requestStart,
                data.startTime
              )}
              {_markerDetailDeltaTimeNullable(
                'response',
                'response',
                data.responseEnd,
                data.responseStart
              )}

          );
        }
      }
      case 'Styles': {
        return [

            {_markerDetail(
              'elementsTraversed',
              'Elements traversed',
              data.elementsTraversed
            )}
            {_markerDetail(
              'elementsStyled',
              'Elements styled',
              data.elementsStyled
            )}
            {_markerDetail(
              'elementsMatched',
              'Elements matched',
              data.elementsMatched
            )}
            {_markerDetail('stylesShared', 'Styles shared', data.stylesShared)}
            {_markerDetail('stylesReused', 'Styles reused', data.stylesReused)}

,
          _markerBacktrace(marker, data, thread, implementationFilter),
        ];
      }
      case 'tracing': {
        return _markerBacktrace(marker, data, thread, implementationFilter);
      }
      default:
    }
  }
  return null;
}

type OwnProps = {|
  +marker: TracingMarker,
  +threadIndex: ThreadIndex,
  +className?: string,
|};

type StateProps = {|
  +threadName?: string,
  +thread: Thread,
  +implementationFilter: ImplementationFilter,
|};

type Props = ConnectedProps<OwnProps, StateProps, {||}>;

class MarkerTooltipContents extends React.PureComponent<Props> {
  render() {
    const {
      marker,
      className,
      threadName,
      thread,
      implementationFilter,
    } = this.props;
    const details = getMarkerDetails(marker, thread, implementationFilter);

    return (

              {/* tracing markers with no start have a negative start, while the
                ones with no end have an infinite duration */}
              {Number.isFinite(marker.dur) && marker.start >= 0
                ? formatNumber(marker.dur) + 'ms'
                : 'unknown duration'}

{marker.title || marker.name}

          {threadName ? (

Thread:

              {threadName}

          ) : null}

        {details}

    );
  }
}

const options: ExplicitConnectOptions<OwnProps, StateProps, {||}> = {
  mapStateToProps: (state, props) => {
    const { threadIndex } = props;
    const selectors = selectorsForThread(threadIndex);
    const threadName = selectors.getFriendlyThreadName(state);
    const thread = selectors.getThread(state);
    const implementationFilter = getImplementationFilter(state);
    return {
      threadName,
      thread,
      implementationFilter,
    };
  },
  component: MarkerTooltipContents,
};

export default explicitConnect(options);
<commit_msg>Add phase times to Garbage Collector markers tooltips (Merge PR #841)<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// @flow

import * as React from 'react';
import classNames from 'classnames';
import {
  formatNumber,
  formatPercent,
  formatBytes,
  formatMicroseconds,
  formatMilliseconds,
  formatValueTotal,
} from '../../utils/format-numbers';
import explicitConnect from '../../utils/connect';
import { selectorsForThread } from '../../reducers/profile-view';
import { getImplementationFilter } from '../../reducers/url-state';

import Backtrace from './Backtrace';

import { bailoutTypeInformation } from '../../profile-logic/marker-info';
import type { Microseconds } from '../../types/units';
import type { TracingMarker } from '../../types/profile-derived';
import type { NotVoidOrNull } from '../../types/utils';
import type { ImplementationFilter } from '../../types/actions';
import type { Thread, ThreadIndex } from '../../types/profile';
import type {
  DOMEventMarkerPayload,
  PaintProfilerMarkerTracing,
  PhaseTimes,
  StyleMarkerPayload,
} from '../../types/markers';
import type {
  ExplicitConnectOptions,
  ConnectedProps,
} from '../../utils/connect';

function _markerDetail<T: NotVoidOrNull>(
  key: string,
  label: string,
  value: T,
  fn: T => string = String
): React.Node {
  return [

      {label}:

,
    fn(value),
  ];
}

function _markerDetailNullable<T: NotVoidOrNull>(
  key: string,
  label: string,
  value: T | void | null,
  fn: T => string = String
): React.Node {
  if (value === undefined || value === null) {
    return null;
  }
  return _markerDetail(key, label, value, fn);
}

function _markerDetailDeltaTimeNullable(
  key: string,
  label: string,
  value1?: number,
  value2?: number
): React.Node {
  if (
    value1 === undefined ||
    value2 === undefined ||
    value1 === null ||
    value2 === null
  ) {
    return null;
  }
  return _markerDetail(key, label, value1 - value2);
}

type PhaseTimeTuple = {| name: string, time: Microseconds |};

function _markerDetailPhase(p: PhaseTimeTuple): React.Node {
  return _markerDetail(
    'gcphase' + p.name,
    'Phase ' + p.name,
    p.time,
    t => formatNumber(t / 1000) + 'ms'
  );
}

function _makePhaseTimesArray(
  phases: PhaseTimes<Microseconds>
): Array<PhaseTimeTuple> {
  const array = [];
  for (const phase in phases) {
    /*
     * The "Total" entry is the total of all phases, it's not needed because
     * the total time is displayed on the marker tooltip (and available in
     * the marker data) directly.
     */
    if (phase !== 'Total') {
      array.push({ name: phase, time: phases[phase] });
    }
  }
  return array;
}

/*
 * Return true if the phase 'phaseName' is a leaf phase among the whole
 * array of phases.
 *
 * A leaf phase is a phase with no sub-phases.
 *
 * If the following are phases:
 * marking.mark_roots
 * marking.mark_heap
 * marking.mark_heap.a
 * sweeping.sweep
 *
 * Then marking.mark_roots, marking.mark_heap.a, sweeping.sweep are the only
 * leaves.  We select these since they will give the person looking at the
 * profile the best clue about which (sub-)phases are taking the longest.
 * For example, it isn't useful to say "sweeping took 200ms" but it is
 * useful to say "sweeping.compacting took 20ms" (if compacting has no
 * sub-phases.
 *
 * We find leaf phases by constructing a tree of phase times and then
 * reading its leaves.
 */

type PhaseTreeNode = {|
  value?: PhaseTimeTuple,
  branches: Map<string, PhaseTreeNode>,
|};

function _treeInsert(
  tree: Map<string, PhaseTreeNode>,
  path: Array<string>,
  phase: PhaseTimeTuple
) {
  const component = path.shift();
  if (component === undefined) {
    // This path is not a leaf, it can be ignored.
    return;
  }

  let node = tree.get(component);
  if (!node) {
    // Make a new node and grow the tree in this direction.
    node = { branches: new Map() };

    tree.set(component, node);
  }

  if (path.length > 0) {
    // There are more path components.  This node should be a branch if it
    // isn't one already.
    if (node.value) {
      // We delete the value to change this node from a leaf to a branch.
      delete node.value;
    }
    _treeInsert(node.branches, path, phase);
  } else {
    // Make the new node leaf node.
    if (node.value) {
      console.error(
        'Duplicate phases in _treeInsert in MarkerTooltipContents.js'
      );
      return;
    }
    node.value = phase;
  }
}

function _treeGetLeaves(
  tree: Map<string, PhaseTreeNode>
): Array<PhaseTimeTuple> {
  const leaves = [];
  for (const node of tree.values()) {
    if (node.value) {
      leaves.push(node.value);
    } else {
      leaves.push(..._treeGetLeaves(node.branches));
    }
  }
  return leaves;
}

function _filterInterestingPhaseTimes(
  rawPhases: PhaseTimes<Microseconds>,
  numSelect: number
): Array<PhaseTimeTuple> {
  let phaseTimes = _makePhaseTimesArray(rawPhases);

  /*
   * Select only the leaf phases.
   */
  const tree = new Map();
  for (const phase of phaseTimes) {
    const components = phase.name.split('.');
    _treeInsert(tree, components, phase);
  }
  phaseTimes = _treeGetLeaves(tree);

  /*
   * Of those N leaf phases, select the M most interesting phases by
   * determining the threshold we want to stop including phases at.
   *
   * Calculate the threshold by sorting the list of times in asscending
   * order, then slicing off all the low items and looking at the first
   * item.
   */
  const sortedPhaseTimes = phaseTimes
    .map(pt => pt.time)
    // Descending order
    .sort((a, b) => b - a);
  const threshold = sortedPhaseTimes[numSelect];

  /*
   * And then filtering the original list, which is in execution order which
   * we'd like to preserve, using the threshold.
   */
  return phaseTimes.filter(pt => pt.time > threshold);
}

function _markerBacktrace(
  marker: TracingMarker,
  data: StyleMarkerPayload | PaintProfilerMarkerTracing | DOMEventMarkerPayload,
  thread: Thread,
  implementationFilter: ImplementationFilter
): React.Node {
  if (data.category === 'DOMEvent') {
    const latency =
      data.timeStamp === undefined
        ? null
        : formatMilliseconds(marker.start - data.timeStamp);
    return (

        {_markerDetail('type', 'Type', data.eventType)}
        {latency === null ? null : _markerDetail('latency', 'Latency', latency)}

    );
  }
  if ('cause' in data && data.cause) {
    const { cause } = data;
    const causeAge = marker.start - cause.time;
    return (

          First invalidated {formatNumber(causeAge)}ms before the flush, at:

        <Backtrace
          cause={cause}
          thread={thread}
          implementationFilter={implementationFilter}
        />

    );
  }
  return null;
}

function getMarkerDetails(
  marker: TracingMarker,
  thread: Thread,
  implementationFilter: ImplementationFilter
): React.Node {
  const data = marker.data;

  if (data) {
    switch (data.type) {
      case 'UserTiming': {
        return (

            {_markerDetail('name', 'Name', data.name)}

        );
      }
      case 'GCMinor': {
        if (data.nursery) {
          const nursery = data.nursery;
          switch (nursery.status) {
            case 'complete': {
              return (

                  {_markerDetail('gcreason', 'Reason', nursery.reason)}
                  {_markerDetail(
                    'gcpromotion',
                    'Bytes tenured',
                    formatValueTotal(
                      nursery.bytes_tenured,
                      nursery.bytes_used,
                      formatBytes
                    )
                  )}
                  {nursery.cur_capacity === undefined
                    ? null
                    : _markerDetail(
                        'gcnurseryusage',
                        'Bytes used',
                        formatValueTotal(
                          nursery.bytes_used,
                          nursery.cur_capacity,
                          formatBytes
                        )
                      )}
                  {nursery.new_capacity === undefined
                    ? null
                    : _markerDetail(
                        'gcnewnurserysize',
                        'New nursery size',
                        nursery.new_capacity,
                        formatBytes
                      )}
                  {nursery.lazy_capacity === undefined
                    ? null
                    : _markerDetail(
                        'gclazynurserysize',
                        'Lazy-allocated size',
                        nursery.lazy_capacity,
                        formatBytes
                      )}
                  {nursery.chunk_alloc_us === undefined
                    ? null
                    : _markerDetail(
                        'gctimeinchunkalloc',
                        'Time spent allocating chunks in mutator',
                        nursery.chunk_alloc_us,
                        formatMicroseconds
                      )}
                  {_makePhaseTimesArray(nursery.phase_times)
                    /*
                     * Nursery collection should usually be very quick.  1ms
                     * is good and beyond 5ms and we could cause some
                     * animation to drop frames.  250us is about where
                     * things start to get interesting for a phase of a
                     * nursery collection.
                     */
                    .filter(pt => pt.time > 250) // 250us
                    .map(_markerDetailPhase)}

              );
            }
            case 'nursery disabled':
              return (

                  {_markerDetail('gcstatus', 'Status', 'Nursery disabled')}

              );
            case 'nursery empty':
              return (

                  {_markerDetail('gcstatus', 'Status', 'Nursery empty')}

              );
            default:
              return null;
          }
        } else {
          return null;
        }
      }
      case 'GCMajor': {
        const timings = data.timings;
        switch (timings.status) {
          case 'aborted':
            return (

                {_markerDetail('status', 'Status', 'Aborted (OOM)')}

            );
          case 'completed': {
            let nonIncrementalReason;
            if (
              timings.nonincremental_reason &&
              timings.nonincremental_reason !== 'None'
            ) {
              nonIncrementalReason = _markerDetail(
                'gcnonincrementalreason',
                'Non-incremental reason',
                timings.nonincremental_reason
              );
            }
            const phase_times = _filterInterestingPhaseTimes(
              timings.phase_times,
              6
            );
            return (

                {_markerDetail('gcreason', 'Reason', timings.reason)}
                {nonIncrementalReason}
                {_markerDetail(
                  'gctime',
                  'Total slice times',
                  timings.total_time,
                  x =>
                    formatMilliseconds(
                      x,
                      /* significantDigits */ 3,
                      /* maxFractionalDigits */ 2
                    )
                )}
                {_markerDetail(
                  'gcmaxpause',
                  'Max Pause',
                  timings.max_pause,
                  x =>
                    formatMilliseconds(
                      x,
                      /* significantDigits */ 3,
                      /* maxFractionalDigits */ 2
                    )
                )}
                {_markerDetail(
                  'gcusage',
                  'Heap usage',
                  timings.allocated_bytes,
                  formatBytes
                )}
                {_markerDetail(
                  'gcmmu20ms',
                  'MMU 20ms',
                  timings.mmu_20ms,
                  formatPercent
                )}
                {_markerDetail(
                  'gcmmu50ms',
                  'MMU 50ms',
                  timings.mmu_50ms,
                  formatPercent
                )}
                {_markerDetail('gcnumminors', 'Minor GCs', timings.minor_gcs)}
                {_markerDetail('gcnumslices', 'Slices', timings.slices)}
                {_markerDetail(
                  'gcnumzones',
                  'Zones',
                  formatValueTotal(
                    timings.zones_collected,
                    timings.total_zones,
                    String
                  )
                )}
                {_markerDetail(
                  'gcnumcompartments',
                  'Compartments',
                  timings.total_compartments
                )}
                {phase_times.map(_markerDetailPhase)}

            );
          }
          default:
            return null;
        }
      }
      case 'GCSlice': {
        const timings = data.timings;
        let triggers;
        if (timings.trigger_amount && timings.trigger_threshold) {
          triggers = _markerDetail(
            'gctrigger',
            'Trigger (amt/trig)',
            formatValueTotal(
              timings.trigger_amount,
              timings.trigger_threshold,
              formatBytes,
              false
            )
          );
        }
        const phase_times = _filterInterestingPhaseTimes(
          timings.phase_times,
          6
        );
        return (

            {_markerDetail('gcreason', 'Reason', timings.reason)}
            {_markerDetail('gcbudget', 'Budget', timings.budget)}
            {_markerDetail(
              'gcstate',
              'States',
              timings.initial_state + ' – ' + timings.final_state
            )}
            {triggers}
            {timings.page_faults === undefined
              ? null
              : _markerDetail('gcfaults', 'Page faults', timings.page_faults)}
            {phase_times.map(_markerDetailPhase)}

        );
      }
      case 'Bailout': {
        return (

            {_markerDetail('bailoutType', 'Type', data.bailoutType)}
            {_markerDetail('where', 'Where', data.where)}
            {_markerDetail('script', 'Script', data.script)}
            {_markerDetail('functionLine', 'Function Line', data.functionLine)}
            {_markerDetail('bailoutLine', 'Bailout Line', data.bailoutLine)}

Description:

              {bailoutTypeInformation['Bailout_' + data.bailoutType]}

        );
      }
      case 'Invalidation': {
        return (

            {_markerDetail('url', 'URL', data.url)}
            {_markerDetail('line', 'Line', data.line)}

        );
      }
      case 'Network': {
        if (
          data.status !== 'STATUS_STOP' &&
          data.status !== 'STATUS_REDIRECT'
        ) {
          return (

              {_markerDetailNullable('url', 'URL', data.URI)}
              {_markerDetail('pri', 'pri', data.pri)}
              {_markerDetailNullable('count', 'count', data.count)}
              {_markerDetail('status', 'Status', data.status)}

          );
        } else {
          return (

              {_markerDetail('status', 'Status', data.status)}
              {_markerDetailNullable('url', 'URL', data.URI)}
              {_markerDetailNullable(
                'redirect_url',
                'Redirect URL',
                data.RedirectURI
              )}
              {_markerDetail('pri', 'pri', data.pri)}
              {_markerDetailNullable('count', 'count', data.count)}
              {_markerDetailDeltaTimeNullable(
                'domainLookup',
                'domainLookup',
                data.domainLookupEnd,
                data.domainLookupStart
              )}
              {_markerDetailDeltaTimeNullable(
                'tcpConnect',
                'tcpConnect',
                data.tcpConnectEnd,
                data.connectStart
              )}
              {_markerDetailNullable(
                'secureConnectionStart',
                'secureConnectionStart',
                data.secureConnectionStart
              )}
              {_markerDetailDeltaTimeNullable(
                'connect',
                'connect',
                data.connectEnd,
                data.connectStart
              )}
              {_markerDetailDeltaTimeNullable(
                'requestStart',
                'requestStart @',
                data.requestStart,
                data.startTime
              )}
              {_markerDetailDeltaTimeNullable(
                'response',
                'response',
                data.responseEnd,
                data.responseStart
              )}

          );
        }
      }
      case 'Styles': {
        return [

            {_markerDetail(
              'elementsTraversed',
              'Elements traversed',
              data.elementsTraversed
            )}
            {_markerDetail(
              'elementsStyled',
              'Elements styled',
              data.elementsStyled
            )}
            {_markerDetail(
              'elementsMatched',
              'Elements matched',
              data.elementsMatched
            )}
            {_markerDetail('stylesShared', 'Styles shared', data.stylesShared)}
            {_markerDetail('stylesReused', 'Styles reused', data.stylesReused)}

,
          _markerBacktrace(marker, data, thread, implementationFilter),
        ];
      }
      case 'tracing': {
        return _markerBacktrace(marker, data, thread, implementationFilter);
      }
      default:
    }
  }
  return null;
}

type OwnProps = {|
  +marker: TracingMarker,
  +threadIndex: ThreadIndex,
  +className?: string,
|};

type StateProps = {|
  +threadName?: string,
  +thread: Thread,
  +implementationFilter: ImplementationFilter,
|};

type Props = ConnectedProps<OwnProps, StateProps, {||}>;

class MarkerTooltipContents extends React.PureComponent<Props> {
  render() {
    const {
      marker,
      className,
      threadName,
      thread,
      implementationFilter,
    } = this.props;
    const details = getMarkerDetails(marker, thread, implementationFilter);

    return (

              {/* tracing markers with no start have a negative start, while the
                ones with no end have an infinite duration */}
              {Number.isFinite(marker.dur) && marker.start >= 0
                ? formatNumber(marker.dur) + 'ms'
                : 'unknown duration'}

{marker.title || marker.name}

          {threadName ? (

Thread:

              {threadName}

          ) : null}

        {details}

    );
  }
}

const options: ExplicitConnectOptions<OwnProps, StateProps, {||}> = {
  mapStateToProps: (state, props) => {
    const { threadIndex } = props;
    const selectors = selectorsForThread(threadIndex);
    const threadName = selectors.getFriendlyThreadName(state);
    const thread = selectors.getThread(state);
    const implementationFilter = getImplementationFilter(state);
    return {
      threadName,
      thread,
      implementationFilter,
    };
  },
  component: MarkerTooltipContents,
};

export default explicitConnect(options);
<|endoftext|>


<commit_before>/**
 * Created by natefang on 1/14/16.
 */
import React, { Component } from 'react';
import { Link } from 'react-router';
import fetch from 'isomorphic-fetch';
import moment from 'moment';
class Topic extends Component {
	constructor(props) {
		super(props);
		this.state = {
			topic: {
				strategies:[],
				owner:{
					nickname :''
				},
				cover: '',
				score: 0,
				tryCount :0,
				description:''
			} };
	}
	componentWillMount (){
		//var id = document.URL.split("/").slice(-1)[0];
		fetch('http://www.iyuanzi.net/topics/'+ this.props.params.id + '?version=v2')
			.then((response) => response.json())
			.then((data) => {
				this.setState({ topic: data });
				var title = data.title || '元子育儿';
				var image = data.cover || 'http://share.iyuanzi.net/favicon.ico';
				var description = title;
				const oMeta = document.createElement('meta');
				oMeta.setAttribute('property', 'og:title');
				oMeta.setAttribute('content', title);
				document.getElementsByTagName('head')[0].appendChild(oMeta);
				const oMetaimage = document.createElement('meta');
				oMetaimage.setAttribute('property', 'og:image');
				oMetaimage.setAttribute('content', image);
				document.getElementsByTagName('head')[0].appendChild(oMetaimage);
				const oMetadesc = document.createElement('meta');
				oMetadesc.setAttribute('property', 'og:description');
				oMetadesc.setAttribute('content', description);
				document.getElementsByTagName('head')[0].appendChild(oMetadesc);
			})
			.catch((ex) => {
				console.log('fetch failed', ex);
			});
	}

	render() {
		return (

				{
					<Topics topic = {this.state.topic}/>
				}

		);
	}
}

class Topics extends Component {
	render () {
		return (

{this.props.topic.title}

 来自: {this.props.topic.owner.nickname}

{this.props.topic.content}

				<StrategiesCollections strategies={this.props.topic.strategies}/>

		);
	}
}

class StrategiesCollections extends  Component {
	render () {
		return (

				{
					this.props.strategies.length ?

							妙招
							({this.props.strategies.length})

							{
								this.props.strategies.map(function(item) {
									return (<StrategyItem key={item.strategyId} {...item}></StrategyItem>);
								})
							}

 : null

				}

		);
	}
}

class StrategyItem extends Component {
	render () {
		return (
			<Link to={'/strategies/'+this.props.strategyId+'/view'} >

{this.props.title}

by {this.props.owner.nickname}

{ this.props.tryCount+'人参与 / ' + this.props.score+'分' }

			</Link>
		);
	};
}

export default Topic;

<commit_msg>add topic css<commit_after>/**
 * Created by natefang on 1/14/16.
 */
import React, { Component } from 'react';
import { Link } from 'react-router';
import fetch from 'isomorphic-fetch';
import moment from 'moment';
import './style/topic.css';
class Topic extends Component {
	constructor(props) {
		super(props);
		this.state = {
			topic: {
				strategies:[],
				owner:{
					nickname :''
				},
				cover: '',
				score: 0,
				tryCount :0,
				description:''
			} };
	}
	componentWillMount (){
		//var id = document.URL.split("/").slice(-1)[0];
		fetch('http://www.iyuanzi.net/topics/'+ this.props.params.id + '?version=v2')
			.then((response) => response.json())
			.then((data) => {
				this.setState({ topic: data });
				var title = data.title || '元子育儿';
				var image = data.cover || 'http://share.iyuanzi.net/favicon.ico';
				var description = title;
				const oMeta = document.createElement('meta');
				oMeta.setAttribute('property', 'og:title');
				oMeta.setAttribute('content', title);
				document.getElementsByTagName('head')[0].appendChild(oMeta);
				const oMetaimage = document.createElement('meta');
				oMetaimage.setAttribute('property', 'og:image');
				oMetaimage.setAttribute('content', image);
				document.getElementsByTagName('head')[0].appendChild(oMetaimage);
				const oMetadesc = document.createElement('meta');
				oMetadesc.setAttribute('property', 'og:description');
				oMetadesc.setAttribute('content', description);
				document.getElementsByTagName('head')[0].appendChild(oMetadesc);
			})
			.catch((ex) => {
				console.log('fetch failed', ex);
			});
	}

	render() {
		return (

				{
					<Topics topic = {this.state.topic}/>
				}

		);
	}
}

class Topics extends Component {
	render () {
		return (

{this.props.topic.title}

 来自: {this.props.topic.owner.nickname}

{this.props.topic.content}

				<StrategiesCollections strategies={this.props.topic.strategies}/>

		);
	}
}

class StrategiesCollections extends  Component {
	render () {
		return (

				{
					this.props.strategies.length ?

							妙招
							({this.props.strategies.length})

							{
								this.props.strategies.map(function(item) {
									return (<StrategyItem key={item.strategyId} {...item}></StrategyItem>);
								})
							}

 : null

				}

		);
	}
}

class StrategyItem extends Component {
	render () {
		return (
			<Link to={'/strategies/'+this.props.strategyId+'/view'} >

{this.props.title}

by {this.props.owner.nickname}

{ this.props.tryCount+'人参与 / ' + this.props.score+'分' }

			</Link>
		);
	};
}

export default Topic;

<|endoftext|>


<commit_before>'use strict';

const getChannelURL = require('ember-source-channel-url');
const { embroiderSafe } = require('@embroider/test-setup');

module.exports = async function() {
  return {
    useYarn: true,
    scenarios: [
      {
        name: 'ember-lts-3.12',
        npm: {
          devDependencies: {
            'ember-source': '~3.12.0',
          },
        },
      },
      {
        name: 'ember-lts-3.16',
        npm: {
          devDependencies: {
            'ember-source': '~3.16.0',
          },
        },
      },
      {
        name: 'ember-release',
        npm: {
          devDependencies: {
            'ember-source': await getChannelURL('release'),
          },
        },
      },
      {
        name: 'ember-beta',
        npm: {
          devDependencies: {
            'ember-source': await getChannelURL('beta'),
          },
        },
      },
      {
        name: 'ember-canary',
        allowedToFail: true,
        npm: {
          devDependencies: {
            'ember-source': await getChannelURL('canary'),
          },
        },
      },
      embroiderSafe(),
      // The default `.travis.yml` runs this scenario via `npm test`,
      // not via `ember try`. It's still included here so that running
      // `ember try:each` manually or from a customized CI config will run it
      // along with all the other scenarios.
      {
        name: 'ember-default',
        npm: {
          devDependencies: {},
        },
      },
      {
        name: 'ember-default-with-jquery',
        env: {
          EMBER_OPTIONAL_FEATURES: JSON.stringify({
            'jquery-integration': true,
          }),
        },
        npm: {
          devDependencies: {
            '@ember/jquery': '^0.5.1',
          },
        },
      },
      {
        name: 'ember-classic',
        env: {
          EMBER_OPTIONAL_FEATURES: JSON.stringify({
            'application-template-wrapper': true,
            'default-async-observers': false,
            'template-only-glimmer-components': false,
          }),
        },
        npm: {
          ember: {
            edition: 'classic',
          },
        },
      },
    ],
  };
};
<commit_msg>ref(ember): Update scenarios and remove a few to speed up tests (#3720)<commit_after>'use strict';

const getChannelURL = require('ember-source-channel-url');
const { embroiderSafe } = require('@embroider/test-setup');

module.exports = async function() {
  return {
    useYarn: true,
    scenarios: [
      {
        name: 'ember-lts-3.20',
        npm: {
          devDependencies: {
            'ember-source': '~3.20.0',
          },
        },
      },
      {
        name: 'ember-release',
        npm: {
          devDependencies: {
            'ember-source': await getChannelURL('release'),
          },
        },
      },
      {
        name: 'ember-beta',
        npm: {
          devDependencies: {
            'ember-source': await getChannelURL('beta'),
          },
        },
      },
      embroiderSafe(),
      {
        name: 'ember-classic',
        env: {
          EMBER_OPTIONAL_FEATURES: JSON.stringify({
            'application-template-wrapper': true,
            'default-async-observers': false,
            'template-only-glimmer-components': false,
          }),
        },
        npm: {
          ember: {
            edition: 'classic',
          },
        },
      },
    ],
  };
};
<|endoftext|>


<commit_before>'use strict'

import React, {Component} from 'react'
import axios from 'axios'

export default class extends Component {
  constructor (props) {
    super(props)
    this.submitSummoner = this.submitSummoner.bind(this)
  }

  componentWillMount () {
    const localStorageRef = localStorage.getItem('token')

    axios.get('http://localhost:3001/profile', {
      headers: {
        'Content-Type': 'application/json',
        'Authorization': localStorageRef
      }
    })
    .then(res => {
      console.log(res)
    })
  }

  submitSummoner (e) {
    e.preventDefault()

    fetch('http://localhost:3001/summoner', {
      method: 'POST',
      headers: {'Content-Type': 'application/json'},
      body: JSON.stringify({
        name: this.name.value
      })
    }).then(res => {
      console.log(res)
    }).catch(err => {
      console.log(err)
    })
  }

  render () {
    return (

Profile

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vel lacus vel augue aliquet luctus. Ut urna libero.

          <form className='registration-form' onSubmit={this.submitSummoner}>
            <fieldset className='form-input'>
              Summoner Name
              <input className='input' type='text' name="name" ref={input => {this.name = input}} />
            </fieldset>

            <button className='btn -secondary -large' type='submit'>Add Summoner</button>
          </form>

    )
  }
}
<commit_msg>Get Account Info & Get Summoner Code<commit_after>'use strict'

import React, {Component} from 'react'
import axios from 'axios'

export default class extends Component {
  constructor (props) {
    super(props)
    this.submitSummoner = this.submitSummoner.bind(this)
  }

  componentWillMount () {
    const localStorageRef = localStorage.getItem('token')

    axios.get('http://localhost:3001/account', {
      headers: {
        'Content-Type': 'application/json',
        'Authorization': localStorageRef
      }
    })
    .then(res => {
      console.log(res)
    })
  }

  submitSummoner (e) {
    e.preventDefault()
    const localStorageRef = localStorage.getItem('token')

    fetch('http://localhost:3001/summoner', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': localStorageRef
      },
      body: JSON.stringify({
        name: this.name.value
      })
    }).then(res => {
      console.log(res)
    }).catch(err => {
      console.log(err)
    })
  }

  render () {
    return (

Profile

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vel lacus vel augue aliquet luctus. Ut urna libero.

          <form className='registration-form' onSubmit={this.submitSummoner}>
            <fieldset className='form-input'>
              Summoner Name
              <input className='input' type='text' name="name" ref={input => {this.name = input}} />
            </fieldset>

            <button className='btn -secondary -large' type='submit'>Add Summoner</button>
          </form>

    )
  }
}
<|endoftext|>


<commit_before>
if (!R8.IDE.View.chefDebugger) {

	R8.IDE.View.chefDebugger = function(view) {
		var _view = view,
			_id = _view.id,
			_panel = _view.panel,
			_pendingDelete = {},

			_modalNoe = null,
			_modalNodeId = 'chef-debugger-'+_id+'-modal',
			_shimNodeId = null,
			_shimNode = null,

			_alertNode = null,
			_alertNodeId = null,

			_nodeList = [],

//DEBUG
//			_contentTpl = '

',
			_contentTpl = '
\

\
									<select id="'+_panel.get('id')+'-chef-debugger-available-nodes" name="'+_panel.get('id')+'-chef-debugger-available-nodes"></select>\

\

\

\

',

			_contentWrapperNode = null,
			_contentNode = null,
			_headerNode = null,

			_nodeSelect = null,
			_currentNodeId = '',
			_logContents = {},

			_initialized = false,

			//FROM WORKSPACE
			_viewSpaces = {},
			_viewSpaceStack = [],
			_currentViewSpace = null,
			_viewContext = 'node',

			_cmdBar = null,

			_logPollerTimeout = null,
			_events = {};

		return {
			init: function() {
				_headerNode = R8.Utils.Y.one('#'+_panel.get('id')+'-'+_view.id+'-header');
				_contentNode = R8.Utils.Y.one('#'+_panel.get('id')+'-'+_view.id+'-content');
				_contentWrapperNode = R8.Utils.Y.one('#'+_panel.get('id')+'-'+_view.id+'-wrapper');

				_nodeSelect = document.getElementById(_panel.get('id')+'-'+_view.id+'-available-nodes');
				_nodeSelectYUI = R8.Utils.Y.one('#'+_panel.get('id')+'-'+_view.id+'-available-nodes');

				var that=this;
				_nodeSelect.onchange = function() {
					that.changeLogFocus(this.options[this.selectedIndex].value);
				}

				var items = R8.IDE.get('nodesInEditor');
				for(var i in items) {
					this.addNode(items[i]);
				}

				_initialized = true;
			},
			render: function() {
				return _contentTpl;
			},
			resize: function() {
				if(!_initialized) return;

				var pRegion = _panel.get('node').get('region');

				_contentWrapperNode.setStyles({'height':pRegion.height-6,'width':pRegion.width-6});
//				_contentNode.setStyles({'height':pRegion.height,'width':pRegion.width});
				_contentNode.setStyles({'height':pRegion.height-(6+1+_headerNode.get('region').height),'width':pRegion.width-6});

/*
				var contentHeight = _node.get('region').height - _headerNode.get('region').height;
				_contentNode.setStyles({'height':contentHeight,'width':_node.get('region').width,'backgroundColor':'#FFFFFF'});
*/
			},
			get: function(key) {
				switch(key) {
					case "id":
						return _id;
						break;
					case "name":
						return _view.name;
						break;
					case "type":
						return _view.type;
						break;
				}
			},
			focus: function() {
				this.resize();
				_contentWrapperNode.setStyle('display','block');

				this.startLogPoller();
			},
			blur: function() {
				_contentWrapperNode.setStyle('display','none');
//				clearTimeout(_logPollerTimeout);
				this.stopLogPoller();
			},
			close: function() {
				_contentWrapperNode.purge(true);
				_contentWrapperNode.remove();
			},

//------------------------------------------------------
//these are debugger view specific functions
//------------------------------------------------------
			startLogPoller: function() {
				var that = this;
				var fireLogPoller = function() {
					that.pollLog();
				}
				_logPollerTimeout = setTimeout(fireLogPoller,2000);
			},

			stopLogPoller: function() {
				clearTimeout(_logPollerTimeout);
				_logPollerTimeout = null;
			},
/*
				var that=this;
				var pollerCallback = function() {
					that.pollLog();
				}
				_logPollerTimeout = setTimeout(pollerCallback,3000);
*/
			changeLogFocus: function(nodeId) {
				_currentNodeId = nodeId;

				_contentNode.set('innerHTML','');

				if(typeof(_logContents[nodeId]) != 'undefined') {
					this.renderLogContents(nodeId);
				}

				if(_logPollerTimeout == null && (typeof(_logContents[nodeId]) == 'undefined' || _logContents[nodeId].complete != true)) {
					this.startLogPoller();
				}
			},
			pollLog: function() {
				var that=this;
				var fireLogPoller = function() {
					that.pollLog();
				}
				_logPollerTimeout = setTimeout(fireLogPoller,2500);

				if(_currentNodeId == '') return;

				var setLogsCallback = function(ioId,responseObj) {
					eval("var response =" + responseObj.responseText);
					var logContent = response.application_task_get_logs.content[0].data;

					that.setLogContent(logContent);
//					contentNode.set('innerHTML',log_content);
//					contentNode.append(log_content);
				}
				var params = {
					'cfg': {
						'data': 'node_id='+_currentNodeId
					},
					'callbacks': {
						'io:success': setLogsCallback
					}
				};
				R8.Ctrl.call('task/get_logs',params);
//				R8.Ctrl.call('task/get_logs/'+level,params);
			},
			setLogContent: function(logContent) {
				for(var l in logContent) {
					_logContents[l] = logContent[l];
				}

				this.renderLogContents(_currentNodeId);

				if(_logContents[_currentNodeId].complete == true) this.stopLogPoller();
/*
      {:type=>:error,
      :error_file_ref=>
       {:type=>:recipe, :cookbook=>"java_webapp", :file_name=>"default.rb"},
       :error_type=>:error_recipe,
      :error_line_num=>2,
      :error_lines=>[],
      :error_detail=>"syntax error, unexpected tEQQ, expecting $end"}],

 */
			},
			addNode: function(nodeObj) {
				_nodeList.push(nodeObj);

				var newOptionStr = '<option value="'+nodeObj.id+'">'+nodeObj.display_name+'</option>';
				_nodeSelectYUI.append(newOptionStr);
//DEBUG
//console.log(nodeObj);
			},
			updateNodeName: function(nodeId,nodeName) {
				var numNodes = _nodeSelect.options.length;
				for(var i=0; i < numNodes; i++) {
					if(_nodeSelect.options[i].value==nodeId) {
						_nodeSelect.options[i].text = nodeName;
					}
				}
			},
			renderLogContents: function(nodeId) {
				for(var i in _logContents[_currentNodeId]['log_segments']) {
					var logSegment = _logContents[_currentNodeId]['log_segments'][i];

					switch(logSegment.type) {
						case "debug":
						case "info":
							var logTpl = '
'+logSegment.line+'
';
							break;
						case "error":
							if(typeof(logSegment.error_file_ref) == 'undefined') {
								var logTpl = '
'+logSegment.error_detail+'
';
							} else {
								var logTpl = '
'+logSegment.error_detail+' in file '+logSegment.error_file_ref.file_name+'
';
							}

							break;
					}

					_contentNode.append(logTpl);
				}
			},
//---------------------------------------------
//alert/notification related
//---------------------------------------------
			showAlert: function(alertStr) {
				_alertNodeId = R8.Utils.Y.guid();

				var alertTpl = '
\

\

'+alertStr+'
\

\

',

					nodeRegion = _contentNode.get('region'),
					height = nodeRegion.bottom - nodeRegion.top,
					width = nodeRegion.right - nodeRegion.left,
					aTop = 0,
					aLeft = Math.floor((width-250)/2);

//				containerNode.append(alertTpl);
				_contentNode.append(alertTpl);
				_alertNode = R8.Utils.Y.one('#'+_alertNodeId);
				_alertNode.setStyles({'top':aTop,'left':aLeft,'display':'block'});
//return;
				YUI().use('anim', function(Y) {
					var anim = new Y.Anim({
						node: '#'+_alertNodeId,
						to: { opacity: 0 },
						duration: .7
					});
					anim.on('end', function(e) {
						var node = this.get('node');
						node.get('parentNode').removeChild(node);
					});
					var delayAnimRun = function(){
							anim.run();
						}
					setTimeout(delayAnimRun,2000);
				});
//				alert(alertStr);
			},

			shimify: function(nodeId) {
				var node = R8.Utils.Y.one('#'+nodeId),
					_shimNodeId = R8.Utils.Y.guid(),
					nodeRegion = node.get('region'),
					height = nodeRegion.bottom - nodeRegion.top,
					width = nodeRegion.right - nodeRegion.left;

				node.append('

');
				_shimNode = R8.Utils.Y.one('#'+_shimNodeId);
				_shimNode.setStyle('opacity','0.8');
				_shimNode.on('click',function(Y){
					R8.Workspace.destroyShim();
				});
			},
			destroyShim: function() {
				_modalNode.purge(true);
				_modalNode.remove();
				_modalNode = null,

				_shimNode.purge(true);
				_shimNode.remove();
				_shimId = null;
				_shimNode = null;
			}

		}
	};
}<commit_msg>quick tweaks<commit_after>
if (!R8.IDE.View.chefDebugger) {

	R8.IDE.View.chefDebugger = function(view) {
		var _view = view,
			_id = _view.id,
			_panel = _view.panel,
			_pendingDelete = {},

			_modalNoe = null,
			_modalNodeId = 'chef-debugger-'+_id+'-modal',
			_shimNodeId = null,
			_shimNode = null,

			_alertNode = null,
			_alertNodeId = null,

			_nodeList = [],

//DEBUG
//			_contentTpl = '

',
			_contentTpl = '
\

\
									<select id="'+_panel.get('id')+'-chef-debugger-available-nodes" name="'+_panel.get('id')+'-chef-debugger-available-nodes">\
										<option value="">-Node List-</option>\
									</select>\

\

\

\

',

			_contentWrapperNode = null,
			_contentNode = null,
			_headerNode = null,

			_nodeSelect = null,
			_currentNodeId = '',
			_logContents = {},

			_initialized = false,

			//FROM WORKSPACE
			_viewSpaces = {},
			_viewSpaceStack = [],
			_currentViewSpace = null,
			_viewContext = 'node',

			_cmdBar = null,

			_logPollerTimeout = null,
			_events = {};

		return {
			init: function() {
				_headerNode = R8.Utils.Y.one('#'+_panel.get('id')+'-'+_view.id+'-header');
				_contentNode = R8.Utils.Y.one('#'+_panel.get('id')+'-'+_view.id+'-content');
				_contentWrapperNode = R8.Utils.Y.one('#'+_panel.get('id')+'-'+_view.id+'-wrapper');

				_nodeSelect = document.getElementById(_panel.get('id')+'-'+_view.id+'-available-nodes');
				_nodeSelectYUI = R8.Utils.Y.one('#'+_panel.get('id')+'-'+_view.id+'-available-nodes');

				var that=this;
				_nodeSelect.onchange = function() {
					that.changeLogFocus(this.options[this.selectedIndex].value);
				}

				var items = R8.IDE.get('nodesInEditor');
				for(var i in items) {
					this.addNode(items[i]);
				}

				_initialized = true;
			},
			render: function() {
				return _contentTpl;
			},
			resize: function() {
				if(!_initialized) return;

				var pRegion = _panel.get('node').get('region');

				_contentWrapperNode.setStyles({'height':pRegion.height-6,'width':pRegion.width-6});
//				_contentNode.setStyles({'height':pRegion.height,'width':pRegion.width});
				_contentNode.setStyles({'height':pRegion.height-(6+1+_headerNode.get('region').height),'width':pRegion.width-6});

/*
				var contentHeight = _node.get('region').height - _headerNode.get('region').height;
				_contentNode.setStyles({'height':contentHeight,'width':_node.get('region').width,'backgroundColor':'#FFFFFF'});
*/
			},
			get: function(key) {
				switch(key) {
					case "id":
						return _id;
						break;
					case "name":
						return _view.name;
						break;
					case "type":
						return _view.type;
						break;
				}
			},
			focus: function() {
				this.resize();
				_contentWrapperNode.setStyle('display','block');

				this.startLogPoller();
			},
			blur: function() {
				_contentWrapperNode.setStyle('display','none');
//				clearTimeout(_logPollerTimeout);
				this.stopLogPoller();
			},
			close: function() {
				_contentWrapperNode.purge(true);
				_contentWrapperNode.remove();
			},

//------------------------------------------------------
//these are debugger view specific functions
//------------------------------------------------------
			startLogPoller: function() {
				var that = this;
				var fireLogPoller = function() {
					that.pollLog();
				}
				_logPollerTimeout = setTimeout(fireLogPoller,2000);
			},

			stopLogPoller: function() {
				clearTimeout(_logPollerTimeout);
				_logPollerTimeout = null;
			},
/*
				var that=this;
				var pollerCallback = function() {
					that.pollLog();
				}
				_logPollerTimeout = setTimeout(pollerCallback,3000);
*/
			changeLogFocus: function(nodeId) {
				if(nodeId == '') return;

				_currentNodeId = nodeId;

				_contentNode.set('innerHTML','');

				if(typeof(_logContents[nodeId]) != 'undefined') {
					this.renderLogContents(nodeId);
				}

				if(_logPollerTimeout == null && (typeof(_logContents[nodeId]) == 'undefined' || _logContents[nodeId].complete != true)) {
					this.startLogPoller();
				}
			},
			pollLog: function() {
				var that=this;
				var fireLogPoller = function() {
					that.pollLog();
				}
				_logPollerTimeout = setTimeout(fireLogPoller,2500);

				if(_currentNodeId == '') return;

				var setLogsCallback = function(ioId,responseObj) {
					eval("var response =" + responseObj.responseText);
					var logContent = response.application_task_get_logs.content[0].data;

					that.setLogContent(logContent);
//					contentNode.set('innerHTML',log_content);
//					contentNode.append(log_content);
				}
				var params = {
					'cfg': {
						'data': 'node_id='+_currentNodeId
					},
					'callbacks': {
						'io:success': setLogsCallback
					}
				};
				R8.Ctrl.call('task/get_logs',params);
//				R8.Ctrl.call('task/get_logs/'+level,params);
			},
			setLogContent: function(logContent) {
				for(var l in logContent) {
					_logContents[l] = logContent[l];
				}

				this.renderLogContents(_currentNodeId);

				if(_logContents[_currentNodeId].complete == true) this.stopLogPoller();
/*
      {:type=>:error,
      :error_file_ref=>
       {:type=>:recipe, :cookbook=>"java_webapp", :file_name=>"default.rb"},
       :error_type=>:error_recipe,
      :error_line_num=>2,
      :error_lines=>[],
      :error_detail=>"syntax error, unexpected tEQQ, expecting $end"}],

 */
			},
			addNode: function(nodeObj) {
				_nodeList.push(nodeObj);

				var newOptionStr = '<option value="'+nodeObj.id+'">'+nodeObj.display_name+'</option>';
				_nodeSelectYUI.append(newOptionStr);
//DEBUG
//console.log(nodeObj);
			},
			updateNodeName: function(nodeId,nodeName) {
				var numNodes = _nodeSelect.options.length;
				for(var i=0; i < numNodes; i++) {
					if(_nodeSelect.options[i].value==nodeId) {
						_nodeSelect.options[i].text = nodeName;
					}
				}
			},
			renderLogContents: function(nodeId) {
				for(var i in _logContents[_currentNodeId]['log_segments']) {
					var logSegment = _logContents[_currentNodeId]['log_segments'][i];

					switch(logSegment.type) {
						case "debug":
						case "info":
							var logTpl = '
'+logSegment.line+'
';
							break;
						case "error":
							if(typeof(logSegment.error_file_ref) == 'undefined' || logSegment.error_file_ref == null || logSegment.error_file_ref == '') {
								var logTpl = '
'+logSegment.error_detail+'
';
							} else {
								var logTpl = '
'+logSegment.error_detail+' in file '+logSegment.error_file_ref.file_name+'
';
							}

							break;
					}

					_contentNode.append(logTpl);
				}
				var contentDiv = document.getElementById(_contentNode.get('id'));
				contentDiv.scrollTop = 5000;
			},
//---------------------------------------------
//alert/notification related
//---------------------------------------------
			showAlert: function(alertStr) {
				_alertNodeId = R8.Utils.Y.guid();

				var alertTpl = '
\

\

'+alertStr+'
\

\

',

					nodeRegion = _contentNode.get('region'),
					height = nodeRegion.bottom - nodeRegion.top,
					width = nodeRegion.right - nodeRegion.left,
					aTop = 0,
					aLeft = Math.floor((width-250)/2);

//				containerNode.append(alertTpl);
				_contentNode.append(alertTpl);
				_alertNode = R8.Utils.Y.one('#'+_alertNodeId);
				_alertNode.setStyles({'top':aTop,'left':aLeft,'display':'block'});
//return;
				YUI().use('anim', function(Y) {
					var anim = new Y.Anim({
						node: '#'+_alertNodeId,
						to: { opacity: 0 },
						duration: .7
					});
					anim.on('end', function(e) {
						var node = this.get('node');
						node.get('parentNode').removeChild(node);
					});
					var delayAnimRun = function(){
							anim.run();
						}
					setTimeout(delayAnimRun,2000);
				});
//				alert(alertStr);
			},

			shimify: function(nodeId) {
				var node = R8.Utils.Y.one('#'+nodeId),
					_shimNodeId = R8.Utils.Y.guid(),
					nodeRegion = node.get('region'),
					height = nodeRegion.bottom - nodeRegion.top,
					width = nodeRegion.right - nodeRegion.left;

				node.append('

');
				_shimNode = R8.Utils.Y.one('#'+_shimNodeId);
				_shimNode.setStyle('opacity','0.8');
				_shimNode.on('click',function(Y){
					R8.Workspace.destroyShim();
				});
			},
			destroyShim: function() {
				_modalNode.purge(true);
				_modalNode.remove();
				_modalNode = null,

				_shimNode.purge(true);
				_shimNode.remove();
				_shimId = null;
				_shimNode = null;
			}

		}
	};
}<|endoftext|>


<commit_before>import {defaultSchema} from "../model"
import {AssertionError} from "../util/error"
import {ParamPrompt} from "../ui/prompt"

import {CommandSet, updateCommands} from "./command"

class Option {
  constructor(defaultValue, update, updateOnInit) {
    this.defaultValue = defaultValue
    this.update = update
    this.updateOnInit = updateOnInit !== false
  }
}

const options = Object.create(null)

// :: (string, any, (pm: ProseMirror, newValue: any, oldValue: any, init: bool), bool)
// Define a new option. The `update` handler will be called with the
// option's old and new value every time the option is
// [changed](#ProseMirror.setOption). When `updateOnInit` is false, it
// will not be called on editor init, otherwise it is called with null as the old value,
// and a fourth argument of true.
export function defineOption(name, defaultValue, update, updateOnInit) {
  options[name] = new Option(defaultValue, update, updateOnInit)
}

// :: Schema #path=schema #kind=option
// The [schema](#Schema) that the editor's document should use.
defineOption("schema", defaultSchema, false)

// :: any #path=doc #kind=option
// The starting document. Usually a `Node`, but can be in another
// format when the `docFormat` option is also specified.
defineOption("doc", null, (pm, value) => pm.setDoc(value), false)

// :: ?string #path=docFormat #kind=option
// The format in which the `doc` option is given. Defaults to `null`
// (a raw `Node`).
defineOption("docFormat", null)

// :: ?union<DOMNode, (DOMNode)> #path=place #kind=option
// Determines the placement of the editor in the page. When `null`,
// the editor is not placed. When a DOM node is given, the editor is
// appended to that node. When a function is given, it is called
// with the editor's wrapping DOM node, and is expected to place it
// into the document.
defineOption("place", null)

// :: number #path=historyDepth #kind=option
// The amount of history events that are collected before the oldest
// events are discarded. Defaults to 100.
defineOption("historyDepth", 100)

// :: number #path=historyEventDelay #kind=option
// The amount of milliseconds that must pass between changes to
// start a new history event. Defaults to 500.
defineOption("historyEventDelay", 500)

// :: CommandSet #path=commands #kind=option
// Specifies the set of [commands](#Command) available in the editor
// (which in turn determines the base key bindings and items available
// in the menus). Defaults to `CommandSet.default`.
defineOption("commands", CommandSet.default, updateCommands)

// :: ParamPrompt #path=commandParamPrompt #kind=option
// A default [parameter prompting](#ui/prompt) class to use when a
// command is [executed](#ProseMirror.execCommand) without providing
// parameters.
defineOption("commandParamPrompt", ParamPrompt)

// :: ?string #path=label #kind=option
// The label of the editor. When set, the editable DOM node gets an
// `aria-label` attribute with this value.
defineOption("label", null)

export function parseOptions(obj) {
  let result = Object.create(null)
  let given = obj ? [obj].concat(obj.use || []) : []
  outer: for (let opt in options) {
    for (let i = 0; i < given.length; i++) {
      if (opt in given[i]) {
        result[opt] = given[i][opt]
        continue outer
      }
    }
    result[opt] = options[opt].defaultValue
  }
  return result
}

export function initOptions(pm) {
  for (var opt in options) {
    let desc = options[opt]
    if (desc.update && desc.updateOnInit)
      desc.update(pm, pm.options[opt], null, true)
  }
}

export function setOption(pm, name, value) {
  let desc = options[name]
  if (desc === undefined) throw new AssertionError("Option '" + name + "' is not defined")
  if (desc.update === false) throw new AssertionError("Option '" + name + "' can not be changed")
  let old = pm.options[name]
  pm.options[name] = value
  if (desc.update) desc.update(pm, value, old, false)
}
<commit_msg>Add option docs<commit_after>import {defaultSchema} from "../model"
import {AssertionError} from "../util/error"
import {ParamPrompt} from "../ui/prompt"

import {CommandSet, updateCommands} from "./command"

// An option encapsulates functionality for an editor instance,
// e.g. the amount of history events that the editor should hold
// onto or the document's schema.
class Option {
  constructor(defaultValue, update, updateOnInit) {
    this.defaultValue = defaultValue
    // A function that will be invoked with the option's old and new
    // value every time the option is [set](#ProseMirror.setOption).
    // This function should bootstrap option functionality.
    this.update = update
    this.updateOnInit = updateOnInit !== false
  }
}

const options = Object.create(null)

// :: (string, any, (pm: ProseMirror, newValue: any, oldValue: any, init: bool), bool)
// Define a new option. The `update` handler will be called with the
// option's old and new value every time the option is
// [changed](#ProseMirror.setOption). When `updateOnInit` is false, it
// will not be called on editor init, otherwise it is called with null as the old value,
// and a fourth argument of true.
export function defineOption(name, defaultValue, update, updateOnInit) {
  options[name] = new Option(defaultValue, update, updateOnInit)
}

// :: Schema #path=schema #kind=option
// The [schema](#Schema) that the editor's document should use.
defineOption("schema", defaultSchema, false)

// :: any #path=doc #kind=option
// The starting document. Usually a `Node`, but can be in another
// format when the `docFormat` option is also specified.
defineOption("doc", null, (pm, value) => pm.setDoc(value), false)

// :: ?string #path=docFormat #kind=option
// The format in which the `doc` option is given. Defaults to `null`
// (a raw `Node`).
defineOption("docFormat", null)

// :: ?union<DOMNode, (DOMNode)> #path=place #kind=option
// Determines the placement of the editor in the page. When `null`,
// the editor is not placed. When a DOM node is given, the editor is
// appended to that node. When a function is given, it is called
// with the editor's wrapping DOM node, and is expected to place it
// into the document.
defineOption("place", null)

// :: number #path=historyDepth #kind=option
// The amount of history events that are collected before the oldest
// events are discarded. Defaults to 100.
defineOption("historyDepth", 100)

// :: number #path=historyEventDelay #kind=option
// The amount of milliseconds that must pass between changes to
// start a new history event. Defaults to 500.
defineOption("historyEventDelay", 500)

// :: CommandSet #path=commands #kind=option
// Specifies the set of [commands](#Command) available in the editor
// (which in turn determines the base key bindings and items available
// in the menus). Defaults to `CommandSet.default`.
defineOption("commands", CommandSet.default, updateCommands)

// :: ParamPrompt #path=commandParamPrompt #kind=option
// A default [parameter prompting](#ui/prompt) class to use when a
// command is [executed](#ProseMirror.execCommand) without providing
// parameters.
defineOption("commandParamPrompt", ParamPrompt)

// :: ?string #path=label #kind=option
// The label of the editor. When set, the editable DOM node gets an
// `aria-label` attribute with this value.
defineOption("label", null)

export function parseOptions(obj) {
  let result = Object.create(null)
  let given = obj ? [obj].concat(obj.use || []) : []
  outer: for (let opt in options) {
    for (let i = 0; i < given.length; i++) {
      if (opt in given[i]) {
        result[opt] = given[i][opt]
        continue outer
      }
    }
    result[opt] = options[opt].defaultValue
  }
  return result
}

export function initOptions(pm) {
  for (var opt in options) {
    let desc = options[opt]
    if (desc.update && desc.updateOnInit)
      desc.update(pm, pm.options[opt], null, true)
  }
}

export function setOption(pm, name, value) {
  let desc = options[name]
  if (desc === undefined) throw new AssertionError("Option '" + name + "' is not defined")
  if (desc.update === false) throw new AssertionError("Option '" + name + "' can not be changed")
  let old = pm.options[name]
  pm.options[name] = value
  if (desc.update) desc.update(pm, value, old, false)
}
<|endoftext|>