Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

popup.js 8.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. /***********/
  2. /* HELPERS */
  3. /***********/
  4. /* Toggle the current state, as represented in the AKS object. (Nothing actually
  5. happens until the UI state is updated, killSticky() is called (if needed),
  6. and the new settings are saved in storage.)
  7. What “toggle the current state” actually means depends on the current mode.
  8. [1] In blacklist mode, toggleState() does one of the following:
  9. (a) (if stickies are not being killed on the current page) adds a matching
  10. pattern (if one is not already there), and removes all applicable
  11. exclusion patterns; or,
  12. (b) (if stickies are being killed on the current page) removes all
  13. applicable matching patterns.
  14. [2] In whitelist mode, toggleState() does one of the following:
  15. (a) (if stickies are not being killed on the current page) removes all
  16. applicable exclusion patterns; or,
  17. (b) (if stickies are being killed on the current page) adds an exclusion
  18. pattern.
  19. */
  20. function toggleState() {
  21. if (AKS.mode == "blacklist") {
  22. if (!AKS.pageMatched || AKS.pageExcluded) {
  23. /* In this case, stickies are NOT being killed. We must add a matching
  24. pattern, and remove all applicable exclusion patterns. */
  25. if (!AKS.pageMatched) {
  26. addPatternForCurrentTab(AKS.matchingPatterns);
  27. }
  28. if (AKS.pageExcluded) {
  29. disablePatternsForCurrentTab(AKS.exclusionPatterns);
  30. }
  31. } else {
  32. /* In this case, stickies ARE being killed. We must remove all
  33. applicable matching patterns. */
  34. disablePatternsForCurrentTab(AKS.matchingPatterns);
  35. }
  36. } else { // if whitelist mode
  37. if (AKS.pageExcluded) {
  38. /* In this case, stickies are NOT being killed. We must remove all
  39. applicable exclusion patterns. */
  40. disablePatternsForCurrentTab(AKS.exclusionPatterns);
  41. } else {
  42. /* In this case, stickies ARE being killed. We must add an exclusion
  43. pattern. */
  44. addPatternForCurrentTab(AKS.exclusionPatterns);
  45. }
  46. }
  47. recalculatePatternEffects();
  48. }
  49. /* Given a patterns list (whether matching or exclusion), enables all patterns
  50. that match the current page URL, if any. If none are found, adds a new
  51. pattern for the current tab.
  52. */
  53. function addPatternForCurrentTab(patterns) {
  54. /* First, we see if there are already any existing but commented-out
  55. patterns that match the active tab. If so, we enable them all. */
  56. var existingPatternsFound = false;
  57. for (var i = 0; i < patterns.length; i++) {
  58. if (patterns[i] && patterns[i].hasPrefix("#")) {
  59. // Strip the leading comment characters and whitespace.
  60. let uncommentedPattern = patterns[i].replace(/^#[#\s]*/, "");
  61. // Check if the pattern matches the active tab’s URL.
  62. if (AKS.activeTabLocation.match(new RegExp(uncommentedPattern))) {
  63. // If so, replace the commented pattern.
  64. patterns[i] = uncommentedPattern;
  65. existingPatternsFound = true;
  66. }
  67. }
  68. }
  69. if (existingPatternsFound) return;
  70. /* If no existing but commented-out patterns have been found, then we’ve
  71. got to add a new pattern. */
  72. let dtf = new Intl.DateTimeFormat([],
  73. { month: 'short', day: 'numeric', year: 'numeric', hour: 'numeric', minute: 'numeric', second: 'numeric' });
  74. patterns.push("## " + dtf.format(new Date()) + " - " + AKS.activeTabLocation);
  75. patterns.push(regExpForCurrentTab());
  76. patterns.push("");
  77. }
  78. /* Given a patterns list (whether matching or exclusion), disables all patterns
  79. that match the current page URL.
  80. */
  81. function disablePatternsForCurrentTab(patterns) {
  82. for (var i = 0; i < patterns.length; i++) {
  83. if (patterns[i] && AKS.activeTabLocation.match(new RegExp(patterns[i])))
  84. patterns[i] = "# " + patterns[i];
  85. }
  86. }
  87. /* Creates a regexp that matches the current page URL. This regexp will match
  88. all pages on the same domain.
  89. */
  90. function regExpForCurrentTab() {
  91. let a = document.createElement("A");
  92. a.href = AKS.activeTabLocation;
  93. return ".*" + a.host.replace(/\./g, "\\.") + ".*";
  94. }
  95. /* Recalculates the values of AKS.pageMatched and AKS.pageExcluded, based on
  96. the contents of the matching and exclusion patterns lists.
  97. */
  98. function recalculatePatternEffects() {
  99. AKS.pageMatched = false;
  100. AKS.pageExcluded = false;
  101. for (let pattern of AKS.matchingPatterns) {
  102. if (pattern &&
  103. !pattern.hasPrefix("#") &&
  104. AKS.activeTabLocation.match(new RegExp(pattern))) {
  105. AKS.pageMatched = true;
  106. break;
  107. }
  108. }
  109. for (let pattern of AKS.exclusionPatterns) {
  110. if (pattern &&
  111. !pattern.hasPrefix("#") &&
  112. AKS.activeTabLocation.match(new RegExp(pattern))) {
  113. AKS.pageExcluded = true;
  114. break;
  115. }
  116. }
  117. }
  118. /* Updates the values of properties of the AKS object on the basis of the
  119. provided result object. Called after a query to storage (to retrieve the
  120. result object).
  121. Updated properties are: the current mode, the matching and exclusion
  122. patterns lists, and the ‘pageMatched’ and ‘pageExcluded’ properties (which
  123. are computed from the patterns lists).
  124. */
  125. function updateState(result) {
  126. AKS.mode = result.mode || "blacklist";
  127. AKS.matchingPatterns = (AKS.mode == "whitelist") ?
  128. [ ".*" ] :
  129. (typeof result.matchingPatterns != "undefined" ?
  130. result.matchingPatterns.split("\n") :
  131. [ ]);
  132. AKS.exclusionPatterns = typeof result.exclusionPatterns != "undefined" ?
  133. result.exclusionPatterns.split("\n") :
  134. [ ];
  135. recalculatePatternEffects();
  136. }
  137. /* Updates the state of all UI elements to reflect the current values of the
  138. AKS object (see updateState()).
  139. */
  140. function updateUIState() {
  141. // The big button.
  142. let mainButton = document.querySelector("button.main-button");
  143. // The block containing the mode indicator and the “Killing stickies?” label.
  144. let info = document.querySelector(".info");
  145. // The “Killing stickies?” label.
  146. let statusLabel = document.querySelector(".info .status-display");
  147. var active, whitelist;
  148. /* The extension (and thus the main button) is shown as ‘active’ if:
  149. (a) Blacklist mode is active, the current page is matched, and NOT
  150. excluded; or,
  151. (b) Whitelist mode is active, and the current page is NOT excluded.
  152. */
  153. if (AKS.mode == "blacklist") {
  154. if (AKS.pageMatched && !AKS.pageExcluded) {
  155. active = true;
  156. } else {
  157. active = false;
  158. }
  159. } else {
  160. if (!AKS.pageExcluded) {
  161. active = false;
  162. } else {
  163. active = true;
  164. }
  165. }
  166. mainButton.classList.toggle("active", active);
  167. statusLabel.classList.toggle("active", active);
  168. mainButton.classList.toggle("whitelist", (AKS.mode == "whitelist"));
  169. info.classList.toggle("whitelist", (AKS.mode == "whitelist"));
  170. }
  171. /******************/
  172. /* INITIALIZATION */
  173. /******************/
  174. function initialize() {
  175. window.AKS = { };
  176. // Update version.
  177. document.querySelector(".info-header .version").innerHTML = chrome.runtime.getManifest().version;
  178. // Retrieve saved settings.
  179. chrome.tabs.query({currentWindow: true, active: true}, (tabs) => {
  180. AKS.activeTabLocation = tabs[0].url;
  181. AKS.activeTabID = tabs[0].id;
  182. chrome.storage.sync.get([ "matchingPatterns", "exclusionPatterns", "mode" ], (result) => {
  183. updateState(result);
  184. updateUIState();
  185. });
  186. });
  187. // Listener for main button.
  188. document.querySelector("button.main-button").addActivateEvent((event) => {
  189. /* This doesn’t actually kill the stickies yet; that’s below, in the
  190. callback to storage.sync.set. */
  191. toggleState();
  192. // Prepare the changes for saving.
  193. var changes = {
  194. "exclusionPatterns": AKS.exclusionPatterns.join("\n"),
  195. "mode": AKS.mode
  196. };
  197. if (AKS.mode == "blacklist")
  198. changes.matchingPatterns = AKS.matchingPatterns.join("\n");
  199. // Save the changes.
  200. chrome.storage.sync.set(changes, () => {
  201. // Update the UI, once changes are saved.
  202. updateUIState();
  203. let reloadButton = document.querySelector("button.reload-button");
  204. /* If need be, actually kill stickies on the current page.
  205. Otherwise, show the reload button. */
  206. let shouldKillSticky = AKS.pageMatched && !AKS.pageExcluded;
  207. if (AKS.pageMatched && !AKS.pageExcluded) {
  208. chrome.tabs.executeScript(null, { code: 'killSticky()' });
  209. reloadButton.classList.toggle("active", false);
  210. } else {
  211. reloadButton.classList.toggle("active", true);
  212. }
  213. // Update the page action (toolbar) icon.
  214. updateIcon(shouldKillSticky, AKS.activeTabID);
  215. });
  216. });
  217. // Listener for Options button.
  218. document.querySelector("button.options-button").addActivateEvent(() => {
  219. chrome.runtime.openOptionsPage(null);
  220. });
  221. // Listener for the Help button.
  222. document.querySelector("button.help-button").addActivateEvent(() => {
  223. // TODO: code!
  224. });
  225. // Listener for reload button (appears when sticky-killing is toggled OFF).
  226. document.querySelector("button.reload-button").addActivateEvent(() => {
  227. chrome.tabs.update(null, { url: AKS.activeTabLocation });
  228. window.close();
  229. });
  230. }
  231. initialize();