1. 1 : /**
  2. 2 : * @module Mel/UsefulFunctions
  3. 3 : */
  4. 4 :
  5. 5 : export {
  6. 6 : isNullOrUndefined,
  7. 7 : isArrayLike,
  8. 8 : Classes,
  9. 9 : toHex,
  10. 10 : isDecimal,
  11. 11 : capitalize,
  12. 12 : getRelativePos,
  13. 13 : isAsync,
  14. 14 : };
  15. 15 :
  16. 16 : /**
  17. 17 : * Vérivie si un nombre est un nombre entier ou décimal.
  18. 18 : * @param {number} number
  19. 19 : * @returns {boolean} Si vrai, alors il s'agit d'un nombre décimal.
  20. 20 : * @example const state = isDecimal(value) ? 1 : 0;
  21. 21 : */
  22. 22 : function isDecimal(number) {
  23. 23 : return ~~number !== number;
  24. 24 : }
  25. 25 :
  26. 26 : /**
  27. 27 : * Renvoie vrai si la variable vaut `null` ou `undefined`.
  28. 28 : * @param {?*} item Variable à tester
  29. 29 : * @returns {boolean}
  30. 30 : */
  31. 31 : function isNullOrUndefined(item) {
  32. 32 : return item === null || item === undefined;
  33. 33 : }
  34. 34 :
  35. 35 : /**
  36. 36 : * Vérifie si une varible est un tableau ou quelque chose qui y ressemble
  37. 37 : * @param {*} item
  38. 38 : * @returns {bool}
  39. 39 : */
  40. 40 : function isArrayLike(item) {
  41. 41 : return (
  42. 42 : !!item &&
  43. 43 : typeof item === 'object' &&
  44. 44 : // eslint-disable-next-line no-prototype-builtins
  45. 45 : item.hasOwnProperty('length') &&
  46. 46 : typeof item.length === 'number' &&
  47. 47 : item.length > 0 &&
  48. 48 : item.length - 1 in item
  49. 49 : );
  50. 50 : }
  51. 51 :
  52. 52 : /**
  53. 53 : * Change un nombre en base 10 en hexadécimal
  54. 54 : * @param {number} number
  55. 55 : * @returns {string} Hexadecimal number
  56. 56 : */
  57. 57 : function toHex(number) {
  58. 58 : return number.toString(16);
  59. 59 : }
  60. 60 :
  61. 61 : /**
  62. 62 : * @typedef Class
  63. 63 : * Indique qu'il s'agit d'un objet qui est une classe. Le mot clé "new" peut être utiliser.
  64. 64 : */
  65. 65 :
  66. 66 : /**
  67. 67 : * @typedef Classes
  68. 68 : * Indique qu'il s'agit d'un mélange de plusieurs classes. Le mot clé "new" peut être utiliser.
  69. 69 : */
  70. 70 :
  71. 71 : /**
  72. 72 : * Permet de créer une "fusion" de deux classes.
  73. 73 : *
  74. 74 : * Cela permet d'avoir une classe qui hérite de 2 classe.
  75. 75 : * @param {Class} baseClass Classe de base
  76. 76 : * @param {...Classes} mixins Autres classes
  77. 77 : * @returns {}
  78. 78 : */
  79. 79 : const Classes = (baseClass, ...mixins) => {
  80. 80 : class base extends baseClass {
  81. 81 : constructor(...args) {
  82. 82 : super(...args);
  83. 83 : mixins.forEach((mixin) => {
  84. 84 : copyProps(this, new mixin());
  85. 85 : });
  86. 86 : }
  87. 87 : }
  88. 88 : let copyProps = (target, source) => {
  89. 89 : // this function copies all properties and symbols, filtering out some special ones
  90. 90 : Object.getOwnPropertyNames(source)
  91. 91 : .concat(Object.getOwnPropertySymbols(source))
  92. 92 : .forEach((prop) => {
  93. 93 : if (
  94. 94 : !prop.match(
  95. 95 : /^(?:constructor|prototype|arguments|caller|name|bind|call|apply|toString|length)$/,
  96. 96 : )
  97. 97 : )
  98. 98 : Object.defineProperty(
  99. 99 : target,
  100. 100 : prop,
  101. 101 : Object.getOwnPropertyDescriptor(source, prop),
  102. 102 : );
  103. 103 : });
  104. 104 : };
  105. 105 : mixins.forEach((mixin) => {
  106. 106 : // outside contructor() to allow aggregation(A,B,C).staticFunction() to be called etc.
  107. 107 : copyProps(base.prototype, mixin.prototype);
  108. 108 : copyProps(base, mixin);
  109. 109 : });
  110. 110 : return base;
  111. 111 : };
  112. 112 :
  113. 113 : function capitalize(s) {
  114. 114 : if (typeof s !== 'string') return '';
  115. 115 :
  116. 116 : s = s.toLowerCase();
  117. 117 : return s.charAt(0).toUpperCase() + s.slice(1);
  118. 118 : }
  119. 119 :
  120. 120 : function getRelativePos(elm) {
  121. 121 : let pPos = elm.parentNode.getBoundingClientRect(), // parent pos
  122. 122 : cPos = elm.getBoundingClientRect(), // target pos
  123. 123 : pos = {};
  124. 124 :
  125. 125 : (pos.top = cPos.top - pPos.top + elm.parentNode.scrollTop),
  126. 126 : (pos.right = cPos.right - pPos.right),
  127. 127 : (pos.bottom = cPos.bottom - pPos.bottom),
  128. 128 : (pos.left = cPos.left - pPos.left);
  129. 129 :
  130. 130 : return pos;
  131. 131 : }
  132. 132 :
  133. 133 : function isAsync(func) {
  134. 134 : return func.constructor.name === 'AsyncFunction';
  135. 135 : }