mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-22 17:55:50 +00:00
375 lines
10 KiB
JavaScript
375 lines
10 KiB
JavaScript
/* 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/. */
|
|
|
|
const {Cu} = require("chrome");
|
|
|
|
const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm");
|
|
const EventEmitter = require("devtools/toolkit/event-emitter");
|
|
const {Services} = Cu.import("resource://gre/modules/Services.jsm");
|
|
const Strings = Services.strings.createBundle("chrome://browser/locale/devtools/webide.properties");
|
|
|
|
let ConfigView;
|
|
|
|
module.exports = ConfigView = function(window) {
|
|
EventEmitter.decorate(this);
|
|
this._doc = window.document;
|
|
this._keys = [];
|
|
return this;
|
|
};
|
|
|
|
ConfigView.prototype = {
|
|
_renderByType: function(input, name, value, customType) {
|
|
value = customType || typeof value;
|
|
|
|
switch (value) {
|
|
case "boolean":
|
|
input.setAttribute("data-type", "boolean");
|
|
input.setAttribute("type", "checkbox");
|
|
break;
|
|
case "number":
|
|
input.setAttribute("data-type", "number");
|
|
input.setAttribute("type", "number");
|
|
break;
|
|
case "object":
|
|
input.setAttribute("data-type", "object");
|
|
input.setAttribute("type", "text");
|
|
break;
|
|
default:
|
|
input.setAttribute("data-type", "string");
|
|
input.setAttribute("type", "text");
|
|
break;
|
|
}
|
|
return input;
|
|
},
|
|
|
|
set front(front) {
|
|
this._front = front;
|
|
},
|
|
|
|
set keys(keys) {
|
|
this._keys = keys;
|
|
},
|
|
|
|
get keys() {
|
|
return this._keys;
|
|
},
|
|
|
|
set kind(kind) {
|
|
this._kind = kind;
|
|
},
|
|
|
|
set includeTypeName(include) {
|
|
this._includeTypeName = include;
|
|
},
|
|
|
|
search: function(event) {
|
|
if (event.target.value.length) {
|
|
let stringMatch = new RegExp(event.target.value, "i");
|
|
|
|
for (let i = 0; i < this._keys.length; i++) {
|
|
let key = this._keys[i];
|
|
let row = this._doc.getElementById("row-" + key);
|
|
if (key.match(stringMatch)) {
|
|
row.classList.remove("hide");
|
|
} else if (row) {
|
|
row.classList.add("hide");
|
|
}
|
|
}
|
|
} else {
|
|
var trs = this._doc.getElementById("device-fields").querySelectorAll("tr");
|
|
|
|
for (let i = 0; i < trs.length; i++) {
|
|
trs[i].classList.remove("hide");
|
|
}
|
|
}
|
|
},
|
|
|
|
generateDisplay: function(json) {
|
|
let deviceItems = Object.keys(json);
|
|
deviceItems.sort();
|
|
this.keys = deviceItems;
|
|
for (let i = 0; i < this.keys.length; i++) {
|
|
let key = this.keys[i];
|
|
this.generateField(key, json[key].value, json[key].hasUserValue);
|
|
}
|
|
},
|
|
|
|
generateField: function(name, value, hasUserValue, customType, newRow) {
|
|
let table = this._doc.querySelector("table");
|
|
let sResetDefault = Strings.GetStringFromName("device_reset_default");
|
|
|
|
if (this._keys.indexOf(name) === -1) {
|
|
this._keys.push(name);
|
|
}
|
|
|
|
let input = this._doc.createElement("input");
|
|
let tr = this._doc.createElement("tr");
|
|
tr.setAttribute("id", "row-" + name);
|
|
tr.classList.add("edit-row");
|
|
let td = this._doc.createElement("td");
|
|
td.classList.add("field-name");
|
|
td.textContent = name;
|
|
tr.appendChild(td);
|
|
td = this._doc.createElement("td");
|
|
input.classList.add("editable");
|
|
input.setAttribute("id", name);
|
|
input = this._renderByType(input, name, value, customType);
|
|
|
|
if (customType === "boolean" || input.type === "checkbox") {
|
|
input.checked = value;
|
|
} else {
|
|
if (typeof value === "object") {
|
|
value = JSON.stringify(value);
|
|
}
|
|
input.value = value;
|
|
}
|
|
|
|
if (!(this._includeTypeName || isNaN(parseInt(value, 10)))) {
|
|
input.type = "number";
|
|
}
|
|
|
|
td.appendChild(input);
|
|
tr.appendChild(td);
|
|
td = this._doc.createElement("td");
|
|
td.setAttribute("id", "td-" + name);
|
|
|
|
let button = this._doc.createElement("button");
|
|
button.setAttribute("data-id", name);
|
|
button.setAttribute("id", "btn-" + name);
|
|
button.classList.add("reset");
|
|
button.textContent = sResetDefault;
|
|
td.appendChild(button);
|
|
|
|
if (!hasUserValue) {
|
|
button.classList.add("hide");
|
|
}
|
|
|
|
tr.appendChild(td);
|
|
|
|
// If this is a new field, add it to the top of the table.
|
|
if (newRow) {
|
|
let existing = table.querySelector("#" + name);
|
|
|
|
if (!existing) {
|
|
table.insertBefore(tr, newRow);
|
|
} else {
|
|
existing.value = value;
|
|
}
|
|
} else {
|
|
table.appendChild(tr);
|
|
}
|
|
},
|
|
|
|
resetTable: function() {
|
|
let table = this._doc.querySelector("table");
|
|
let trs = table.querySelectorAll("tr:not(#add-custom-field)");
|
|
|
|
for (var i = 0; i < trs.length; i++) {
|
|
table.removeChild(trs[i]);
|
|
}
|
|
|
|
return table;
|
|
},
|
|
|
|
_getCallType: function(type, name) {
|
|
let frontName = "get";
|
|
|
|
if (this._includeTypeName) {
|
|
frontName += type;
|
|
}
|
|
|
|
return this._front[frontName + this._kind](name);
|
|
},
|
|
|
|
_setCallType: function(type, name, value) {
|
|
let frontName = "set";
|
|
|
|
if (this._includeTypeName) {
|
|
frontName += type;
|
|
}
|
|
|
|
return this._front[frontName + this._kind](name, value);
|
|
},
|
|
|
|
_saveByType: function(options) {
|
|
let fieldName = options.id;
|
|
let inputType = options.type;
|
|
let value = options.value;
|
|
let input = this._doc.getElementById(fieldName);
|
|
|
|
switch(inputType) {
|
|
case "boolean":
|
|
this._setCallType("Bool", fieldName, input.checked);
|
|
break;
|
|
case "number":
|
|
this._setCallType("Int", fieldName, value);
|
|
break;
|
|
case "object":
|
|
try {
|
|
value = JSON.parse(value);
|
|
} catch(e) {}
|
|
this._setCallType("Object", fieldName, value);
|
|
break;
|
|
default:
|
|
this._setCallType("Char", fieldName, value);
|
|
break;
|
|
}
|
|
},
|
|
|
|
updateField: function(event) {
|
|
if (event.target) {
|
|
let inputType = event.target.getAttribute("data-type");
|
|
let inputValue = event.target.checked || event.target.value;
|
|
|
|
if (event.target.nodeName == "input" &&
|
|
event.target.validity.valid &&
|
|
event.target.classList.contains("editable")) {
|
|
let id = event.target.id;
|
|
if (inputType === "boolean") {
|
|
if (event.target.checked) {
|
|
inputValue = true;
|
|
} else {
|
|
inputValue = false;
|
|
}
|
|
}
|
|
|
|
this._saveByType({
|
|
id: id,
|
|
type: inputType,
|
|
value: inputValue
|
|
});
|
|
this._doc.getElementById("btn-" + id).classList.remove("hide");
|
|
}
|
|
}
|
|
},
|
|
|
|
_resetToDefault: function(name, input, button) {
|
|
this._front["clearUser" + this._kind](name);
|
|
let dataType = input.getAttribute("data-type");
|
|
let tr = this._doc.getElementById("row-" + name);
|
|
|
|
switch (dataType) {
|
|
case "boolean":
|
|
this._defaultField = this._getCallType("Bool", name);
|
|
this._defaultField.then(boolean => {
|
|
input.checked = boolean;
|
|
}, () => {
|
|
input.checked = false;
|
|
tr.parentNode.removeChild(tr);
|
|
});
|
|
break;
|
|
case "number":
|
|
this._defaultField = this._getCallType("Int", name);
|
|
this._defaultField.then(number => {
|
|
input.value = number;
|
|
}, () => {
|
|
tr.parentNode.removeChild(tr);
|
|
});
|
|
break;
|
|
case "object":
|
|
this._defaultField = this._getCallType("Object", name);
|
|
this._defaultField.then(object => {
|
|
input.value = JSON.stringify(object);
|
|
}, () => {
|
|
tr.parentNode.removeChild(tr);
|
|
});
|
|
break;
|
|
default:
|
|
this._defaultField = this._getCallType("Char", name);
|
|
this._defaultField.then(string => {
|
|
input.value = string;
|
|
}, () => {
|
|
tr.parentNode.removeChild(tr);
|
|
});
|
|
break;
|
|
}
|
|
|
|
button.classList.add("hide");
|
|
},
|
|
|
|
checkReset: function(event) {
|
|
if (event.target.classList.contains("reset")) {
|
|
let btnId = event.target.getAttribute("data-id");
|
|
let input = this._doc.getElementById(btnId);
|
|
this._resetToDefault(btnId, input, event.target);
|
|
}
|
|
},
|
|
|
|
updateFieldType: function() {
|
|
let table = this._doc.querySelector("table");
|
|
let customValueType = table.querySelector("#custom-value-type").value;
|
|
let customTextEl = table.querySelector("#custom-value-text");
|
|
let customText = customTextEl.value;
|
|
|
|
if (customValueType.length === 0) {
|
|
return false;
|
|
}
|
|
|
|
switch (customValueType) {
|
|
case "boolean":
|
|
customTextEl.type = "checkbox";
|
|
customText = customTextEl.checked;
|
|
break;
|
|
case "number":
|
|
customText = parseInt(customText, 10) || 0;
|
|
customTextEl.type = "number";
|
|
break;
|
|
default:
|
|
customTextEl.type = "text";
|
|
break;
|
|
}
|
|
|
|
return customValueType;
|
|
},
|
|
|
|
clearNewFields: function() {
|
|
let table = this._doc.querySelector("table");
|
|
let customTextEl = table.querySelector("#custom-value-text");
|
|
if (customTextEl.checked) {
|
|
customTextEl.checked = false;
|
|
} else {
|
|
customTextEl.value = "";
|
|
}
|
|
|
|
this.updateFieldType();
|
|
},
|
|
|
|
updateNewField: function() {
|
|
let table = this._doc.querySelector("table");
|
|
let customValueType = this.updateFieldType();
|
|
|
|
if (!customValueType) {
|
|
return;
|
|
}
|
|
|
|
let customRow = table.querySelector("tr:nth-of-type(2)");
|
|
let customTextEl = table.querySelector("#custom-value-text");
|
|
let customTextNameEl = table.querySelector("#custom-value-name");
|
|
|
|
if (customTextEl.validity.valid) {
|
|
let customText = customTextEl.value;
|
|
|
|
if (customValueType === "boolean") {
|
|
customText = customTextEl.checked;
|
|
}
|
|
|
|
let customTextName = customTextNameEl.value.replace(/[^A-Za-z0-9\.\-_]/gi, "");
|
|
this.generateField(customTextName, customText, true, customValueType, customRow);
|
|
this._saveByType({
|
|
id: customTextName,
|
|
type: customValueType,
|
|
value: customText
|
|
});
|
|
customTextNameEl.value = "";
|
|
this.clearNewFields();
|
|
}
|
|
},
|
|
|
|
checkNewFieldSubmit: function(event) {
|
|
if (event.keyCode === 13) {
|
|
this._doc.getElementById("custom-value").click();
|
|
}
|
|
}
|
|
};
|