script.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. "use strict";
  2. window.AllowBackFromHistory = false;
  3. function CheckLocation() {
  4. var start = "#go_to_message";
  5. var hash = location.hash;
  6. if (hash.substr(0, start.length) == start) {
  7. var messageId = parseInt(hash.substr(start.length));
  8. if (messageId) {
  9. GoToMessage(messageId);
  10. }
  11. } else if (hash == "#allow_back") {
  12. window.AllowBackFromHistory = true;
  13. }
  14. }
  15. function ShowToast(text) {
  16. var container = document.createElement("div");
  17. container.className = "toast_container";
  18. var inner = container.appendChild(document.createElement("div"));
  19. inner.className = "toast_body";
  20. inner.appendChild(document.createTextNode(text));
  21. var appended = document.body.appendChild(container);
  22. setTimeout(function () {
  23. AddClass(appended, "toast_shown");
  24. setTimeout(function () {
  25. RemoveClass(appended, "toast_shown");
  26. setTimeout(function () {
  27. document.body.removeChild(appended);
  28. }, 3000);
  29. }, 3000);
  30. }, 0);
  31. }
  32. function ShowHashtag(tag) {
  33. ShowToast("This is a hashtag '#" + tag + "' link.");
  34. return false;
  35. }
  36. function ShowCashtag(tag) {
  37. ShowToast("This is a cashtag '$" + tag + "' link.");
  38. return false;
  39. }
  40. function ShowBotCommand(command) {
  41. ShowToast("This is a bot command '/" + command + "' link.");
  42. return false;
  43. }
  44. function ShowMentionName() {
  45. ShowToast("This is a link to a user mentioned by name.");
  46. return false;
  47. }
  48. function ShowNotLoadedEmoji() {
  49. ShowToast("This custom emoji is not included, change data exporting settings to download.");
  50. return false;
  51. }
  52. function ShowNotAvailableEmoji() {
  53. ShowToast("This custom emoji is not available.");
  54. return false;
  55. }
  56. function ShowTextCopied(content) {
  57. navigator.clipboard.writeText(content);
  58. ShowToast("Text copied to clipboard.");
  59. return false;
  60. }
  61. function ShowSpoiler(target) {
  62. if (target.classList.contains("hidden")) {
  63. target.classList.toggle("hidden");
  64. }
  65. }
  66. function AddClass(element, name) {
  67. var current = element.className;
  68. var expression = new RegExp('(^|\\s)' + name + '(\\s|$)', 'g');
  69. if (expression.test(current)) {
  70. return;
  71. }
  72. element.className = current + ' ' + name;
  73. }
  74. function RemoveClass(element, name) {
  75. var current = element.className;
  76. var expression = new RegExp('(^|\\s)' + name + '(\\s|$)', '');
  77. var match = expression.exec(current);
  78. while ((match = expression.exec(current)) != null) {
  79. if (match[1].length > 0 && match[2].length > 0) {
  80. current = current.substr(0, match.index + match[1].length)
  81. + current.substr(match.index + match[0].length);
  82. } else {
  83. current = current.substr(0, match.index)
  84. + current.substr(match.index + match[0].length);
  85. }
  86. }
  87. element.className = current;
  88. }
  89. function EaseOutQuad(t) {
  90. return t * t;
  91. }
  92. function EaseInOutQuad(t) {
  93. return (t < 0.5) ? (2 * t * t) : ((4 - 2 * t) * t - 1);
  94. }
  95. function ScrollHeight() {
  96. if ("innerHeight" in window) {
  97. return window.innerHeight;
  98. } else if (document.documentElement) {
  99. return document.documentElement.clientHeight;
  100. }
  101. return document.body.clientHeight;
  102. }
  103. function ScrollTo(top, callback) {
  104. var html = document.documentElement;
  105. var current = html.scrollTop;
  106. var delta = top - current;
  107. var finish = function () {
  108. html.scrollTop = top;
  109. if (callback) {
  110. callback();
  111. }
  112. };
  113. if (!window.performance.now || delta == 0) {
  114. finish();
  115. return;
  116. }
  117. var transition = EaseOutQuad;
  118. var max = 300;
  119. if (delta < -max) {
  120. current = top + max;
  121. delta = -max;
  122. } else if (delta > max) {
  123. current = top - max;
  124. delta = max;
  125. } else {
  126. transition = EaseInOutQuad;
  127. }
  128. var duration = 150;
  129. var interval = 7;
  130. var time = window.performance.now();
  131. var animate = function () {
  132. var now = window.performance.now();
  133. if (now >= time + duration) {
  134. finish();
  135. return;
  136. }
  137. var dt = (now - time) / duration;
  138. html.scrollTop = Math.round(current + delta * transition(dt));
  139. setTimeout(animate, interval);
  140. };
  141. setTimeout(animate, interval);
  142. }
  143. function ScrollToElement(element, callback) {
  144. var header = document.getElementsByClassName("page_header")[0];
  145. var headerHeight = header.offsetHeight;
  146. var html = document.documentElement;
  147. var scrollHeight = ScrollHeight();
  148. var available = scrollHeight - headerHeight;
  149. var padding = 10;
  150. var top = element.offsetTop;
  151. var height = element.offsetHeight;
  152. var desired = top
  153. - Math.max((available - height) / 2, padding)
  154. - headerHeight;
  155. var scrollTopMax = html.offsetHeight - scrollHeight;
  156. ScrollTo(Math.min(desired, scrollTopMax), callback);
  157. }
  158. function GoToMessage(messageId) {
  159. var element = document.getElementById("message" + messageId);
  160. if (element) {
  161. var hash = "#go_to_message" + messageId;
  162. if (location.hash != hash) {
  163. location.hash = hash;
  164. }
  165. ScrollToElement(element, function () {
  166. AddClass(element, "selected");
  167. setTimeout(function () {
  168. RemoveClass(element, "selected");
  169. }, 1000);
  170. });
  171. } else {
  172. ShowToast("This message was not exported. Maybe it was deleted.");
  173. }
  174. return false;
  175. }
  176. function GoBack(anchor) {
  177. if (!window.AllowBackFromHistory) {
  178. return true;
  179. }
  180. history.back();
  181. if (!anchor || !anchor.getAttribute) {
  182. return true;
  183. }
  184. var destination = anchor.getAttribute("href");
  185. if (!destination) {
  186. return true;
  187. }
  188. setTimeout(function () {
  189. location.href = destination;
  190. }, 100);
  191. return false;
  192. }