moveElemsAttrsToGroup.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. 'use strict';
  2. exports.type = 'perItemReverse';
  3. exports.active = true;
  4. exports.description = 'moves elements attributes to the existing group wrapper';
  5. var inheritableAttrs = require('./_collections').inheritableAttrs,
  6. pathElems = require('./_collections.js').pathElems;
  7. /**
  8. * Collapse content's intersected and inheritable
  9. * attributes to the existing group wrapper.
  10. *
  11. * @example
  12. * <g attr1="val1">
  13. * <g attr2="val2">
  14. * text
  15. * </g>
  16. * <circle attr2="val2" attr3="val3"/>
  17. * </g>
  18. * ⬇
  19. * <g attr1="val1" attr2="val2">
  20. * <g>
  21. * text
  22. * </g>
  23. * <circle attr3="val3"/>
  24. * </g>
  25. *
  26. * @param {Object} item current iteration item
  27. * @return {Boolean} if false, item will be filtered out
  28. *
  29. * @author Kir Belevich
  30. */
  31. exports.fn = function(item) {
  32. if (item.isElem('g') && !item.isEmpty() && item.content.length > 1) {
  33. var intersection = {},
  34. hasTransform = false,
  35. hasClip = item.hasAttr('clip-path') || item.hasAttr('mask'),
  36. intersected = item.content.every(function(inner) {
  37. if (inner.isElem() && inner.hasAttr()) {
  38. // don't mess with possible styles (hack until CSS parsing is implemented)
  39. if (inner.hasAttr('class')) return false;
  40. if (!Object.keys(intersection).length) {
  41. intersection = inner.attrs;
  42. } else {
  43. intersection = intersectInheritableAttrs(intersection, inner.attrs);
  44. if (!intersection) return false;
  45. }
  46. return true;
  47. }
  48. }),
  49. allPath = item.content.every(function(inner) {
  50. return inner.isElem(pathElems);
  51. });
  52. if (intersected) {
  53. item.content.forEach(function(g) {
  54. for (var name in intersection) {
  55. if (!allPath && !hasClip || name !== 'transform') {
  56. g.removeAttr(name);
  57. if (name === 'transform') {
  58. if (!hasTransform) {
  59. if (item.hasAttr('transform')) {
  60. item.attr('transform').value += ' ' + intersection[name].value;
  61. } else {
  62. item.addAttr(intersection[name]);
  63. }
  64. hasTransform = true;
  65. }
  66. } else {
  67. item.addAttr(intersection[name]);
  68. }
  69. }
  70. }
  71. });
  72. }
  73. }
  74. };
  75. /**
  76. * Intersect inheritable attributes.
  77. *
  78. * @param {Object} a first attrs object
  79. * @param {Object} b second attrs object
  80. *
  81. * @return {Object} intersected attrs object
  82. */
  83. function intersectInheritableAttrs(a, b) {
  84. var c = {};
  85. for (var n in a) {
  86. if (
  87. b.hasOwnProperty(n) &&
  88. inheritableAttrs.indexOf(n) > -1 &&
  89. a[n].name === b[n].name &&
  90. a[n].value === b[n].value &&
  91. a[n].prefix === b[n].prefix &&
  92. a[n].local === b[n].local
  93. ) {
  94. c[n] = a[n];
  95. }
  96. }
  97. if (!Object.keys(c).length) return false;
  98. return c;
  99. }