nodes.js 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. var _ = require("underscore");
  2. exports.Element = Element;
  3. exports.element = function(name, attributes, children) {
  4. return new Element(name, attributes, children);
  5. };
  6. exports.text = function(value) {
  7. return {
  8. type: "text",
  9. value: value
  10. };
  11. };
  12. var emptyElement = {
  13. first: function() {
  14. return null;
  15. },
  16. firstOrEmpty: function() {
  17. return emptyElement;
  18. },
  19. attributes: {}
  20. };
  21. function Element(name, attributes, children) {
  22. this.type = "element";
  23. this.name = name;
  24. this.attributes = attributes || {};
  25. this.children = children || [];
  26. }
  27. Element.prototype.first = function(name) {
  28. return _.find(this.children, function(child) {
  29. return child.name === name;
  30. });
  31. };
  32. Element.prototype.firstOrEmpty = function(name) {
  33. return this.first(name) || emptyElement;
  34. };
  35. Element.prototype.getElementsByTagName = function(name) {
  36. var elements = _.filter(this.children, function(child) {
  37. return child.name === name;
  38. });
  39. return toElementList(elements);
  40. };
  41. Element.prototype.text = function() {
  42. if (this.children.length === 0) {
  43. return "";
  44. } else if (this.children.length !== 1 || this.children[0].type !== "text") {
  45. throw new Error("Not implemented");
  46. }
  47. return this.children[0].value;
  48. };
  49. var elementListPrototype = {
  50. getElementsByTagName: function(name) {
  51. return toElementList(_.flatten(this.map(function(element) {
  52. return element.getElementsByTagName(name);
  53. }, true)));
  54. }
  55. };
  56. function toElementList(array) {
  57. return _.extend(array, elementListPrototype);
  58. }