Formula.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. /**
  2. * Formula.js
  3. *
  4. * @author realor
  5. */
  6. import { ObjectUtils } from '../utils/ObjectUtils.js'
  7. class Formula {
  8. /* Formula contructor: new Formula("position.x", "position.y + 1") */
  9. constructor(path, expression) {
  10. this.path = path
  11. this.expression = expression
  12. this.getFn = new Function('object', 'return object.' + path)
  13. this.setFn = ObjectUtils.createEvalFunction('object.' + path + '=' + expression)
  14. }
  15. evaluate(object) {
  16. return this.setFn(object)
  17. }
  18. /* static methods */
  19. static create(object, path, expression, evaluate = true) {
  20. if (object.formulas === undefined) {
  21. object.formulas = {}
  22. }
  23. const formula = new Formula(path, expression)
  24. if (evaluate) formula.evaluate(object)
  25. object.formulas[path] = formula
  26. return formula
  27. }
  28. static set(object, formula, evaluate = true) {
  29. if (object.formulas === undefined) {
  30. object.formulas = {}
  31. }
  32. if (evaluate) formula.evaluate(object)
  33. object.formulas[formula.path] = formula
  34. return formula
  35. }
  36. static get(object, path) {
  37. if (object.formulas) {
  38. return object.formulas[path]
  39. }
  40. }
  41. static getAll(object) {
  42. return object.formulas
  43. }
  44. static remove(object, path) {
  45. if (object.formulas) {
  46. if (path) {
  47. delete object.formulas[path]
  48. } else {
  49. object.formulas = {}
  50. }
  51. }
  52. }
  53. static isDefined(object, path = '') {
  54. if (object.formulas) {
  55. for (let key in object.formulas) {
  56. if (key.startsWith(path)) {
  57. return true
  58. }
  59. }
  60. }
  61. return false
  62. }
  63. static eval(object, path) {
  64. if (object.formulas) {
  65. const formula = object.formulas[path]
  66. if (formula) {
  67. return formula.evaluate(object)
  68. }
  69. }
  70. }
  71. static update(object, path = '', prefix = path === '' ? true : false) {
  72. let updated = false
  73. if (object.formulas) {
  74. if (prefix) {
  75. const formulas = object.formulas
  76. for (let key in formulas) {
  77. if (key.startsWith(path)) {
  78. let formula = formulas[key]
  79. const oldValue = formula.getFn(object)
  80. const newValue = formula.setFn(object)
  81. updated = updated || oldValue !== newValue
  82. }
  83. }
  84. } else {
  85. const formula = object.formulas[path]
  86. if (formula) {
  87. const oldValue = formula.getFn(object)
  88. const newValue = formula.setFn(object)
  89. updated = oldValue !== newValue
  90. }
  91. }
  92. }
  93. return updated
  94. }
  95. static updateTree(object, path = '', prefix = path === '' ? true : false) {
  96. const updatedObjects = []
  97. const updateFormulas = object => {
  98. if (Formula.update(object, path, prefix)) {
  99. updatedObjects.push(object)
  100. }
  101. for (let child of object.children) {
  102. updateFormulas(child)
  103. }
  104. }
  105. updateFormulas(object)
  106. return updatedObjects
  107. }
  108. static copy(target, source) {
  109. if (target.formulas === undefined) {
  110. target.formulas = {}
  111. }
  112. const targetFormulas = target.formulas
  113. const sourceFormulas = source.formulas
  114. for (let path in sourceFormulas) {
  115. targetFormulas[path] = sourceFormulas[path]
  116. }
  117. }
  118. }
  119. export { Formula }