PageSourceSearch

https://googlesnakemods.org/snake-web-initial.js

js googlesnakemods.org collected 2026-10-02 00:39:15 UTC 13,248 bytes, 350 lines download raw bytes

1let webLatestVersion = 10; //Update this every time a new version is added. This should correspond to the version of the snake clone in v/current.
2
3//Code in here runs before snake-mod-loader-web.js
4//Useful to help set stuff up specific to the web version, that doesn't belong in the mod-loader script
5
6window.webSnake = window.webSnake ?? {};
7window.webSnake.logUrlChanges = false;
8
9//Disable analytics
10window.navigator.sendBeacon = function() {
11  //Do nothing
12  window.webSnake.logUrlChanges && console.log('beacon disabled');
13}
14
15//Disable google logging
16window.google.log = function() {
17  //Do nothing
18  window.webSnake.logUrlChanges && console.log('google.log disabled');
19}
20
21window.google.logUrl = function() {
22  //Do nothing
23  window.webSnake.logUrlChanges && console.log('google.logUrl disabled');
24}
25
26//Update url redirects to be relative
27//Commented out as this might not be needed
28/*
29window.webSnake.urlMap.forEach(rule => {
30  const thisUrl = new URL(document.location);
31  const urlStart = thisUrl.origin + thisUrl.pathname;
32  rule.newUrl = thisUrl.origin + thisUrl.pathname + rule.newUrl;
33});
34*/
35
36//Block urls in xhr
37window.oldXhrOpen = XMLHttpRequest.prototype.open;
38XMLHttpRequest.prototype.open = function () {
39  let url = makeUrlAbsolute(arguments[1]);
40  
41  if(window.webSnake.blockedUrls.includes(url)) {
42    window.webSnake.logUrlChanges && console.log('Blocking url: ' + url);
43    throw new Error('Blocking url ' + url); //Slightly sketchy to error here as it may have side effects. This seems ok in practise
44  }
45
46  return oldXhrOpen.apply(this, arguments);
47};
48
49window.oldFetch = window.fetch;
50
51window.fetch = function(url) {
52  if(typeof url === 'string') {
53    let mapping = window.webSnake.urlMap.find(m=>m.oldUrl === url);
54
55    if(mapping && mapping.newUrl) {
56      window.webSnake.logUrlChanges && console.log('Redirecting url: ' + url);
57      arguments[0] = mapping.newUrl;
58    }
59  }
60
61  return window.oldFetch(...arguments);
62}
63
64function makeUrlAbsolute(url) {
65  //If url starts with / then add https://www.google.com
66  if (/^\/[^\/]/.test(url)) {
67    url = "https://www.google.com" + url;
68  }
69  return url;
70}
71
72function switchToMobile() {
73  const currentGameVersion = getGameVersionFromUrl(); //defined in snake-mod-loader-web.js
74
75  //Add is-mobile data attribute
76  let snakeContainer = document.getElementsByClassName('EjCLSb')[0];
77  snakeContainer.dataset.isMobile = '';
78
79  //Delete fullscreen button
80  let fullscreenButtonOld = document.querySelector('img[src$="fullscreen_white_24dp.png"]')
81  if(fullscreenButtonOld) {
82    fullscreenButtonOld.remove();
83  }
84
85  let fullscreenButtonsNew = document.querySelectorAll('div.EFcTud[jsaction="zeJAAd"]');
86  if(fullscreenButtonsNew.length > 0) {
87    [...fullscreenButtonsNew].forEach(button => button.remove());
88  }
89
90  //Add styles needed for mobile
91  let css = `
92  
93  /*Flexible size for snake container*/
94  .EjCLSb {
95    height: 100% !important;
96    min-height: 0 !important;
97    min-width: 0 !important;
98    width: 100% !important;
99  }
100
101  /*Don't centre the snake container*/
102  .yZz3de {
103    position: static !important;
104    left: 0 !important;
105    top: 0 !important;
106    transform: none !important;
107  }
108
109  /*Change keys image to swipe image*/
110  .rNjvu {
111    background-image: url(//www.google.com/logos/fnbx/snake_arcade/swipe.svg) !important
112  }
113
114  /*Menu modal panels don't overlap edge*/
115  .T7SB3d {
116    width: calc(100% - 64px) !important;
117    max-width: 300px !important;
118  }
119
120  /*Buttons below menu modal dont overlap edge*/
121  .wUt0xf {
122    width: calc(100% - 64px) !important;
123    max-width: 300px !important;
124  }
125
126  /*Current/highscore on menu modal taking up less space*/
127  @media only screen and (max-width: 315px),only screen and (orientation:landscape) and (max-height:315px) {
128    .bF4Gmf {
129        margin-left:5% !important;
130        margin-right: 5% !important;
131    }
132  }
133
134  /*Current/highscore on menu modal taking up less space*/
135  @media only screen and (max-width: 215px),only screen and (orientation:landscape) and (max-height:215px) {
136      .bF4Gmf {
137          margin-left:0% !important;
138          margin-right: 0% !important;
139      }
140  }
141
142  /*score on top bar less wide*/
143  .HIonyd {
144    width: 45px !important;
145  }
146
147  /*score on top bar less wide responsively*/
148  @media only screen and (max-width: 285px), only screen and (orientation: landscape) and (max-height: 285px)
149  .HIonyd {
150      width: 35px !important;
151      padding-left: 0 !important;
152  }
153  `;
154
155  if(currentGameVersion >= 5) {
156    //Add in additional changes to the html/css that were introduced in version 5
157    css += `
158    /*hide icons on the menu buttons (play/settings/daily challenge) to save space on small screens*/
159    @media only screen and (max-width: 285px) {
160      .DwxlBd {
161          display:none
162      }
163    }
164
165    /* I'm not 100% sure what .jKj29e is for.
166      I suspect it is used to hide menu buttons as above when the translations for play/settings/daily challenge are really long (>20 chars)
167    */
168    @media only screen and (max-width: 340px) {
169        .jKj29e .DwxlBd {
170            display:none
171        }
172
173        .jKj29e .qM98Ge {
174            visibility: hidden
175        }
176    }
177
178    /* Same as above, but .KjMIn is for translations >25 chars.
179    @media only screen and (max-width: 355px) {
180        .jKj29e .DwxlBd {
181            display:none
182        }
183
184        .KjMIn .qM98Ge {
185            visibility: hidden
186        }
187    }
188
189    /* .SU4xse is set when the daily challenge menu is visible */
190    @media only screen and (max-width: 340px) {
191        /* Smaller image icons */
192        .SU4xse .fbftZe {
193            width:28px
194        }
195
196        /* Probably image icons again on daily challenge if there are at least 5 modes? */
197        .SU4xse .OZ9aHc {
198            border-radius: 4px;
199            margin: 3px;
200            padding: 3px;
201            width: 20px
202        }
203
204        /* Small daily challenge icons in the "previous days" view */
205        .SU4xse .Cg6pxb .fbftZe {
206            border-radius: 4px;
207            margin: 8px 2px;
208            padding: 2px;
209            width: 16px
210        }
211    }
212
213    /* Various restrictions based on height */
214    @media only screen and (max-height: 650px) {
215        /* Shorter play/settings/daily challenge buttons */
216        .FL0z2d {
217            height:36px;
218            margin-top: 8px
219        }
220
221        /* Shorter play/settings/daily challenge icons */
222        .DwxlBd {
223            height: 30px;
224            width: 30px
225        }
226
227        /* Small play/settings/daily challenge font-size */
228        .l3ryBd {
229            font-size: 17px
230        }
231
232        /* Maybe something for svgs? No idea really */
233        .w9ahb {
234            height: 26px;
235            width: 26px
236        }
237
238        .w9ahb svg {
239            width: 100%;
240            height: 100%
241        }
242    }
243
244    /*  Undo some styles that exist only of the desktop version */
245    /* remove aspect ratio constraint on game canvas */
246    .jNB0Ic {
247        aspect-ratio: auto !important;
248    }
249
250    /*main container of everything */
251    :not(.DgO4x).EjCLSb {
252        max-width: none !important;
253    }
254
255    /*main container of everything */
256    @media only screen and (min-height: 650px) {
257        :not(.DgO4x).EjCLSb {
258            max-height: none !important;
259        }
260    }
261
262    /* Custom css for gsm so that the button for enabling touch pad controls isn't blocked */
263    .O6HIqc {
264      right: unset !important;
265      left: 10px;
266    }
267    `;
268
269    //Add class so that game can adapt height depending on whether mobile touchpad is enabled
270    let divWithMainCanvas = document.getElementsByClassName('cer0Bd')[0].parentElement;
271    divWithMainCanvas.classList.add('azpHl');
272
273    //Add stuff for the mobile touchpad (touchpad itself + the button to enable it)
274    let settingsOverlay = document.getElementsByClassName('wjOYOd')[0];
275
276    const touchpadHtml = `
277    <div jsname="Ycs2rd" class="Oiw5Ib" jsaction="touchstart:G0IZGc;touchmove:G0IZGc;touchend:G0IZGc" data-ved="0ahUKEwjzppHUw_eFAxWPR_EDHQIwB6kQvNgMCAM">
278        <div class="KM6Me">
279            <div jsname="MUDVS" class="CyfBUb fzrkB">
280                <div class="YD2pbc">
281                    <svg height="100%" viewBox="0 -960 960 960" xmlns="http://www.w3.org/2000/svg">
282                        <path d="M480-360 280-560h400L480-360Z" fill="#000000"></path>
283                    </svg>
284                </div>
285            </div>
286            <div jsname="rmiREc" class="CyfBUb DVNA1b">
287                <div class="YD2pbc">
288                    <svg height="100%" viewBox="0 -960 960 960" xmlns="http://www.w3.org/2000/svg">
289                        <path d="M480-360 280-560h400L480-360Z" fill="#000000"></path>
290                    </svg>
291                </div>
292            </div>
293            <div jsname="p4rndc" class="CyfBUb aq6vAe">
294                <div class="YD2pbc">
295                    <svg height="100%" viewBox="0 -960 960 960" xmlns="http://www.w3.org/2000/svg">
296                        <path d="M480-360 280-560h400L480-360Z" fill="#000000"></path>
297                    </svg>
298                </div>
299            </div>
300            <div jsname="dICtMc" class="CyfBUb EyxhB">
301                <div class="YD2pbc">
302                    <svg height="100%" viewBox="0 -960 960 960" xmlns="http://www.w3.org/2000/svg">
303                        <path d="M480-360 280-560h400L480-360Z" fill="#000000"></path>
304                    </svg>
305                </div>
306            </div>
307        </div>
308        <div jsname="k8ZH5e" class="ekPAb">
309            <div class="SjfyTc"></div>
310        </div>
311    </div>
312    `;
313
314    const enableTouchpadButton = `
315    <div class="O6HIqc" aria-label="Toggle virtual controls" role="button" tabindex="0" jsaction="Uex1ad">
316        <div class="qMDOx">
317            <svg height="100%" viewBox="0 -960 960 960" xmlns="http://www.w3.org/2000/svg">
318                <path d="m296-345-56-56 240-240 240 240-56 56-184-184-184 184Z" fill="#FFFFFF"></path>
319            </svg>
320        </div>
321        <div jsname="ZxgYgc" class="DZekPe vCjPXe" data-ved="0ahUKEwjzppHUw_eFAxWPR_EDHQIwB6kQxvMMCAU">
322            <svg height="100%" viewBox="0 -960 960 960" xmlns="http://www.w3.org/2000/svg">
323                <path d="M172.309-260.001q-30.308 0-51.308-21t-21-51.435v-295.128q0-30.435 21-51.435 21-21 51.308-21h615.382q30.308 0 51.308 21t21 51.435v295.128q0 30.435-21 51.435-21 21-51.308 21H172.309Zm0-59.999h615.382q4.616 0 8.463-3.846 3.846-3.847 3.846-8.463v-295.382q0-4.616-3.846-8.463-3.847-3.846-8.463-3.846H172.309q-4.616 0-8.463 3.846-3.846 3.847-3.846 8.463v295.382q0 4.616 3.846 8.463 3.847 3.846 8.463 3.846Zm117.692-50.001h59.998v-80h80v-59.998h-80v-80h-59.998v80h-80v59.998h80v80Zm289.954 0q20.814 0 35.429-14.57 14.615-14.57 14.615-35.384t-14.57-35.429q-14.57-14.615-35.384-14.615t-35.429 14.57q-14.615 14.57-14.615 35.384t14.57 35.429q14.57 14.615 35.384 14.615Zm120-120q20.814 0 35.429-14.57 14.615-14.57 14.615-35.384t-14.57-35.429q-14.57-14.615-35.384-14.615t-35.429 14.57q-14.615 14.57-14.615 35.384t14.57 35.429q14.57 14.615 35.384 14.615ZM160-320V-640-320Z" fill="#FFFFFF"></path>
324            </svg>
325        </div>
326        <div jsname="fIqioc" class="ufnB2c vCjPXe" data-ved="0ahUKEwjzppHUw_eFAxWPR_EDHQIwB6kQxfMMCAY">
327            <svg height="100%" viewBox="0 -960 960 960" xmlns="http://www.w3.org/2000/svg">
328                <path d="M172.309-260.001q-30.308 0-51.308-21t-21-51.435v-295.128q0-30.435 21-51.435 21-21 51.308-21h615.382q30.308 0 51.308 21t21 51.435v295.128q0 30.435-21 51.435-21 21-51.308 21H172.309Zm0-59.999h615.382q4.616 0 8.463-3.846 3.846-3.847 3.846-8.463v-295.382q0-4.616-3.846-8.463-3.847-3.846-8.463-3.846H172.309q-4.616 0-8.463 3.846-3.846 3.847-3.846 8.463v295.382q0 4.616 3.846 8.463 3.847 3.846 8.463 3.846Zm117.692-50.001h59.998v-80h80v-59.998h-80v-80h-59.998v80h-80v59.998h80v80Zm289.954 0q20.814 0 35.429-14.57 14.615-14.57 14.615-35.384t-14.57-35.429q-14.57-14.615-35.384-14.615t-35.429 14.57q-14.615 14.57-14.615 35.384t14.57 35.429q14.57 14.615 35.384 14.615Zm120-120q20.814 0 35.429-14.57 14.615-14.57 14.615-35.384t-14.57-35.429q-14.57-14.615-35.384-14.615t-35.429 14.57q-14.615 14.57-14.615 35.384t14.57 35.429q14.57 14.615 35.384 14.615ZM160-320V-640-320Z" fill="#FFFFFF"></path>
329            </svg>
330        </div>
331    </div>
332    `;
333
334    settingsOverlay.insertAdjacentHTML('beforebegin', touchpadHtml);
335    settingsOverlay.insertAdjacentHTML('afterbegin', enableTouchpadButton);
336
337    //Rotate game to portrait for mobile
338    const rotateGameMobileHtml = `
339    <div jsname="ar2wLb" class="t6jjTb">
340        <img class="xAAoNb" src="https://fonts.gstatic.com/s/i/short-term/release/googlesymbols/screen_rotation/default/48px.svg" alt="Rotate device to portrait">
341    </div>
342    `;
343
344    snakeContainer.insertAdjacentHTML('beforeend', rotateGameMobileHtml);
345  }
346
347  let styleElement = document.createElement('style');
348  styleElement.innerHTML = css;
349  document.head.appendChild(styleElement);
350}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.