forked from mirrors/gecko-dev
Bug 1273653 - Fix ESLint errors in devtools/client/shared/(components|redux). r=tromey
MozReview-Commit-ID: 5hY0uII6wf8
This commit is contained in:
parent
4a048a0f4b
commit
75f63a4458
48 changed files with 436 additions and 421 deletions
|
|
@ -103,10 +103,9 @@ devtools/client/shared/*.jsm
|
|||
!devtools/client/shared/css-color.js
|
||||
!devtools/client/shared/css-color-db.js
|
||||
!devtools/client/shared/css-parsing-utils.js
|
||||
devtools/client/shared/components/**
|
||||
devtools/client/shared/redux/**
|
||||
devtools/client/shared/components/test/**
|
||||
devtools/client/shared/redux/middleware/test/**
|
||||
devtools/client/shared/test/**
|
||||
devtools/client/shared/vendor/**
|
||||
devtools/client/shared/widgets/**
|
||||
devtools/client/sourceeditor/**
|
||||
devtools/client/webaudioeditor/**
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ const { LocalizationHelper } = require("devtools/client/shared/l10n");
|
|||
const l10n = new LocalizationHelper("chrome://devtools/locale/components.properties");
|
||||
|
||||
module.exports = createClass({
|
||||
displayName: "Frame",
|
||||
|
||||
propTypes: {
|
||||
// SavedFrame, or an object containing all the required properties.
|
||||
frame: PropTypes.shape({
|
||||
|
|
@ -34,8 +36,6 @@ module.exports = createClass({
|
|||
};
|
||||
},
|
||||
|
||||
displayName: "Frame",
|
||||
|
||||
render() {
|
||||
let { onClick, frame, showFunctionName, showHost } = this.props;
|
||||
let source = frame.source ? String(frame.source) : "";
|
||||
|
|
@ -72,7 +72,8 @@ module.exports = createClass({
|
|||
|
||||
if (showFunctionName && frame.functionDisplayName) {
|
||||
elements.push(
|
||||
dom.span({ className: "frame-link-function-display-name" }, frame.functionDisplayName)
|
||||
dom.span({ className: "frame-link-function-display-name" },
|
||||
frame.functionDisplayName)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -87,7 +88,9 @@ module.exports = createClass({
|
|||
// Intentionally exclude 0
|
||||
if (column) {
|
||||
sourceElements.push(dom.span({ className: "frame-link-colon" }, ":"));
|
||||
sourceElements.push(dom.span({ className: "frame-link-column" }, column));
|
||||
sourceElements.push(
|
||||
dom.span({ className: "frame-link-column" }, column)
|
||||
);
|
||||
// Add `data-column` attribute for testing
|
||||
attributes["data-column"] = column;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@
|
|||
* 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/. */
|
||||
|
||||
/* eslint-env browser */
|
||||
"use strict";
|
||||
|
||||
// A box with a start and a end pane, separated by a dragable splitter that
|
||||
// allows the user to resize the relative widths of the panes.
|
||||
//
|
||||
|
|
@ -30,20 +33,6 @@ const { assert } = require("devtools/shared/DevToolsUtils");
|
|||
module.exports = createClass({
|
||||
displayName: "HSplitBox",
|
||||
|
||||
getDefaultProps() {
|
||||
return {
|
||||
startWidth: 0.5,
|
||||
minStartWidth: "20px",
|
||||
minEndWidth: "20px",
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
return {
|
||||
mouseDown: false
|
||||
};
|
||||
},
|
||||
|
||||
propTypes: {
|
||||
// The contents of the start pane.
|
||||
start: PropTypes.any.isRequired,
|
||||
|
|
@ -68,6 +57,34 @@ module.exports = createClass({
|
|||
onResize: PropTypes.func.isRequired,
|
||||
},
|
||||
|
||||
getDefaultProps() {
|
||||
return {
|
||||
startWidth: 0.5,
|
||||
minStartWidth: "20px",
|
||||
minEndWidth: "20px",
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
return {
|
||||
mouseDown: false
|
||||
};
|
||||
},
|
||||
|
||||
componentDidMount() {
|
||||
document.defaultView.top.addEventListener("mouseup", this._onMouseUp,
|
||||
false);
|
||||
document.defaultView.top.addEventListener("mousemove", this._onMouseMove,
|
||||
false);
|
||||
},
|
||||
|
||||
componentWillUnmount() {
|
||||
document.defaultView.top.removeEventListener("mouseup", this._onMouseUp,
|
||||
false);
|
||||
document.defaultView.top.removeEventListener("mousemove", this._onMouseMove,
|
||||
false);
|
||||
},
|
||||
|
||||
_onMouseDown(event) {
|
||||
if (event.button !== 0) {
|
||||
return;
|
||||
|
|
@ -100,21 +117,12 @@ module.exports = createClass({
|
|||
event.preventDefault();
|
||||
},
|
||||
|
||||
componentDidMount() {
|
||||
document.defaultView.top.addEventListener("mouseup", this._onMouseUp, false);
|
||||
document.defaultView.top.addEventListener("mousemove", this._onMouseMove, false);
|
||||
},
|
||||
|
||||
componentWillUnmount() {
|
||||
document.defaultView.top.removeEventListener("mouseup", this._onMouseUp, false);
|
||||
document.defaultView.top.removeEventListener("mousemove", this._onMouseMove, false);
|
||||
},
|
||||
|
||||
render() {
|
||||
/* eslint-disable no-shadow */
|
||||
const { start, end, startWidth, minStartWidth, minEndWidth } = this.props;
|
||||
assert(0 <= startWidth && startWidth <= 1,
|
||||
assert(startWidth => 0 && startWidth <= 1,
|
||||
"0 <= this.props.startWidth <= 1");
|
||||
|
||||
/* eslint-enable */
|
||||
return dom.div(
|
||||
{
|
||||
className: "h-split-box",
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@ const PriorityLevels = {
|
|||
* https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/notificationbox
|
||||
*/
|
||||
var NotificationBox = createClass({
|
||||
displayName: "NotificationBox",
|
||||
|
||||
propTypes: {
|
||||
// List of notifications appended into the box.
|
||||
notifications: PropTypes.arrayOf(PropTypes.shape({
|
||||
|
|
@ -74,8 +76,6 @@ var NotificationBox = createClass({
|
|||
})),
|
||||
},
|
||||
|
||||
displayName: "NotificationBox",
|
||||
|
||||
getInitialState() {
|
||||
return {
|
||||
notifications: new Immutable.OrderedMap()
|
||||
|
|
|
|||
|
|
@ -24,49 +24,6 @@ define(function(require, exports, module) {
|
|||
let ArrayRep = React.createClass({
|
||||
displayName: "ArrayRep",
|
||||
|
||||
render: function() {
|
||||
let mode = this.props.mode || "short";
|
||||
let object = this.props.object;
|
||||
let items;
|
||||
|
||||
if (mode == "tiny") {
|
||||
items = DOM.span({className: "length"}, object.length);
|
||||
} else {
|
||||
let max = (mode == "short") ? 3 : 300;
|
||||
items = this.arrayIterator(object, max);
|
||||
}
|
||||
|
||||
return (
|
||||
ObjectBox({
|
||||
className: "array",
|
||||
onClick: this.onToggleProperties},
|
||||
DOM.a({
|
||||
className: "objectLink",
|
||||
onclick: this.onClickBracket},
|
||||
DOM.span({
|
||||
className: "arrayLeftBracket",
|
||||
role: "presentation"},
|
||||
"["
|
||||
)
|
||||
),
|
||||
items,
|
||||
DOM.a({
|
||||
className: "objectLink",
|
||||
onclick: this.onClickBracket},
|
||||
DOM.span({
|
||||
className: "arrayRightBracket",
|
||||
role: "presentation"},
|
||||
"]"
|
||||
)
|
||||
),
|
||||
DOM.span({
|
||||
className: "arrayProperties",
|
||||
role: "group"}
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
getTitle: function (object, context) {
|
||||
return "[" + object.length + "]";
|
||||
},
|
||||
|
|
@ -158,7 +115,50 @@ define(function(require, exports, module) {
|
|||
},
|
||||
|
||||
onClickBracket: function (event) {
|
||||
},
|
||||
|
||||
render: function () {
|
||||
let mode = this.props.mode || "short";
|
||||
let object = this.props.object;
|
||||
let items;
|
||||
|
||||
if (mode == "tiny") {
|
||||
items = DOM.span({className: "length"}, object.length);
|
||||
} else {
|
||||
let max = (mode == "short") ? 3 : 300;
|
||||
items = this.arrayIterator(object, max);
|
||||
}
|
||||
|
||||
return (
|
||||
ObjectBox({
|
||||
className: "array",
|
||||
onClick: this.onToggleProperties},
|
||||
DOM.a({
|
||||
className: "objectLink",
|
||||
onclick: this.onClickBracket},
|
||||
DOM.span({
|
||||
className: "arrayLeftBracket",
|
||||
role: "presentation"},
|
||||
"["
|
||||
)
|
||||
),
|
||||
items,
|
||||
DOM.a({
|
||||
className: "objectLink",
|
||||
onclick: this.onClickBracket},
|
||||
DOM.span({
|
||||
className: "arrayRightBracket",
|
||||
role: "presentation"},
|
||||
"]"
|
||||
)
|
||||
),
|
||||
DOM.span({
|
||||
className: "arrayProperties",
|
||||
role: "group"}
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -23,12 +23,12 @@ define(function(require, exports, module) {
|
|||
* Renders DOM attribute
|
||||
*/
|
||||
let Attribute = React.createClass({
|
||||
displayName: "Attr",
|
||||
|
||||
propTypes: {
|
||||
object: React.PropTypes.object.isRequired
|
||||
},
|
||||
|
||||
displayName: "Attr",
|
||||
|
||||
getTitle: function (grip) {
|
||||
return grip.preview.nodeName;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -21,12 +21,12 @@ define(function(require, exports, module) {
|
|||
* Used to render JS built-in Date() object.
|
||||
*/
|
||||
let DateTime = React.createClass({
|
||||
displayName: "Date",
|
||||
|
||||
propTypes: {
|
||||
object: React.PropTypes.object.isRequired
|
||||
},
|
||||
|
||||
displayName: "Date",
|
||||
|
||||
getTitle: function (grip) {
|
||||
return new Date(grip.preview.timestamp).toString();
|
||||
},
|
||||
|
|
|
|||
|
|
@ -22,12 +22,12 @@ define(function(require, exports, module) {
|
|||
* Renders DOM document object.
|
||||
*/
|
||||
let Document = React.createClass({
|
||||
displayName: "Document",
|
||||
|
||||
propTypes: {
|
||||
object: React.PropTypes.object.isRequired
|
||||
},
|
||||
|
||||
displayName: "Document",
|
||||
|
||||
getLocation: function (grip) {
|
||||
let location = grip.preview.location;
|
||||
return location ? getFileName(location) : "";
|
||||
|
|
|
|||
|
|
@ -18,12 +18,12 @@ define(function(require, exports, module) {
|
|||
* Renders DOM event objects.
|
||||
*/
|
||||
let Event = React.createClass({
|
||||
displayName: "event",
|
||||
|
||||
propTypes: {
|
||||
object: React.PropTypes.object.isRequired
|
||||
},
|
||||
|
||||
displayName: "event",
|
||||
|
||||
summarizeEvent: function (grip) {
|
||||
let info = [grip.preview.type, " "];
|
||||
|
||||
|
|
|
|||
|
|
@ -19,12 +19,12 @@ define(function(require, exports, module) {
|
|||
* This component represents a template for Function objects.
|
||||
*/
|
||||
let Func = React.createClass({
|
||||
displayName: "Func",
|
||||
|
||||
propTypes: {
|
||||
object: React.PropTypes.object.isRequired
|
||||
},
|
||||
|
||||
displayName: "Func",
|
||||
|
||||
summarizeFunction: function (grip) {
|
||||
let name = grip.displayName || grip.name || "function";
|
||||
return cropString(name + "()", 100);
|
||||
|
|
|
|||
|
|
@ -22,14 +22,14 @@ define(function(require, exports, module) {
|
|||
* and the max number of rendered items depends on the current mode.
|
||||
*/
|
||||
let GripArray = React.createClass({
|
||||
displayName: "GripArray",
|
||||
|
||||
propTypes: {
|
||||
object: React.PropTypes.object.isRequired,
|
||||
mode: React.PropTypes.string,
|
||||
provider: React.PropTypes.object,
|
||||
},
|
||||
|
||||
displayName: "GripArray",
|
||||
|
||||
getLength: function (grip) {
|
||||
return grip.preview ? grip.preview.length : 0;
|
||||
},
|
||||
|
|
@ -158,12 +158,12 @@ define(function(require, exports, module) {
|
|||
* a delimiter (a comma by default).
|
||||
*/
|
||||
let GripArrayItem = React.createFactory(React.createClass({
|
||||
displayName: "GripArrayItem",
|
||||
|
||||
propTypes: {
|
||||
delim: React.PropTypes.string,
|
||||
},
|
||||
|
||||
displayName: "GripArrayItem",
|
||||
|
||||
render: function () {
|
||||
let { Rep } = createFactories(require("./rep"));
|
||||
|
||||
|
|
|
|||
|
|
@ -22,13 +22,13 @@ define(function(require, exports, module) {
|
|||
* @template TODO docs
|
||||
*/
|
||||
const Grip = React.createClass({
|
||||
displayName: "Grip",
|
||||
|
||||
propTypes: {
|
||||
object: React.PropTypes.object.isRequired,
|
||||
mode: React.PropTypes.string,
|
||||
},
|
||||
|
||||
displayName: "Grip",
|
||||
|
||||
getTitle: function () {
|
||||
return "";
|
||||
},
|
||||
|
|
@ -167,14 +167,14 @@ define(function(require, exports, module) {
|
|||
* Property for a grip object.
|
||||
*/
|
||||
let PropRep = React.createFactory(React.createClass({
|
||||
displayName: "PropRep",
|
||||
|
||||
propTypes: {
|
||||
name: React.PropTypes.string,
|
||||
equal: React.PropTypes.string,
|
||||
delim: React.PropTypes.string,
|
||||
},
|
||||
|
||||
displayName: "PropRep",
|
||||
|
||||
render: function () {
|
||||
let { Rep } = createFactories(require("./rep"));
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ define(function(require, exports, module) {
|
|||
* Used to render a map of values provided as a grip.
|
||||
*/
|
||||
let NamedNodeMap = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
object: React.PropTypes.object.isRequired,
|
||||
mode: React.PropTypes.string,
|
||||
|
|
@ -122,13 +123,13 @@ define(function(require, exports, module) {
|
|||
* Property for a grip object.
|
||||
*/
|
||||
let PropRep = React.createFactory(React.createClass({
|
||||
displayName: "PropRep",
|
||||
|
||||
propTypes: {
|
||||
equal: React.PropTypes.string,
|
||||
delim: React.PropTypes.string,
|
||||
},
|
||||
|
||||
displayName: "PropRep",
|
||||
|
||||
render: function () {
|
||||
const { Rep } = createFactories(require("./rep"));
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@ define(function(require, exports, module) {
|
|||
const Number = React.createClass({
|
||||
displayName: "Number",
|
||||
|
||||
stringify: function (object) {
|
||||
return (Object.is(object, -0) ? "-0" : String(object));
|
||||
},
|
||||
|
||||
render: function () {
|
||||
let value = this.props.object;
|
||||
return (
|
||||
|
|
@ -26,11 +30,7 @@ define(function(require, exports, module) {
|
|||
this.stringify(value)
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
stringify: function(object) {
|
||||
return (Object.is(object, -0) ? "-0" : String(object));
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
function supportsObject(object, type) {
|
||||
|
|
|
|||
|
|
@ -21,12 +21,12 @@ define(function(require, exports, module) {
|
|||
* Renders a grip object with textual data.
|
||||
*/
|
||||
let ObjectWithText = React.createClass({
|
||||
displayName: "ObjectWithText",
|
||||
|
||||
propTypes: {
|
||||
object: React.PropTypes.object.isRequired,
|
||||
},
|
||||
|
||||
displayName: "ObjectWithText",
|
||||
|
||||
getType: function (grip) {
|
||||
return grip.class;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -21,12 +21,12 @@ define(function(require, exports, module) {
|
|||
* Renders a grip object with URL data.
|
||||
*/
|
||||
let ObjectWithURL = React.createClass({
|
||||
displayName: "ObjectWithURL",
|
||||
|
||||
propTypes: {
|
||||
object: React.PropTypes.object.isRequired,
|
||||
},
|
||||
|
||||
displayName: "ObjectWithURL",
|
||||
|
||||
getType: function (grip) {
|
||||
return grip.class;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -22,13 +22,13 @@ define(function(require, exports, module) {
|
|||
* properties enclosed in curly brackets.
|
||||
*/
|
||||
const Obj = React.createClass({
|
||||
displayName: "Obj",
|
||||
|
||||
propTypes: {
|
||||
object: React.PropTypes.object,
|
||||
mode: React.PropTypes.string,
|
||||
},
|
||||
|
||||
displayName: "Obj",
|
||||
|
||||
getTitle: function () {
|
||||
return "";
|
||||
},
|
||||
|
|
@ -151,6 +151,8 @@ define(function(require, exports, module) {
|
|||
* Renders object property, name-value pair.
|
||||
*/
|
||||
let PropRep = React.createFactory(React.createClass({
|
||||
displayName: "PropRep",
|
||||
|
||||
propTypes: {
|
||||
object: React.PropTypes.any,
|
||||
mode: React.PropTypes.string,
|
||||
|
|
@ -159,8 +161,6 @@ define(function(require, exports, module) {
|
|||
delim: React.PropTypes.string,
|
||||
},
|
||||
|
||||
displayName: "PropRep",
|
||||
|
||||
render: function () {
|
||||
let { Rep } = createFactories(require("./rep"));
|
||||
let object = this.props.object;
|
||||
|
|
|
|||
|
|
@ -21,12 +21,12 @@ define(function(require, exports, module) {
|
|||
* Renders a grip object with regular expression.
|
||||
*/
|
||||
let RegExp = React.createClass({
|
||||
displayName: "regexp",
|
||||
|
||||
propTypes: {
|
||||
object: React.PropTypes.object.isRequired,
|
||||
},
|
||||
|
||||
displayName: "regexp",
|
||||
|
||||
getTitle: function (grip) {
|
||||
return grip.class;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -69,13 +69,13 @@ define(function(require, exports, module) {
|
|||
* property.
|
||||
*/
|
||||
const Rep = React.createClass({
|
||||
displayName: "Rep",
|
||||
|
||||
propTypes: {
|
||||
object: React.PropTypes.any,
|
||||
defaultRep: React.PropTypes.object,
|
||||
},
|
||||
|
||||
displayName: "Rep",
|
||||
|
||||
render: function () {
|
||||
let rep = getRep(this.props.object, this.props.defaultRep);
|
||||
return rep(this.props);
|
||||
|
|
|
|||
|
|
@ -22,12 +22,12 @@ define(function(require, exports, module) {
|
|||
* Renders a grip representing CSSStyleSheet
|
||||
*/
|
||||
let StyleSheet = React.createClass({
|
||||
displayName: "object",
|
||||
|
||||
propTypes: {
|
||||
object: React.PropTypes.object.isRequired,
|
||||
},
|
||||
|
||||
displayName: "object",
|
||||
|
||||
getLocation: function (grip) {
|
||||
// Embedded stylesheets don't have URL and so, no preview.
|
||||
let url = grip.preview ? grip.preview.url : "";
|
||||
|
|
|
|||
|
|
@ -22,13 +22,13 @@ define(function(require, exports, module) {
|
|||
* Renders DOM #text node.
|
||||
*/
|
||||
let TextNode = React.createClass({
|
||||
displayName: "TextNode",
|
||||
|
||||
propTypes: {
|
||||
object: React.PropTypes.object.isRequired,
|
||||
mode: React.PropTypes.string,
|
||||
},
|
||||
|
||||
displayName: "TextNode",
|
||||
|
||||
getTextContent: function (grip) {
|
||||
return cropMultipleLines(grip.preview.textContent);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -22,12 +22,12 @@ define(function(require, exports, module) {
|
|||
* Renders a grip representing a window.
|
||||
*/
|
||||
let Window = React.createClass({
|
||||
displayName: "Window",
|
||||
|
||||
propTypes: {
|
||||
object: React.PropTypes.object.isRequired,
|
||||
},
|
||||
|
||||
displayName: "Window",
|
||||
|
||||
getLocation: function (grip) {
|
||||
return cropString(grip.preview.url);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
/* 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/. */
|
||||
/* eslint-env browser */
|
||||
"use strict";
|
||||
|
||||
const { DOM: dom, createClass, createFactory, PropTypes } = require("devtools/client/shared/vendor/react");
|
||||
const { ViewHelpers } = require("devtools/client/shared/widgets/view-helpers");
|
||||
|
||||
const AUTO_EXPAND_DEPTH = 0; // depth
|
||||
const AUTO_EXPAND_DEPTH = 0;
|
||||
const NUMBER_OF_OFFSCREEN_ITEMS = 1;
|
||||
|
||||
/**
|
||||
|
|
@ -95,7 +96,7 @@ const NUMBER_OF_OFFSCREEN_ITEMS = 1;
|
|||
* }
|
||||
* });
|
||||
*/
|
||||
const Tree = module.exports = createClass({
|
||||
module.exports = createClass({
|
||||
displayName: "Tree",
|
||||
|
||||
propTypes: {
|
||||
|
|
@ -231,15 +232,15 @@ const Tree = module.exports = createClass({
|
|||
this._updateHeight();
|
||||
},
|
||||
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener("resize", this._updateHeight);
|
||||
},
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
this._autoExpand();
|
||||
this._updateHeight();
|
||||
},
|
||||
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener("resize", this._updateHeight);
|
||||
},
|
||||
|
||||
_autoExpand() {
|
||||
if (!this.props.autoExpandDepth) {
|
||||
return;
|
||||
|
|
@ -271,72 +272,6 @@ const Tree = module.exports = createClass({
|
|||
}
|
||||
},
|
||||
|
||||
render() {
|
||||
const traversal = this._dfsFromRoots();
|
||||
|
||||
// Remove `NUMBER_OF_OFFSCREEN_ITEMS` from `begin` and add `2 *
|
||||
// NUMBER_OF_OFFSCREEN_ITEMS` to `end` so that the top and bottom of the
|
||||
// page are filled with the `NUMBER_OF_OFFSCREEN_ITEMS` previous and next
|
||||
// items respectively, rather than whitespace if the item is not in full
|
||||
// view.
|
||||
const begin = Math.max(((this.state.scroll / this.props.itemHeight) | 0) - NUMBER_OF_OFFSCREEN_ITEMS, 0);
|
||||
const end = begin + (2 * NUMBER_OF_OFFSCREEN_ITEMS) + ((this.state.height / this.props.itemHeight) | 0);
|
||||
const toRender = traversal.slice(begin, end);
|
||||
|
||||
const nodes = [
|
||||
dom.div({
|
||||
key: "top-spacer",
|
||||
style: {
|
||||
padding: 0,
|
||||
margin: 0,
|
||||
height: begin * this.props.itemHeight + "px"
|
||||
}
|
||||
})
|
||||
];
|
||||
|
||||
for (let i = 0; i < toRender.length; i++) {
|
||||
let { item, depth } = toRender[i];
|
||||
nodes.push(TreeNode({
|
||||
key: this.props.getKey(item),
|
||||
index: begin + i,
|
||||
item: item,
|
||||
depth: depth,
|
||||
renderItem: this.props.renderItem,
|
||||
focused: this.props.focused === item,
|
||||
expanded: this.props.isExpanded(item),
|
||||
hasChildren: !!this.props.getChildren(item).length,
|
||||
onExpand: this._onExpand,
|
||||
onCollapse: this._onCollapse,
|
||||
onFocus: () => this._focus(begin + i, item),
|
||||
}));
|
||||
}
|
||||
|
||||
nodes.push(dom.div({
|
||||
key: "bottom-spacer",
|
||||
style: {
|
||||
padding: 0,
|
||||
margin: 0,
|
||||
height: (traversal.length - 1 - end) * this.props.itemHeight + "px"
|
||||
}
|
||||
}));
|
||||
|
||||
return dom.div(
|
||||
{
|
||||
className: "tree",
|
||||
ref: "tree",
|
||||
onKeyDown: this._onKeyDown,
|
||||
onKeyPress: this._preventArrowKeyScrolling,
|
||||
onKeyUp: this._preventArrowKeyScrolling,
|
||||
onScroll: this._onScroll,
|
||||
style: {
|
||||
padding: 0,
|
||||
margin: 0
|
||||
}
|
||||
},
|
||||
nodes
|
||||
);
|
||||
},
|
||||
|
||||
_preventArrowKeyScrolling(e) {
|
||||
switch (e.key) {
|
||||
case "ArrowUp":
|
||||
|
|
@ -451,12 +386,12 @@ const Tree = module.exports = createClass({
|
|||
const itemStartPosition = index * this.props.itemHeight;
|
||||
const itemEndPosition = (index + 1) * this.props.itemHeight;
|
||||
|
||||
// Note that if the height of the viewport (this.state.height) is less than
|
||||
// `this.props.itemHeight`, we could accidentally try and scroll both up and
|
||||
// down in a futile attempt to make both the item's start and end positions
|
||||
// visible. Instead, give priority to the start of the item by checking its
|
||||
// position first, and then using an "else if", rather than a separate "if",
|
||||
// for the end position.
|
||||
// Note that if the height of the viewport (this.state.height) is less
|
||||
// than `this.props.itemHeight`, we could accidentally try and scroll both
|
||||
// up and down in a futile attempt to make both the item's start and end
|
||||
// positions visible. Instead, give priority to the start of the item by
|
||||
// checking its position first, and then using an "else if", rather than
|
||||
// a separate "if", for the end position.
|
||||
if (this.state.scroll > itemStartPosition) {
|
||||
this.refs.tree.scrollTo(0, itemStartPosition);
|
||||
} else if ((this.state.scroll + this.state.height) < itemEndPosition) {
|
||||
|
|
@ -609,6 +544,74 @@ const Tree = module.exports = createClass({
|
|||
|
||||
this._focus(parentIndex, parent);
|
||||
}),
|
||||
|
||||
render() {
|
||||
const traversal = this._dfsFromRoots();
|
||||
|
||||
// Remove `NUMBER_OF_OFFSCREEN_ITEMS` from `begin` and add `2 *
|
||||
// NUMBER_OF_OFFSCREEN_ITEMS` to `end` so that the top and bottom of the
|
||||
// page are filled with the `NUMBER_OF_OFFSCREEN_ITEMS` previous and next
|
||||
// items respectively, rather than whitespace if the item is not in full
|
||||
// view.
|
||||
const begin = Math.max(((this.state.scroll / this.props.itemHeight) | 0)
|
||||
- NUMBER_OF_OFFSCREEN_ITEMS, 0);
|
||||
const end = begin + (2 * NUMBER_OF_OFFSCREEN_ITEMS)
|
||||
+ ((this.state.height / this.props.itemHeight) | 0);
|
||||
const toRender = traversal.slice(begin, end);
|
||||
|
||||
const nodes = [
|
||||
dom.div({
|
||||
key: "top-spacer",
|
||||
style: {
|
||||
padding: 0,
|
||||
margin: 0,
|
||||
height: begin * this.props.itemHeight + "px"
|
||||
}
|
||||
})
|
||||
];
|
||||
|
||||
for (let i = 0; i < toRender.length; i++) {
|
||||
let { item, depth } = toRender[i];
|
||||
nodes.push(TreeNode({
|
||||
key: this.props.getKey(item),
|
||||
index: begin + i,
|
||||
item: item,
|
||||
depth: depth,
|
||||
renderItem: this.props.renderItem,
|
||||
focused: this.props.focused === item,
|
||||
expanded: this.props.isExpanded(item),
|
||||
hasChildren: !!this.props.getChildren(item).length,
|
||||
onExpand: this._onExpand,
|
||||
onCollapse: this._onCollapse,
|
||||
onFocus: () => this._focus(begin + i, item),
|
||||
}));
|
||||
}
|
||||
|
||||
nodes.push(dom.div({
|
||||
key: "bottom-spacer",
|
||||
style: {
|
||||
padding: 0,
|
||||
margin: 0,
|
||||
height: (traversal.length - 1 - end) * this.props.itemHeight + "px"
|
||||
}
|
||||
}));
|
||||
|
||||
return dom.div(
|
||||
{
|
||||
className: "tree",
|
||||
ref: "tree",
|
||||
onKeyDown: this._onKeyDown,
|
||||
onKeyPress: this._preventArrowKeyScrolling,
|
||||
onKeyUp: this._preventArrowKeyScrolling,
|
||||
onScroll: this._onScroll,
|
||||
style: {
|
||||
padding: 0,
|
||||
margin: 0
|
||||
}
|
||||
},
|
||||
nodes
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
|
|
@ -659,6 +662,22 @@ const TreeNode = createFactory(createClass({
|
|||
}
|
||||
},
|
||||
|
||||
_buttonAttrs: {
|
||||
ref: "button",
|
||||
style: {
|
||||
opacity: 0,
|
||||
width: "0 !important",
|
||||
height: "0 !important",
|
||||
padding: "0 !important",
|
||||
outline: "none",
|
||||
MozAppearance: "none",
|
||||
// XXX: Despite resetting all of the above properties (and margin), the
|
||||
// button still ends up with ~79px width, so we set a large negative
|
||||
// margin to completely hide it.
|
||||
MozMarginStart: "-1000px !important",
|
||||
}
|
||||
},
|
||||
|
||||
render() {
|
||||
const arrow = ArrowExpander({
|
||||
item: this.props.item,
|
||||
|
|
@ -691,22 +710,6 @@ const TreeNode = createFactory(createClass({
|
|||
// unless there is an input/button child.
|
||||
dom.button(this._buttonAttrs)
|
||||
);
|
||||
},
|
||||
|
||||
_buttonAttrs: {
|
||||
ref: "button",
|
||||
style: {
|
||||
opacity: 0,
|
||||
width: "0 !important",
|
||||
height: "0 !important",
|
||||
padding: "0 !important",
|
||||
outline: "none",
|
||||
MozAppearance: "none",
|
||||
// XXX: Despite resetting all of the above properties (and margin), the
|
||||
// button still ends up with ~79px width, so we set a large negative
|
||||
// margin to completely hide it.
|
||||
marginInlineStart: "-1000px !important",
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
|
|
|
|||
|
|
@ -18,14 +18,14 @@ define(function(require, exports, module) {
|
|||
* Render the default cell used for toggle buttons
|
||||
*/
|
||||
let LabelCell = React.createClass({
|
||||
displayName: "LabelCell",
|
||||
|
||||
// See the TreeView component for details related
|
||||
// to the 'member' object.
|
||||
propTypes: {
|
||||
member: PropTypes.object.isRequired
|
||||
},
|
||||
|
||||
displayName: "LabelCell",
|
||||
|
||||
render: function () {
|
||||
let member = this.props.member;
|
||||
let level = member.level || 0;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ define(function(require, exports, module) {
|
|||
* using <td> element (the row is <tr> and the entire tree is <table>).
|
||||
*/
|
||||
let TreeCell = React.createClass({
|
||||
displayName: "TreeCell",
|
||||
|
||||
// See TreeView component for detailed property explanation.
|
||||
propTypes: {
|
||||
value: PropTypes.any,
|
||||
|
|
@ -27,8 +29,6 @@ define(function(require, exports, module) {
|
|||
renderValue: PropTypes.func.isRequired
|
||||
},
|
||||
|
||||
displayName: "TreeCell",
|
||||
|
||||
/**
|
||||
* Optimize cell rendering. Rerender cell content only if
|
||||
* the value or expanded state changes.
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ define(function(require, exports, module) {
|
|||
* It's based on <thead> element.
|
||||
*/
|
||||
let TreeHeader = React.createClass({
|
||||
displayName: "TreeHeader",
|
||||
|
||||
// See also TreeView component for detailed info about properties.
|
||||
propTypes: {
|
||||
// Custom tree decorator
|
||||
|
|
@ -29,8 +31,6 @@ define(function(require, exports, module) {
|
|||
columns: PropTypes.array
|
||||
},
|
||||
|
||||
displayName: "TreeHeader",
|
||||
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
columns: [{
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ define(function(require, exports, module) {
|
|||
* using <tr> element (the entire tree is one big <table>).
|
||||
*/
|
||||
let TreeRow = React.createClass({
|
||||
displayName: "TreeRow",
|
||||
|
||||
// See TreeView component for more details about the props and
|
||||
// the 'member' object.
|
||||
propTypes: {
|
||||
|
|
@ -47,7 +49,18 @@ define(function(require, exports, module) {
|
|||
onClick: PropTypes.func.isRequired
|
||||
},
|
||||
|
||||
displayName: "TreeRow",
|
||||
componentWillReceiveProps(nextProps) {
|
||||
// I don't like accessing the underlying DOM elements directly,
|
||||
// but this optimization makes the filtering so damn fast!
|
||||
// The row doesn't have to be re-rendered, all we really need
|
||||
// to do is toggling a class name.
|
||||
// The important part is that DOM elements don't need to be
|
||||
// re-created when they should appear again.
|
||||
if (nextProps.member.hidden != this.props.member.hidden) {
|
||||
let row = ReactDOM.findDOMNode(this);
|
||||
row.classList.toggle("hidden");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Optimize row rendering. If props are the same do not render.
|
||||
|
|
@ -64,19 +77,6 @@ define(function(require, exports, module) {
|
|||
return false;
|
||||
},
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
// I don't like accessing the underlying DOM elements directly,
|
||||
// but this optimization makes the filtering so damn fast!
|
||||
// The row doesn't have to be re-rendered, all we really need
|
||||
// to do is toggling a class name.
|
||||
// The important part is that DOM elements don't need to be
|
||||
// re-created when they should appear again.
|
||||
if (nextProps.member.hidden != this.props.member.hidden) {
|
||||
let row = ReactDOM.findDOMNode(this);
|
||||
row.classList.toggle("hidden");
|
||||
}
|
||||
},
|
||||
|
||||
getRowClass: function (object) {
|
||||
let decorator = this.props.decorator;
|
||||
if (!decorator || !decorator.getRowClass) {
|
||||
|
|
|
|||
|
|
@ -54,6 +54,8 @@ define(function(require, exports, module) {
|
|||
* }
|
||||
*/
|
||||
let TreeView = React.createClass({
|
||||
displayName: "TreeView",
|
||||
|
||||
// The only required property (not set by default) is the input data
|
||||
// object that is used to puputate the tree.
|
||||
propTypes: {
|
||||
|
|
@ -103,8 +105,6 @@ define(function(require, exports, module) {
|
|||
}))
|
||||
},
|
||||
|
||||
displayName: "TreeView",
|
||||
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
object: null,
|
||||
|
|
|
|||
|
|
@ -48,4 +48,4 @@ module.exports = (opts={}) => {
|
|||
}
|
||||
|
||||
return applyMiddleware(...middleware)(createStore);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,9 +12,9 @@ const DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
|||
*/
|
||||
exports.history = (log = []) => ({ dispatch, getState }) => {
|
||||
if (!DevToolsUtils.testing) {
|
||||
console.warn(`Using history middleware stores all actions in state for testing\
|
||||
and devtools is not currently running in test mode. Be sure this is\
|
||||
intentional.`);
|
||||
console.warn("Using history middleware stores all actions in state for " +
|
||||
"testing and devtools is not currently running in test " +
|
||||
"mode. Be sure this is intentional.");
|
||||
}
|
||||
return next => action => {
|
||||
log.push(action);
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
const uuidgen = require("sdk/util/uuid").uuid;
|
||||
const promise = require("promise");
|
||||
const {
|
||||
entries, toObject, reportException, executeSoon
|
||||
entries, toObject, executeSoon
|
||||
} = require("devtools/shared/DevToolsUtils");
|
||||
const PROMISE = exports.PROMISE = "@@dispatch/promise";
|
||||
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@
|
|||
"use strict";
|
||||
|
||||
const { Task } = require("resource://gre/modules/Task.jsm");
|
||||
const { executeSoon, isGenerator, isPromise, reportException } = require("devtools/shared/DevToolsUtils");
|
||||
const { executeSoon, isGenerator, reportException } = require("devtools/shared/DevToolsUtils");
|
||||
const ERROR_TYPE = exports.ERROR_TYPE = "@@redux/middleware/task#error";
|
||||
|
||||
/**
|
||||
* A middleware that allows generator thunks (functions) and promise
|
||||
* to be dispatched. If it's a generator, it is called with `dispatch` and `getState`,
|
||||
* allowing the action to create multiple actions (most likely
|
||||
* to be dispatched. If it's a generator, it is called with `dispatch`
|
||||
* and `getState`, allowing the action to create multiple actions (most likely
|
||||
* asynchronously) and yield on each. If called with a promise, calls `dispatch`
|
||||
* on the results.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ function waitUntilState (store, predicate) {
|
|||
function check() {
|
||||
if (predicate(store.getState())) {
|
||||
unsubscribe();
|
||||
deferred.resolve()
|
||||
deferred.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ function fetch2 (data) {
|
|||
return {
|
||||
type: "fetch2",
|
||||
data
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function reducer(state = [], action) {
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ function comboAction () {
|
|||
data.async = yield dispatch(fetchAsync("async"));
|
||||
data.sync = yield dispatch(fetchSync("sync"));
|
||||
dispatch({ type: "fetch-done", data });
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function fetchSync(data) {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,6 @@ function thunk({ dispatch, getState }) {
|
|||
return (typeof action === "function")
|
||||
? action(dispatch, getState)
|
||||
: next(action);
|
||||
}
|
||||
};
|
||||
}
|
||||
exports.thunk = thunk;
|
||||
|
|
|
|||
|
|
@ -40,8 +40,7 @@ function waitUntilService({ dispatch, getState }) {
|
|||
for (let request of pending) {
|
||||
if (request.predicate(action)) {
|
||||
readyRequests.push(request);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
stillPending.push(request);
|
||||
}
|
||||
}
|
||||
|
|
@ -55,12 +54,11 @@ function waitUntilService({ dispatch, getState }) {
|
|||
return next => action => {
|
||||
if (action.type === NAME) {
|
||||
pending.push(action);
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
var result = next(action);
|
||||
let result = next(action);
|
||||
checkPending(action);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
exports.waitUntilService = waitUntilService;
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ function makeStateBroadcaster(stillAliveFunc) {
|
|||
enqueuedChanges.forEach(([name, payload]) => {
|
||||
if (listeners[name]) {
|
||||
listeners[name].forEach(listener => {
|
||||
listener(payload)
|
||||
listener(payload);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
@ -115,7 +115,7 @@ function enhanceStoreWithBroadcaster(store, broadcaster) {
|
|||
store.onChange = broadcaster.onChange;
|
||||
store.offChange = broadcaster.offChange;
|
||||
return store;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Function that takes a hash of reducers, like `combineReducers`, and
|
||||
|
|
@ -132,17 +132,20 @@ function combineBroadcastingReducers(reducers, emitChange) {
|
|||
// Wrap each reducer with a wrapper function that calls
|
||||
// the reducer with a third argument, an `emitChange` function.
|
||||
// Use this rather than a new custom top level reducer that would ultimately
|
||||
// have to replicate redux's `combineReducers` so we only pass in correct state,
|
||||
// the error checking, and other edge cases.
|
||||
// have to replicate redux's `combineReducers` so we only pass in correct
|
||||
// state, the error checking, and other edge cases.
|
||||
function wrapReduce(newReducers, key) {
|
||||
newReducers[key] = (state, action) => reducers[key](state, action, emitChange);
|
||||
newReducers[key] = (state, action) => {
|
||||
return reducers[key](state, action, emitChange);
|
||||
};
|
||||
return newReducers;
|
||||
}
|
||||
|
||||
return combineReducers(Object.keys(reducers).reduce(wrapReduce, Object.create(null)));
|
||||
return combineReducers(
|
||||
Object.keys(reducers).reduce(wrapReduce, Object.create(null))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
makeStateBroadcaster,
|
||||
enhanceStoreWithBroadcaster,
|
||||
|
|
|
|||
Loading…
Reference in a new issue