ajax.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. // -*- Mode: JavaScript; tab-width: 2; indent-tabs-mode: nil; -*-
  2. // vim:set ft=javascript ts=2 sw=2 sts=2 cindent:
  3. var Ajax = (function($, window, undefined) {
  4. var PROTOCOL_VERSION = 1
  5. var Ajax = function(dispatcher) {
  6. var that = this;
  7. var pending = 0;
  8. var count = 0;
  9. var pendingList = {};
  10. // merge data will get merged into the response data
  11. // before calling the callback
  12. var ajaxCall = function(data, callback, merge, extraOptions) {
  13. merge = merge || {};
  14. dispatcher.post('spin');
  15. pending++;
  16. var id = count++;
  17. // special value: `merge.keep = true` prevents obsolescence
  18. pendingList[id] = merge.keep || false;
  19. delete merge.keep;
  20. // If no protocol version is explicitly set, set it to current
  21. if (data.toString() == '[object FormData]') {
  22. data.append('protocol', PROTOCOL_VERSION);
  23. } else if (data['protocol'] === undefined) {
  24. // TODO: Extract the protocol version somewhere global
  25. data['protocol'] = PROTOCOL_VERSION;
  26. }
  27. options = {
  28. url: 'ajax.cgi',
  29. data: data,
  30. type: 'POST',
  31. success: function(response) {
  32. pending--;
  33. // If no exception is set, verify the server results
  34. if (response.exception == undefined && response.action !== data.action) {
  35. console.error('Action ' + data.action +
  36. ' returned the results of action ' + response.action);
  37. response.exception = true;
  38. dispatcher.post('messages', [[['Protocol error: Action' + data.action + ' returned the results of action ' + response.action + ' maybe the server is unable to run, please run tools/troubleshooting.sh from your installation to diagnose it', 'error', -1]]]);
  39. }
  40. // If the request is obsolete, do nothing; if not...
  41. if (pendingList.hasOwnProperty(id)) {
  42. dispatcher.post('messages', [response.messages]);
  43. if (response.exception == 'configurationError'
  44. || response.exception == 'protocolVersionMismatch') {
  45. // this is a no-rescue critical failure.
  46. // Stop *everything*.
  47. pendingList = {};
  48. dispatcher.post('screamingHalt');
  49. // If we had a protocol mismatch, prompt the user for a reload
  50. if (response.exception == 'protocolVersionMismatch') {
  51. if(confirm('The server is running a different version ' +
  52. 'from brat than your client, possibly due to a ' +
  53. 'server upgrade. Would you like to reload the ' +
  54. 'current page to update your client to the latest ' +
  55. 'version?')) {
  56. window.location.reload(true);
  57. } else {
  58. dispatcher.post('messages', [[['Fatal Error: Protocol ' +
  59. 'version mismatch, please contact the administrator',
  60. 'error', -1]]]);
  61. }
  62. }
  63. return;
  64. }
  65. delete pendingList[id];
  66. // if .exception is just Boolean true, do not process
  67. // the callback; if it is anything else, the
  68. // callback is responsible for handling it
  69. if (response.exception == true) {
  70. $('#waiter').dialog('close');
  71. } else if (callback) {
  72. $.extend(response, merge);
  73. dispatcher.post(0, callback, [response]);
  74. }
  75. }
  76. dispatcher.post('unspin');
  77. },
  78. error: function(response, textStatus, errorThrown) {
  79. pending--;
  80. dispatcher.post('unspin');
  81. $('#waiter').dialog('close');
  82. dispatcher.post('messages', [[['Error: Action' + data.action + ' failed on error ' + response.statusText, 'error']]]);
  83. console.error(textStatus + ':', errorThrown, response);
  84. }
  85. };
  86. if (extraOptions) {
  87. $.extend(options, extraOptions);
  88. }
  89. $.ajax(options);
  90. return id;
  91. };
  92. var isReloadOkay = function() {
  93. // do not reload while data is pending
  94. return pending == 0;
  95. };
  96. var makeObsolete = function(all) {
  97. if (all) {
  98. pendingList = {};
  99. } else {
  100. $.each(pendingList, function(id, keep) {
  101. if (!keep) delete pendingList[id];
  102. });
  103. }
  104. }
  105. dispatcher.
  106. on('isReloadOkay', isReloadOkay).
  107. on('makeAjaxObsolete', makeObsolete).
  108. on('ajax', ajaxCall);
  109. };
  110. return Ajax;
  111. })(jQuery, window);