browserUtil.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. browserUtil = {};
  2. browserUtil.isRhino = (typeof(window) === 'undefined');
  3. /**
  4. * Pause (for the graphics to update and the script timer to clear), then run the
  5. * specified action.
  6. */
  7. browserUtil.pauseAndThen = function (cb) {
  8. cb && window.setTimeout(cb, 1);
  9. };
  10. /**
  11. * Iterate using continuation-passing style.
  12. */
  13. browserUtil.cpsIterate = function (f, start, end, pause, callback) {
  14. var pat = pause ? browserUtil.pauseAndThen : function (cb) { cb && cb(); };
  15. function go() {
  16. var called = false;
  17. if (start >= end) {
  18. pat(callback);
  19. } else {
  20. pat(function () { f(start, function () {
  21. if (!called) { called = true; start++; go(); }
  22. }); });
  23. }
  24. }
  25. go (start);
  26. };
  27. /**
  28. * Map a function over an array using continuation-passing style.
  29. */
  30. browserUtil.cpsMap = function (map, list, pause, callback) {
  31. browserUtil.cpsIterate(function (i, cb) { map(list[i], i, list.length, cb); },
  32. 0, list.length, pause, callback);
  33. }
  34. /** Cache for remotely loaded scripts. */
  35. browserUtil.scriptCache = {}
  36. /** Load several scripts, then call back */
  37. browserUtil.loadScripts = function(scriptNames, cbSuccess, cbError) {
  38. var head = document.getElementsByTagName('head')[0];
  39. browserUtil.cpsMap(function (script, i, n, cb) {
  40. var scriptE = document.createElement('script'), xhr, loaded = false;
  41. browserUtil.status("Loading script " + script);
  42. if (window.location.protocol === "file:") {
  43. /* Can't make an AJAX request for files.
  44. * But, we know the load time will be short, so timeout-based error
  45. * detection is fine.
  46. */
  47. scriptE.onload = function () {
  48. loaded = true;
  49. cb();
  50. };
  51. scriptE.onerror = function(err) {
  52. cbError && cbError(script, err, cb);
  53. };
  54. script.onreadystatechange = function() {
  55. if (this.readyState == 'complete' || this.readyState == 'loaded') {
  56. loaded = true;
  57. cb();
  58. }
  59. };
  60. scriptE.type = 'text/javascript';
  61. scriptE.src = script+"?"+(new Date().valueOf());
  62. window.setTimeout(function () {
  63. loaded || cbError && cbError(script, "timeout expired", cb);
  64. }, 100);
  65. head.appendChild(scriptE);
  66. } else if (browserUtil.scriptCache[script] !== undefined) {
  67. try {
  68. scriptE.appendChild(document.createTextNode(browserUtil.scriptCache[script]));
  69. } catch (e) {
  70. scriptE.text = browserUtil.scriptCache[script];
  71. }
  72. head.appendChild(scriptE);
  73. cb();
  74. } else {
  75. var xhr = new XMLHttpRequest();
  76. xhr.onreadystatechange = function() {
  77. if (xhr.readyState == 4) {
  78. if (xhr.status == 200) {
  79. browserUtil.scriptCache[script] = xhr.responseText;
  80. try {
  81. scriptE.appendChild(document.createTextNode(xhr.responseText));
  82. } catch (e) {
  83. scriptE.text = xhr.responseText;
  84. }
  85. head.appendChild(scriptE);
  86. cb();
  87. } else {
  88. cbError && cbError(script, xhr.status, cb);
  89. }
  90. }
  91. }
  92. xhr.open("GET", script+"?"+(new Date().valueOf()), true);
  93. xhr.send();
  94. }
  95. }, scriptNames, false, cbSuccess);
  96. };
  97. /** Write a message to the console */
  98. browserUtil.write = function(type, message) {
  99. var d1 = document.getElementById("print"), d2 = document.createElement("div"), d3 = document.createElement("div");
  100. d3.className = type;
  101. d3.appendChild(document.createTextNode(message));
  102. d2.appendChild(d3);
  103. d1.appendChild(d2);
  104. return { update: function (type2, message2) {
  105. var d4 = document.createElement("div");
  106. d4.className = type2 + " also";
  107. d4.appendChild(document.createTextNode(message2));
  108. d2.insertBefore(d4, d3);
  109. }};
  110. };
  111. /** Write a newline. Does nothing in the browser. */
  112. browserUtil.writeNewline = function () { };
  113. /** Write a message to the status line */
  114. browserUtil.status = function(message) {
  115. var d1 = document.getElementById("status");
  116. d1.replaceChild(document.createTextNode(message), d1.firstChild);
  117. };