utils.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /**
  2. * This JS file contains utils functions
  3. */
  4. class Utils {
  5. constructor(parent) {
  6. this.parent = parent;
  7. this.multipleSize = [1280, 1024, 'Mobile'];
  8. }
  9. /**
  10. * When something is written in the editor, it reset the safe mode
  11. */
  12. markDirty() {
  13. if (this.parent.monacoCreator.BlockEditorChange) return;
  14. this.setToMultipleID("safemodeToggle", "addClass", "checked");
  15. !
  16. this.setToMultipleID('safemodeToggle', 'innerHTML', 'Safe mode <i class="fa fa-check-square" aria-hidden="true"></i>');
  17. };
  18. toLocationError(errorMessage, errorEvent) {
  19. if (!errorEvent) {
  20. return null;
  21. }
  22. // Do we have any location info?
  23. if (errorEvent.hasOwnProperty('lineNumber') && errorEvent.hasOwnProperty('columnNumber'))
  24. return errorEvent;
  25. // Else try to parse the stack to retrieve location...
  26. var regEx = /\(.+:(\d+):(\d+)\)\n/g;
  27. var match = regEx.exec(errorEvent.stack);
  28. if (match) {
  29. var error = new EvalError(errorMessage);
  30. error.lineNumber = match[1];
  31. error.columnNumber = match[2];
  32. return error;
  33. }
  34. // Not an error with proper location
  35. return null;
  36. }
  37. /**
  38. * Used to show error messages
  39. * @param {String} errorMessage
  40. * @param {String} errorEvent
  41. */
  42. showError(errorMessage, errorEvent) {
  43. let errorContent = '<div class="alert alert-error"><button type="button" class="close" data-dismiss="alert">&times;</button>';
  44. const locationError = this.toLocationError(errorMessage, errorEvent);
  45. if (locationError == null) {
  46. // use a regular message
  47. errorContent += `${errorMessage}</div>`;
  48. } else {
  49. // we have location information
  50. errorContent += `<span id="gotoLocation">Line ${locationError.lineNumber} : ${locationError.columnNumber} - ${errorMessage}</span></div>`;
  51. }
  52. document.getElementById("errorZone").style.display = 'block';
  53. document.getElementById("errorZone").innerHTML = errorContent;
  54. // Close button error
  55. document.getElementById("errorZone").querySelector('.close').addEventListener('click', function () {
  56. document.getElementById("errorZone").style.display = 'none';
  57. });
  58. // Go To Location
  59. const gotoLocation = document.getElementById("gotoLocation");
  60. const jsEditor = this.parent.monacoCreator.jsEditor;
  61. if (gotoLocation) {
  62. gotoLocation.addEventListener('click', function () {
  63. const position = {
  64. lineNumber: Number(locationError.lineNumber),
  65. column: Number(locationError.columnNumber)
  66. };
  67. jsEditor.revealPositionInCenter(position, monaco.editor.ScrollType.Smooth);
  68. jsEditor.setPosition(position);
  69. });
  70. }
  71. };
  72. /**
  73. * Apply things to the differents menu sizes
  74. */
  75. setToMultipleID(id, thingToDo, param) {
  76. this.multipleSize.forEach(function (size) {
  77. if (thingToDo == "innerHTML") {
  78. document.getElementById(id + size).innerHTML = param
  79. } else if (thingToDo == "click") {
  80. if (param.length > 1) {
  81. for (var i = 0; i < param.length; i++) {
  82. document.getElementById(id + size).addEventListener("click", param[i]);
  83. }
  84. } else
  85. document.getElementById(id + size).addEventListener("click", param);
  86. } else if (thingToDo == "addClass") {
  87. document.getElementById(id + size).classList.add(param);
  88. } else if (thingToDo == "removeClass") {
  89. document.getElementById(id + size).classList.remove(param);
  90. } else if (thingToDo == "display") {
  91. document.getElementById(id + size).style.display = param;
  92. } else if (thingToDo === "title") {
  93. document.getElementById(id + size).setAttribute("title", param);
  94. }
  95. });
  96. };
  97. /**
  98. * Function to get the current screen size
  99. */
  100. getCurrentSize() {
  101. for (var i = 0; i < this.multipleSize.length; i++) {
  102. if (document.getElementById("menuButton" + this.multipleSize[i]).offsetHeight > 0) return this.multipleSize[i];
  103. }
  104. };
  105. debounceAsync(fn, wait = 0, options = {}) {
  106. let lastCallAt
  107. let deferred
  108. let timer
  109. let pendingArgs = []
  110. return function debounced(...args) {
  111. const currentWait = getWait(wait)
  112. const currentTime = new Date().getTime()
  113. const isCold = !lastCallAt || (currentTime - lastCallAt) > currentWait
  114. lastCallAt = currentTime
  115. if (isCold && options.leading) {
  116. return options.accumulate ?
  117. Promise.resolve(fn.call(this, [args])).then(result => result[0]) :
  118. Promise.resolve(fn.call(this, ...args))
  119. }
  120. if (deferred) {
  121. clearTimeout(timer)
  122. } else {
  123. deferred = defer()
  124. }
  125. pendingArgs.push(args)
  126. timer = setTimeout(flush.bind(this), currentWait)
  127. if (options.accumulate) {
  128. const argsIndex = pendingArgs.length - 1
  129. return deferred.promise.then(results => results[argsIndex])
  130. }
  131. return deferred.promise
  132. }
  133. function getWait(wait) {
  134. return (typeof wait === 'function') ? wait() : wait
  135. }
  136. function defer() {
  137. const deferred = {}
  138. deferred.promise = new Promise((resolve, reject) => {
  139. deferred.resolve = resolve
  140. deferred.reject = reject
  141. })
  142. return deferred
  143. }
  144. function flush() {
  145. const thisDeferred = deferred
  146. clearTimeout(timer)
  147. Promise.resolve(
  148. options.accumulate ?
  149. fn.call(this, pendingArgs) :
  150. fn.apply(this, pendingArgs[pendingArgs.length - 1])
  151. )
  152. .then(thisDeferred.resolve, thisDeferred.reject)
  153. pendingArgs = []
  154. deferred = null
  155. }
  156. }
  157. }