You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

adopter.js 3.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. import { addMethodNames } from './methods.js'
  2. import { capitalize } from './utils.js'
  3. import { svg } from '../modules/core/namespaces.js'
  4. import { globals } from '../utils/window.js'
  5. import Base from '../types/Base.js'
  6. const elements = {}
  7. export const root = '___SYMBOL___ROOT___'
  8. // Method for element creation
  9. export function create (name, ns = svg) {
  10. // create element
  11. return globals.document.createElementNS(ns, name)
  12. }
  13. export function makeInstance (element, isHTML = false) {
  14. if (element instanceof Base) return element
  15. if (typeof element === 'object') {
  16. return adopter(element)
  17. }
  18. if (element == null) {
  19. return new elements[root]()
  20. }
  21. if (typeof element === 'string' && element.charAt(0) !== '<') {
  22. return adopter(globals.document.querySelector(element))
  23. }
  24. // Make sure, that HTML elements are created with the correct namespace
  25. const wrapper = isHTML ? globals.document.createElement('div') : create('svg')
  26. wrapper.innerHTML = element
  27. // We can use firstChild here because we know,
  28. // that the first char is < and thus an element
  29. element = adopter(wrapper.firstChild)
  30. // make sure, that element doesn't have its wrapper attached
  31. wrapper.removeChild(wrapper.firstChild)
  32. return element
  33. }
  34. export function nodeOrNew (name, node) {
  35. return (node && node.ownerDocument && node instanceof node.ownerDocument.defaultView.Node) ? node : create(name)
  36. }
  37. // Adopt existing svg elements
  38. export function adopt (node) {
  39. // check for presence of node
  40. if (!node) return null
  41. // make sure a node isn't already adopted
  42. if (node.instance instanceof Base) return node.instance
  43. if (node.nodeName === '#document-fragment') {
  44. return new elements.Fragment(node)
  45. }
  46. // initialize variables
  47. let className = capitalize(node.nodeName || 'Dom')
  48. // Make sure that gradients are adopted correctly
  49. if (className === 'LinearGradient' || className === 'RadialGradient') {
  50. className = 'Gradient'
  51. // Fallback to Dom if element is not known
  52. } else if (!elements[className]) {
  53. className = 'Dom'
  54. }
  55. return new elements[className](node)
  56. }
  57. let adopter = adopt
  58. export function mockAdopt (mock = adopt) {
  59. adopter = mock
  60. }
  61. export function register (element, name = element.name, asRoot = false) {
  62. elements[name] = element
  63. if (asRoot) elements[root] = element
  64. addMethodNames(Object.getOwnPropertyNames(element.prototype))
  65. return element
  66. }
  67. export function getClass (name) {
  68. return elements[name]
  69. }
  70. // Element id sequence
  71. let did = 1000
  72. // Get next named element id
  73. export function eid (name) {
  74. return 'Svgjs' + capitalize(name) + (did++)
  75. }
  76. // Deep new id assignment
  77. export function assignNewId (node) {
  78. // do the same for SVG child nodes as well
  79. for (let i = node.children.length - 1; i >= 0; i--) {
  80. assignNewId(node.children[i])
  81. }
  82. if (node.id) {
  83. node.id = eid(node.nodeName)
  84. return node
  85. }
  86. return node
  87. }
  88. // Method for extending objects
  89. export function extend (modules, methods) {
  90. let key, i
  91. modules = Array.isArray(modules) ? modules : [ modules ]
  92. for (i = modules.length - 1; i >= 0; i--) {
  93. for (key in methods) {
  94. modules[i].prototype[key] = methods[key]
  95. }
  96. }
  97. }
  98. export function wrapWithAttrCheck (fn) {
  99. return function (...args) {
  100. const o = args[args.length - 1]
  101. if (o && o.constructor === Object && !(o instanceof Array)) {
  102. return fn.apply(this, args.slice(0, -1)).attr(o)
  103. } else {
  104. return fn.apply(this, args)
  105. }
  106. }
  107. }