element-node.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  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. // ReactJS
  9. const React = require("devtools/client/shared/vendor/react");
  10. const { isGrip } = require("./rep-utils");
  11. // Utils
  12. const nodeConstants = require("devtools/shared/dom-node-constants");
  13. // Shortcuts
  14. const { span } = React.DOM;
  15. /**
  16. * Renders DOM element node.
  17. */
  18. const ElementNode = React.createClass({
  19. displayName: "ElementNode",
  20. propTypes: {
  21. object: React.PropTypes.object.isRequired,
  22. mode: React.PropTypes.string,
  23. },
  24. getElements: function (grip, mode) {
  25. let {attributes, nodeName} = grip.preview;
  26. const nodeNameElement = span({
  27. className: "tag-name theme-fg-color3"
  28. }, nodeName);
  29. if (mode === "tiny") {
  30. let elements = [nodeNameElement];
  31. if (attributes.id) {
  32. elements.push(
  33. span({className: "attr-name theme-fg-color2"}, `#${attributes.id}`));
  34. }
  35. if (attributes.class) {
  36. elements.push(
  37. span({className: "attr-name theme-fg-color2"},
  38. attributes.class
  39. .replace(/(^\s+)|(\s+$)/g, "")
  40. .split(" ")
  41. .map(cls => `.${cls}`)
  42. .join("")
  43. )
  44. );
  45. }
  46. return elements;
  47. }
  48. let attributeElements = Object.keys(attributes)
  49. .sort(function getIdAndClassFirst(a1, a2) {
  50. if ([a1, a2].includes("id")) {
  51. return 3 * (a1 === "id" ? -1 : 1);
  52. }
  53. if ([a1, a2].includes("class")) {
  54. return 2 * (a1 === "class" ? -1 : 1);
  55. }
  56. // `id` and `class` excepted,
  57. // we want to keep the same order that in `attributes`.
  58. return 0;
  59. })
  60. .reduce((arr, name, i, keys) => {
  61. let value = attributes[name];
  62. let attribute = span({},
  63. span({className: "attr-name theme-fg-color2"}, `${name}`),
  64. `="`,
  65. span({className: "attr-value theme-fg-color6"}, `${value}`),
  66. `"`
  67. );
  68. return arr.concat([" ", attribute]);
  69. }, []);
  70. return [
  71. "<",
  72. nodeNameElement,
  73. ...attributeElements,
  74. ">",
  75. ];
  76. },
  77. render: function () {
  78. let {object, mode} = this.props;
  79. let elements = this.getElements(object, mode);
  80. const baseElement = span({className: "objectBox"}, ...elements);
  81. if (this.props.objectLink) {
  82. return this.props.objectLink({object}, baseElement);
  83. }
  84. return baseElement;
  85. },
  86. });
  87. // Registration
  88. function supportsObject(object, type) {
  89. if (!isGrip(object)) {
  90. return false;
  91. }
  92. return object.preview && object.preview.nodeType === nodeConstants.ELEMENT_NODE;
  93. }
  94. // Exports from this module
  95. exports.ElementNode = {
  96. rep: ElementNode,
  97. supportsObject: supportsObject
  98. };
  99. });