CyberChef/src/web/SeasonalWaiter.js

157 lines
4.4 KiB
JavaScript
Raw Normal View History

2017-05-02 23:13:50 +01:00
import spiderImages from "./spiderImages.json";
const { spider16, spider32, spider64 } = spiderImages;
2016-11-28 10:42:58 +00:00
/**
* Waiter to handle seasonal events and easter eggs.
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2016
* @license Apache-2.0
*
* @constructor
* @param {App} app - The main view object for CyberChef.
2016-11-28 10:42:58 +00:00
* @param {Manager} manager - The CyberChef event manager.
*/
2017-04-13 18:08:50 +01:00
const SeasonalWaiter = function(app, manager) {
2016-11-28 10:42:58 +00:00
this.app = app;
this.manager = manager;
};
/**
* Loads all relevant items depending on the current date.
*/
SeasonalWaiter.prototype.load = function() {
2017-03-22 00:05:40 +00:00
//var now = new Date();
2016-12-14 16:39:17 +00:00
2016-11-28 10:42:58 +00:00
// SpiderChef
2016-12-14 16:39:17 +00:00
// if (now.getMonth() === 3 && now.getDate() === 1) { // Apr 1
// this.insertSpiderIcons();
// this.insertSpiderText();
2016-11-28 10:42:58 +00:00
// }
2016-12-14 16:39:17 +00:00
2016-11-28 10:42:58 +00:00
// Konami code
this.kkeys = [];
window.addEventListener("keydown", this.konamiCodeListener.bind(this));
2016-11-28 10:42:58 +00:00
};
/**
* Replaces chef icons with spider icons.
* #spiderchef
*/
SeasonalWaiter.prototype.insertSpiderIcons = function() {
2016-12-14 16:39:17 +00:00
2016-11-28 10:42:58 +00:00
// Favicon
document.querySelector("link[rel=icon]").setAttribute("href", "data:image/png;base64," + spider16);
2016-12-14 16:39:17 +00:00
2016-11-28 10:42:58 +00:00
// Bake button
document.querySelector("#bake img").setAttribute("src", "data:image/png;base64," + spider32);
2016-12-14 16:39:17 +00:00
2016-11-28 10:42:58 +00:00
// About box
document.querySelector(".about-img-left").setAttribute("src", "data:image/png;base64," + spider64);
};
/**
* Replaces all instances of the word "cyber" with "spider".
* #spiderchef
*/
SeasonalWaiter.prototype.insertSpiderText = function() {
2016-11-28 10:42:58 +00:00
// Title
document.title = document.title.replace(/Cyber/g, "Spider");
2016-12-14 16:39:17 +00:00
2016-11-28 10:42:58 +00:00
// Body
SeasonalWaiter.treeWalk(document.body, function(node) {
2016-11-28 10:42:58 +00:00
// process only text nodes
2016-12-14 16:39:17 +00:00
if (node.nodeType === 3) {
2016-11-28 10:42:58 +00:00
node.nodeValue = node.nodeValue.replace(/Cyber/g, "Spider");
}
}, true);
2016-12-14 16:39:17 +00:00
2016-11-28 10:42:58 +00:00
// Bake button
SeasonalWaiter.treeWalk(document.getElementById("bake-group"), function(node) {
2016-11-28 10:42:58 +00:00
// process only text nodes
2016-12-14 16:39:17 +00:00
if (node.nodeType === 3) {
2016-11-28 10:42:58 +00:00
node.nodeValue = node.nodeValue.replace(/Bake/g, "Spin");
}
}, true);
2016-12-14 16:39:17 +00:00
2016-11-28 10:42:58 +00:00
// Recipe title
document.querySelector("#recipe .title").innerHTML = "Web";
};
/**
* Listen for the Konami code sequence of keys. Turn the page upside down if they are all heard in
* sequence.
* #konamicode
*/
SeasonalWaiter.prototype.konamiCodeListener = function(e) {
2016-11-28 10:42:58 +00:00
this.kkeys.push(e.keyCode);
2017-04-13 18:08:50 +01:00
const konami = [38, 38, 40, 40, 37, 39, 37, 39, 66, 65];
for (let i = 0; i < this.kkeys.length; i++) {
2016-12-14 16:39:17 +00:00
if (this.kkeys[i] !== konami[i]) {
2016-11-28 10:42:58 +00:00
this.kkeys = [];
break;
}
2016-12-14 16:39:17 +00:00
if (i === konami.length - 1) {
2016-11-28 10:42:58 +00:00
$("body").children().toggleClass("konami");
this.kkeys = [];
}
}
};
/**
* Walks through the entire DOM starting at the specified element and operates on each node.
*
* @static
* @param {element} parent - The DOM node to start from
* @param {Function} fn - The callback function to operate on each node
* @param {booleam} allNodes - Whether to operate on every node or not
2016-11-28 10:42:58 +00:00
*/
SeasonalWaiter.treeWalk = (function() {
2016-11-28 10:42:58 +00:00
// Create closure for constants
2017-04-13 18:08:50 +01:00
const skipTags = {
2016-12-14 16:39:17 +00:00
"SCRIPT": true, "IFRAME": true, "OBJECT": true,
2016-11-28 10:42:58 +00:00
"EMBED": true, "STYLE": true, "LINK": true, "META": true
};
2016-12-14 16:39:17 +00:00
return function(parent, fn, allNodes) {
2017-04-13 18:08:50 +01:00
let node = parent.firstChild;
2016-12-14 16:39:17 +00:00
while (node && node !== parent) {
if (allNodes || node.nodeType === 1) {
2016-11-28 10:42:58 +00:00
if (fn(node) === false) {
2017-02-09 15:09:33 +00:00
return false;
2016-11-28 10:42:58 +00:00
}
}
// If it's an element &&
// has children &&
// has a tagname && is not in the skipTags list
// then, we can enumerate children
if (node.nodeType === 1 &&
node.firstChild &&
!(node.tagName && skipTags[node.tagName])) {
node = node.firstChild;
} else if (node.nextSibling) {
node = node.nextSibling;
} else {
// No child and no nextsibling
// Find parent that has a nextSibling
2016-12-14 16:39:17 +00:00
while ((node = node.parentNode) !== parent) {
2016-11-28 10:42:58 +00:00
if (node.nextSibling) {
node = node.nextSibling;
break;
}
}
}
}
};
})();
export default SeasonalWaiter;