array.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  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 } = require("./rep-utils");
  11. const { Caption } = createFactories(require("./caption"));
  12. // Shortcuts
  13. const DOM = 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 ArrayRep = React.createClass({
  19. displayName: "ArrayRep",
  20. getTitle: function (object, context) {
  21. return "[" + object.length + "]";
  22. },
  23. arrayIterator: function (array, max) {
  24. let items = [];
  25. let delim;
  26. for (let i = 0; i < array.length && i < max; i++) {
  27. try {
  28. let value = array[i];
  29. delim = (i == array.length - 1 ? "" : ", ");
  30. items.push(ItemRep({
  31. object: value,
  32. // Hardcode tiny mode to avoid recursive handling.
  33. mode: "tiny",
  34. delim: delim
  35. }));
  36. } catch (exc) {
  37. items.push(ItemRep({
  38. object: exc,
  39. mode: "tiny",
  40. delim: delim
  41. }));
  42. }
  43. }
  44. if (array.length > max) {
  45. let objectLink = this.props.objectLink || DOM.span;
  46. items.push(Caption({
  47. object: objectLink({
  48. object: this.props.object
  49. }, (array.length - max) + " more…")
  50. }));
  51. }
  52. return items;
  53. },
  54. /**
  55. * Returns true if the passed object is an array with additional (custom)
  56. * properties, otherwise returns false. Custom properties should be
  57. * displayed in extra expandable section.
  58. *
  59. * Example array with a custom property.
  60. * let arr = [0, 1];
  61. * arr.myProp = "Hello";
  62. *
  63. * @param {Array} array The array object.
  64. */
  65. hasSpecialProperties: function (array) {
  66. function isInteger(x) {
  67. let y = parseInt(x, 10);
  68. if (isNaN(y)) {
  69. return false;
  70. }
  71. return x === y.toString();
  72. }
  73. let props = Object.getOwnPropertyNames(array);
  74. for (let i = 0; i < props.length; i++) {
  75. let p = props[i];
  76. // Valid indexes are skipped
  77. if (isInteger(p)) {
  78. continue;
  79. }
  80. // Ignore standard 'length' property, anything else is custom.
  81. if (p != "length") {
  82. return true;
  83. }
  84. }
  85. return false;
  86. },
  87. // Event Handlers
  88. onToggleProperties: function (event) {
  89. },
  90. onClickBracket: function (event) {
  91. },
  92. render: function () {
  93. let mode = this.props.mode || "short";
  94. let object = this.props.object;
  95. let items;
  96. let brackets;
  97. let needSpace = function (space) {
  98. return space ? { left: "[ ", right: " ]"} : { left: "[", right: "]"};
  99. };
  100. if (mode == "tiny") {
  101. let isEmpty = object.length === 0;
  102. items = [DOM.span({className: "length"}, isEmpty ? "" : object.length)];
  103. brackets = needSpace(false);
  104. } else {
  105. let max = (mode == "short") ? 3 : 300;
  106. items = this.arrayIterator(object, max);
  107. brackets = needSpace(items.length > 0);
  108. }
  109. let objectLink = this.props.objectLink || DOM.span;
  110. return (
  111. DOM.span({
  112. className: "objectBox objectBox-array"},
  113. objectLink({
  114. className: "arrayLeftBracket",
  115. object: object
  116. }, brackets.left),
  117. ...items,
  118. objectLink({
  119. className: "arrayRightBracket",
  120. object: object
  121. }, brackets.right),
  122. DOM.span({
  123. className: "arrayProperties",
  124. role: "group"}
  125. )
  126. )
  127. );
  128. },
  129. });
  130. /**
  131. * Renders array item. Individual values are separated by a comma.
  132. */
  133. let ItemRep = React.createFactory(React.createClass({
  134. displayName: "ItemRep",
  135. render: function () {
  136. const { Rep } = createFactories(require("./rep"));
  137. let object = this.props.object;
  138. let delim = this.props.delim;
  139. let mode = this.props.mode;
  140. return (
  141. DOM.span({},
  142. Rep({object: object, mode: mode}),
  143. delim
  144. )
  145. );
  146. }
  147. }));
  148. function supportsObject(object, type) {
  149. return Array.isArray(object) ||
  150. Object.prototype.toString.call(object) === "[object Arguments]";
  151. }
  152. // Exports from this module
  153. exports.ArrayRep = {
  154. rep: ArrayRep,
  155. supportsObject: supportsObject
  156. };
  157. });