grip-array.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. "use strict";
  6. // Make this available to both AMD and CJS environments
  7. define(function (require, exports, module) {
  8. // Dependencies
  9. const React = require("devtools/client/shared/vendor/react");
  10. const { createFactories, isGrip } = require("./rep-utils");
  11. const { Caption } = createFactories(require("./caption"));
  12. // Shortcuts
  13. const { span } = React.DOM;
  14. /**
  15. * Renders an array. The array is enclosed by left and right bracket
  16. * and the max number of rendered items depends on the current mode.
  17. */
  18. let GripArray = React.createClass({
  19. displayName: "GripArray",
  20. propTypes: {
  21. object: React.PropTypes.object.isRequired,
  22. mode: React.PropTypes.string,
  23. provider: React.PropTypes.object,
  24. },
  25. getLength: function (grip) {
  26. if (!grip.preview) {
  27. return 0;
  28. }
  29. return grip.preview.length || grip.preview.childNodesLength || 0;
  30. },
  31. getTitle: function (object, context) {
  32. let objectLink = this.props.objectLink || span;
  33. if (this.props.mode != "tiny") {
  34. return objectLink({
  35. object: object
  36. }, object.class + " ");
  37. }
  38. return "";
  39. },
  40. getPreviewItems: function (grip) {
  41. if (!grip.preview) {
  42. return null;
  43. }
  44. return grip.preview.items || grip.preview.childNodes || null;
  45. },
  46. arrayIterator: function (grip, max) {
  47. let items = [];
  48. const gripLength = this.getLength(grip);
  49. if (!gripLength) {
  50. return items;
  51. }
  52. const previewItems = this.getPreviewItems(grip);
  53. if (!previewItems) {
  54. return items;
  55. }
  56. let delim;
  57. // number of grip preview items is limited to 10, but we may have more
  58. // items in grip-array.
  59. let delimMax = gripLength > previewItems.length ?
  60. previewItems.length : previewItems.length - 1;
  61. let provider = this.props.provider;
  62. for (let i = 0; i < previewItems.length && i < max; i++) {
  63. try {
  64. let itemGrip = previewItems[i];
  65. let value = provider ? provider.getValue(itemGrip) : itemGrip;
  66. delim = (i == delimMax ? "" : ", ");
  67. items.push(GripArrayItem(Object.assign({}, this.props, {
  68. object: value,
  69. delim: delim
  70. })));
  71. } catch (exc) {
  72. items.push(GripArrayItem(Object.assign({}, this.props, {
  73. object: exc,
  74. delim: delim
  75. })));
  76. }
  77. }
  78. if (previewItems.length > max || gripLength > previewItems.length) {
  79. let objectLink = this.props.objectLink || span;
  80. let leftItemNum = gripLength - max > 0 ?
  81. gripLength - max : gripLength - previewItems.length;
  82. items.push(Caption({
  83. object: objectLink({
  84. object: this.props.object
  85. }, leftItemNum + " more…")
  86. }));
  87. }
  88. return items;
  89. },
  90. render: function () {
  91. let mode = this.props.mode || "short";
  92. let object = this.props.object;
  93. let items;
  94. let brackets;
  95. let needSpace = function (space) {
  96. return space ? { left: "[ ", right: " ]"} : { left: "[", right: "]"};
  97. };
  98. if (mode == "tiny") {
  99. let objectLength = this.getLength(object);
  100. let isEmpty = objectLength === 0;
  101. items = [span({className: "length"}, isEmpty ? "" : objectLength)];
  102. brackets = needSpace(false);
  103. } else {
  104. let max = (mode == "short") ? 3 : 300;
  105. items = this.arrayIterator(object, max);
  106. brackets = needSpace(items.length > 0);
  107. }
  108. let objectLink = this.props.objectLink || span;
  109. let title = this.getTitle(object);
  110. return (
  111. span({
  112. className: "objectBox objectBox-array"},
  113. title,
  114. objectLink({
  115. className: "arrayLeftBracket",
  116. object: object
  117. }, brackets.left),
  118. ...items,
  119. objectLink({
  120. className: "arrayRightBracket",
  121. object: object
  122. }, brackets.right),
  123. span({
  124. className: "arrayProperties",
  125. role: "group"}
  126. )
  127. )
  128. );
  129. },
  130. });
  131. /**
  132. * Renders array item. Individual values are separated by
  133. * a delimiter (a comma by default).
  134. */
  135. let GripArrayItem = React.createFactory(React.createClass({
  136. displayName: "GripArrayItem",
  137. propTypes: {
  138. delim: React.PropTypes.string,
  139. },
  140. render: function () {
  141. let { Rep } = createFactories(require("./rep"));
  142. return (
  143. span({},
  144. Rep(Object.assign({}, this.props, {
  145. mode: "tiny"
  146. })),
  147. this.props.delim
  148. )
  149. );
  150. }
  151. }));
  152. function supportsObject(grip, type) {
  153. if (!isGrip(grip)) {
  154. return false;
  155. }
  156. return (grip.preview && (
  157. grip.preview.kind == "ArrayLike" ||
  158. type === "DocumentFragment"
  159. )
  160. );
  161. }
  162. // Exports from this module
  163. exports.GripArray = {
  164. rep: GripArray,
  165. supportsObject: supportsObject
  166. };
  167. });