error-page-embed.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. (function(window, document, JSON){
  2. 'use strict';
  3. /**
  4. window.sentryConfig = {
  5. dsn: 'http://public@example.com/1',
  6. eventId: '...',
  7. attachOnLoad: true,
  8. parent: document.body
  9. };
  10. */
  11. var strings = {{ strings }};
  12. var template = /*{{ template }}*/'';
  13. var endpoint = /*{{ endpoint }}*/'';
  14. var GENERIC_ERROR = '<p class="message-error">' + strings.generic_error + '</p>';
  15. var FORM_ERROR = '<p class="message-error">' + strings.form_error + '</p>';
  16. // XMLHttpRequest.DONE does not exist in all browsers
  17. var XHR_DONE = 4;
  18. var serialize = function(form) {
  19. var q = [];
  20. for (var i = 0; i < form.elements.length; i++) {
  21. q.push(form.elements[i].name + '=' + encodeURIComponent(form.elements[i].value));
  22. }
  23. return q.join('&');
  24. };
  25. var onReady = function(f) {
  26. /in/.test(document.readyState)
  27. ? setTimeout(function() { onReady(f); }, 9)
  28. : f();
  29. };
  30. var SentryErrorEmbed = function(options) {
  31. this.build();
  32. };
  33. SentryErrorEmbed.prototype.build = function() {
  34. var self = this;
  35. this.element = document.createElement('div');
  36. this.element.className = 'sentry-error-embed-wrapper';
  37. this.element.innerHTML = template;
  38. self.element.onclick = function(e){
  39. if (e.target !== self.element) return;
  40. self.close();
  41. };
  42. this._form = this.element.getElementsByTagName('form')[0];
  43. this._form.onsumbit = function(e) {
  44. e.preventDefault();
  45. self.submit(self.serialize());
  46. };
  47. this._submitBtn = this.element.getElementsByTagName('button')[0];
  48. this._submitBtn.onclick = function(e) {
  49. e.preventDefault();
  50. self.submit(self.serialize());
  51. };
  52. var divTags = this._form.getElementsByTagName('div');
  53. var i;
  54. for (i = 0; i < divTags.length; i++) {
  55. if (divTags[i].className === 'error-wrapper') {
  56. this._errorWrapper = divTags[i];
  57. }
  58. if (divTags[i].className === 'form-content') {
  59. this._formContent = divTags[i];
  60. }
  61. }
  62. var linkTags = this.element.getElementsByTagName('a');
  63. var onclickHandler = function(e) {
  64. e.preventDefault();
  65. self.close();
  66. };
  67. for (i = 0; i < linkTags.length; i++) {
  68. if (linkTags[i].className === 'close') {
  69. linkTags[i].onclick = onclickHandler;
  70. }
  71. }
  72. this._formMap = {};
  73. var node;
  74. for (i = 0; i < this._form.elements.length; i++) {
  75. node = this._form.elements[i];
  76. this._formMap[node.name] = node.parentNode;
  77. }
  78. };
  79. SentryErrorEmbed.prototype.serialize = function() {
  80. return serialize(this._form);
  81. };
  82. SentryErrorEmbed.prototype.close = function() {
  83. this.element.parentNode.removeChild(this.element);
  84. };
  85. SentryErrorEmbed.prototype.submit = function(body) {
  86. var self = this;
  87. if (this._submitInProgress)
  88. return;
  89. this._submitInProgress = true;
  90. var xhr = new XMLHttpRequest();
  91. xhr.onreadystatechange = function() {
  92. if (xhr.readyState === XHR_DONE) {
  93. if (xhr.status === 200) {
  94. self.onSuccess();
  95. } else if (xhr.status == 400) {
  96. self.onFormError(JSON.parse(xhr.responseText));
  97. } else {
  98. self._errorWrapper.innerHTML = GENERIC_ERROR;
  99. }
  100. self._submitInProgress = false;
  101. }
  102. };
  103. xhr.open('POST', endpoint, true);
  104. xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
  105. xhr.send(body);
  106. };
  107. SentryErrorEmbed.prototype.onSuccess = function() {
  108. this._errorWrapper.innerHTML = '';
  109. this._formContent.innerHTML = '<p class="message-success">' + strings.sent_message + '</p>';
  110. this._submitBtn.parentNode.removeChild(this._submitBtn);
  111. };
  112. SentryErrorEmbed.prototype.onFormError = function (data) {
  113. var node;
  114. for (var key in this._formMap) {
  115. node = this._formMap[key];
  116. if (data.errors[key]) {
  117. if (!/form-errors/.test(node.className)) {
  118. node.className += ' form-errors';
  119. }
  120. } else if (/form-errors/.test(node.className)) {
  121. node.className = node.className.replace(/form-errors/, '');
  122. }
  123. }
  124. this._errorWrapper.innerHTML = FORM_ERROR;
  125. };
  126. SentryErrorEmbed.prototype.attach = function(parent) {
  127. parent.appendChild(this.element);
  128. };
  129. var options = window.sentryConfig || {};
  130. var embed = new SentryErrorEmbed(options);
  131. if (options.attachOnLoad !== false) {
  132. onReady(function(){
  133. embed.attach(options.parent || document.body);
  134. if (window.sentryEmbedCallback && typeof sentryEmbedCallback === 'function') {
  135. sentryEmbedCallback(embed);
  136. }
  137. });
  138. }
  139. }(window, document, JSON));