summaryrefslogtreecommitdiff
path: root/static/favicons.js
blob: 2eac64173439df64b32899883c394fcca0aa34f3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// from sizeof.cat 

function favicons () {
  this.hidden = "hidden";
  this.visibilityChange = "visibilitychange";
  this.favicon = document.querySelector("[rel='shortcut icon']").href;
  this.title = document.title;

  /* Define a list of "services", each being a pair of favicon URL and the tab title to show. */
  this.services = {
    /* Reddit */
    reddit: () => {
      let title = "Reddit - Dive into anything";
      let favicon = "/img/favicons/reddit.ico";
      return {
        title, favicon
      }
    },
    /* X, formerly known as Twitter */
    x: () => {
      let title = "X. It's what's happening / X";
      let favicon = "/img/favicons/x.ico";
      return {
        title, favicon
      }
    },
    /* Bluesky */
    bluesky: () => {
      let title = "Discover - Bluesky";
      let favicon = "/img/favicons/bluesky.ico";
      return {
        title, favicon
      }
    },
    /* Wikipedia */
    wikipedia: () => {
      let title = "Wikipedia";
      let favicon = "/img/favicons/wikipedia.ico";
      return {
        title, favicon
      }
    },
    /* TikTok, where the hip kids are hanging out */
    tiktok: () => {
      let title = "Explore - Find your favourite videos on TikTok";
      let favicon = "/img/favicons/tiktok.ico";
      return {
        title, favicon
      }
    },
    /* Facebook, your grandma is most likely here */
    facebook: () => {
      /* Pick a random notification number between 1 and 100 */
      let count = Math.round(Math.random() * 99) + 1;
      let title = "(" + count + ") Facebook";
      let favicon = "/img/favicons/facebook.ico";
      return {
        title, favicon
      }
    },
    /* Instagram */
    instagram: () => {
      /* Pick a random notification number between 1 and 100 */
      let count = Math.round(Math.random() * 99) + 1;
      let title = "(" + count + ") Instagram";
      let favicon = "/img/favicons/instagram.ico";
      return {
        title, favicon
      }
    }
  }

  /* Those "services" are enabled, which means the web browser tab can change
    favicon/title using their data. */
  this.enabledServices = [
    'x',
    'reddit',
    'bluesky',
    'instagram',
    'tiktok',
    'facebook',
    'wikipedia'
  ];

  /* Initialization function, checks if the web browser has the specified event
    listeners and binds a handler to the existing one. */
  this.init = function () {
    if (typeof document.mozHidden !== 'undefined') {
      this.hidden = "mozHidden";
      this.visibilityChange = "mozvisibilitychange";
    } else if (typeof document.msHidden !== 'undefined') {
      this.hidden = "msHidden";
      this.visibilityChange = "msvisibilitychange";
    } else if (typeof document.webkitHidden !== 'undefined') {
      this.hidden = "webkitHidden";
      this.visibilityChange = "webkitvisibilitychange";
    }
    document.addEventListener(this.visibilityChange, this.handler.bind(this), false);
  }

  /* The default function which returns the initial favicon/title pair of the
    page, so it can get swapped back upon tab activation. */
  this.default = function () {
    let title = this.title;
    let favicon = this.favicon;
    this.update({
      title, favicon
    });
  }

  /* This function updates the favicon/title pair of the web browser tab when
    the tab is not focused (hidden from view). We're using a cache-busting
    technique so that the favicon is freshly loaded and not cached. */
  this.update = function (data) {
    let cacheBuster = "?v=" + Math.round(Math.random() * 10000000);
    let link  = document.createElement('link');
    link.type = "image/x-icon";
    link.rel = "shortcut icon";
    link.href = data.favicon + cacheBuster;
    document.getElementsByTagName("head")[0].querySelector("[rel='shortcut icon']").remove();
    document.getElementsByTagName("head")[0].appendChild(link);
    document.title = data.title;
  }

  /* The spoof() function randomizes the enabled "services" and picks one from
    them, updating the tab favicon and title. */
  this.spoof = function () {
    let i = Math.round(Math.random() * (this.enabledServices.length - 1));
    let service = this.enabledServices[i];
    if (service && this.services[service]) {
      this.update(this.services[service]());
    }
  }

  /* The default event handler which checks whether the current tab is hidden,
    and if it is then it swaps the favicon/title pair with one from the
    enabled "services". Otherwise, it shows the default favicon and title. */
  this.handler = function () {
    if (document[this.hidden]) {
      this.spoof();
    } else {
      this.default();
    }
  }

  /* Autorun the initialization function. */
  this.init();
}

document.addEventListener("DOMContentLoaded", function(event) {
  favicons();
});