-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathkonami-code.js
325 lines (281 loc) · 12.6 KB
/
konami-code.js
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
/* global define, module */
/**
* Create Konami Code Sequence recognition « Up Up Bottom Bottom Left Right Left Right B A » on specific HTMLElement or on global HTMLDocument. Usage of finger is also possible with « Up Up Bottom Bottom Left Right Left Right Tap Tap ».
* @class KonamiCode
* @version 0.8.3
* @author {@link https://www.lesieur.name/|Bruno Lesieur}
* @param {Object|Function} [options] - Container for all options. If type of `options` is Function, it is executed after Konami Code Sequence has been recognize.
* @param {Function} [options.callback] - If `options` is not a Function, `options.callback` is executed after Konami Code Sequence has been entered. The first parameter provided by the callback is current instance of KonamiCode.
* @param {Node} [options.listener] - By default it is the HTMLDocument `window.document`. You can pass some HTMLElement like `<input>` (HTMLInputElement) to only recognize Konami Code Sequence from this element.
* @param {boolean} [options.debug] - By default it is set to `false`. When you set this value to `true`, that allows you to see all debug message in the console.
*/
(function (root, factory) {
var initialClass = root.KonamiCode,
api = root.KonamiCode = factory;
/**
* If a previous `KonamiCode` variable exist into global environment, you could kept it by changing name of current KonamiCode.
* You can also just use that function to change the name of Global « KonamiCode » variable.
* @function noConflict
* @memberOf KonamiCode.
* @example <script src="other/konami-code.js"></script>
* <script src="last/konami-code.js"></script>
* <script>
* var MyKC = KonamiCode.noConflict();
* console.log(KonamiCode); // Return the other KonamiCode
* console.log(MyKC); // Return your KonamiCode
* </script>
*/
api.noConflict = function () {
root.KonamiCode = initialClass;
return api;
};
if (typeof define === "function" && define.amd) {
define(function () {
return factory;
});
}
if (typeof module === "object" && module.exports) {
module.exports = factory;
}
}(this || globalThis, function callee(options) {
var publics = this,
privates = {},
statics = callee;
/**
* Return the number of time KonamiCode was instanciated.
* @function getNumberOfInstance
* @memberOf KonamiCode.
* @return {number} - Number of KonamiCode instance create from begining.
*/
statics.getNumberOfInstance = function () {
return statics._numberOfInstance;
};
/**
* Active the listening of Konami Code Sequence.
* @function enable
* @memberOf KonamiCode#
* @return {KonamiCode} Current instance of KonamiCode
*/
publics.enable = function () {
privates.listenCodeCharSequence();
privates.listenCodeGestureSequence();
privates.debug && privates.debug("Listener enabled for all.");
return publics;
};
/**
* Active the listening of Konami Code Sequence for Keyboard Keys.
* @function enableKeyboardKeys
* @memberOf KonamiCode#
* @return {KonamiCode} Current instance of KonamiCode
*/
publics.enableKeyboardKeys = function () {
privates.listenCodeCharSequence();
privates.debug && privates.debug("Listener enabled for Keyboard Keys.");
return publics;
};
/**
* Active the listening of Konami Code Sequence for Touch Gesture.
* @function enableTouchGesture
* @memberOf KonamiCode#
* @return {KonamiCode} Current instance of KonamiCode
*/
publics.enableTouchGesture = function () {
privates.listenCodeGestureSequence();
privates.debug && privates.debug("Listener enabled for Touch Gesture.");
return publics;
};
/**
* Unactive the listening of Konami Code Sequence.
* @function disable
* @memberOf KonamiCode#
* @return {KonamiCode} Current instance of KonamiCode
*/
publics.disable = function () {
privates.stopCodeCharSequence();
privates.stopCodeGestureSequence();
privates.debug && privates.debug("Listener disabled for all.");
return publics;
};
/**
* Unactive the listening of Konami Code Sequence for Keyboard Keys.
* @function disabledKeyboardKeys
* @memberOf KonamiCode#
* @return {KonamiCode} Current instance of KonamiCode
*/
publics.disableKeyboardKeys = function () {
privates.stopCodeCharSequence();
privates.debug && privates.debug("Listener disabled for Keyboard Keys.");
return publics;
};
/**
* Unactive the listening of Konami Code Sequence for Touch Gesture.
* @function disabledTouchGesture
* @memberOf KonamiCode#
* @return {KonamiCode} Current instance of KonamiCode
*/
publics.disableTouchGesture = function () {
privates.stopCodeGestureSequence();
privates.debug && privates.debug("Listener disabled for Touch Gesture.");
return publics;
};
/**
* Change the listener. The old listener will no longer work. Note: change the listener enable this instance if it is previously disabled.
* @function setListener
* @param {Node} listener - You can pass some HTMLElement like `<input>` (HTMLInputElement) to only recognize Konami Code Sequence from this element.
* @memberOf KonamiCode#
* @return {KonamiCode} Current instance of KonamiCode
*/
publics.setListener = function (listener) {
privates.stopCodeCharSequence();
privates.stopCodeGestureSequence();
privates.listener = listener || document;
privates.listenCodeCharSequence();
privates.listenCodeGestureSequence();
privates.debug && privates.debug("Listener changed.", listener);
return publics;
};
/**
* Change the Function executed after Konami Code Sequence has been entered.
* @function setCallback
* @param {Function} callback - Function executed after Konami Code Sequence has been entered. The first parameter provided by the callback is current instance of KonamiCode.
* @memberOf KonamiCode#
* @return {KonamiCode} Current instance of KonamiCode
* @example new KonamiCode().setCallback(function (konamiCode) {
* konamiCode.disable();
* // Do something here.
* });
*/
publics.setCallback = function (callback) {
privates.afterCodeSequenceCallback = (typeof callback === "function" && callback) || privates.defaultCallback;
privates.debug && privates.debug("Callback changed.", callback);
return publics;
};
/**
* Change options of instance currently existing.
* @function setOptions
* @param {Object} [options] - Container for all options.
* @param {Function} [options.callback] - Function executed after Konami Code Sequence has been entered. The first parameter provided by the callback is current instance of KonamiCode.
* @param {Node} [options.listener] - By default it is the HTMLDocument `window.document`. You can pass some HTMLElement like `<input>` (HTMLInputElement) to only recognize Konami Code Sequence from this element.
* @param {boolean} [options.debug] - By default it is set to `false`. When you set this value to `true`, that allows you to see all debug message in the console.
* @memberOf KonamiCode#
* @return {KonamiCode} Current instance of KonamiCode
*/
publics.setOptions = function (options) {
privates.initOptions(options);
return publics;
};
privates.keptLastCodeChar = function () {
if (privates.input.length > privates.konamiCodeChar.length) {
privates.input = privates.input.substr((privates.input.length - privates.konamiCodeChar.length));
}
};
privates.defaultCallback = function () {
privates.debug && privates.debug("Konami Code Sequence Entered. There is no action defined.");
};
privates.checkIfCodeCharIsValid = function () {
if (privates.input === privates.konamiCodeChar) {
privates.afterCodeSequenceCallback(publics);
}
};
privates.codeSequenceEventKeyDown = function (event) {
privates.input += event.keyCode;
privates.keptLastCodeChar();
privates.checkIfCodeCharIsValid();
};
privates.codeSequenceEventTouchMove = function (event) {
var touch;
if (event.touches.length === 1 && privates.capture === true) {
touch = event.touches[0];
privates.stopX = touch.pageX;
privates.stopY = touch.pageY;
privates.tap = false;
privates.capture = false;
privates.checkIfCodeGestureIsValid();
}
};
privates.codeSequenceEventTouchEnd = function () {
if (privates.tap === true) {
privates.checkIfCodeGestureIsValid();
}
};
privates.codeSequenceEventTouchStart = function (event) {
privates.startX = event.changedTouches[0].pageX;
privates.startY = event.changedTouches[0].pageY;
privates.tap = true;
privates.capture = true;
};
privates.stopCodeCharSequence = function () {
privates.listener.removeEventListener("keydown", privates.codeSequenceEventKeyDown);
};
privates.stopCodeGestureSequence = function () {
privates.listener.removeEventListener("touchstart", privates.codeSequenceEventTouchStart);
privates.listener.removeEventListener("touchmove", privates.codeSequenceEventTouchMove);
privates.listener.removeEventListener("touchend", privates.codeSequenceEventTouchEnd);
};
privates.listenCodeCharSequence = function () {
privates.stopCodeCharSequence();
privates.listener.addEventListener("keydown", privates.codeSequenceEventKeyDown);
};
privates.listenCodeGestureSequence = function () {
privates.originalCodeGesture = privates.konamiCodeGesture;
privates.stopCodeGestureSequence();
privates.listener.addEventListener("touchstart", privates.codeSequenceEventTouchStart);
privates.listener.addEventListener("touchmove", privates.codeSequenceEventTouchMove);
privates.listener.addEventListener("touchend", privates.codeSequenceEventTouchEnd, false);
};
privates.checkIfCodeGestureIsValid = function () {
var xMagnitude = Math.abs(privates.startX - privates.stopX),
yMagnitude = Math.abs(privates.startY - privates.stopY),
x = (privates.startX - privates.stopX < 0) ? "rt" : "lt",
y = (privates.startY - privates.stopY < 0) ? "dn" : "up",
result = (xMagnitude > yMagnitude) ? x : y;
result = (privates.tap === true) ? "tp" : result;
if (result === privates.konamiCodeGesture.substr(0, 2)) {
privates.konamiCodeGesture = privates.konamiCodeGesture.substr(2, privates.konamiCodeGesture.length - 2);
} else {
privates.konamiCodeGesture = privates.originalCodeGesture;
}
if (privates.konamiCodeGesture.length === 0) {
privates.konamiCodeGesture = privates.originalCodeGesture;
privates.afterCodeSequenceCallback(publics);
}
};
privates.checkDebugMode = function (options) {
if (options && options.debug === true) {
privates.debug = function (message, obj) {
if (obj !== undefined) {
console.log(message, obj);
} else {
console.log(message);
}
};
privates.debug && privates.debug("Debug Mode On.");
} else {
privates.debug = false;
}
};
privates.initOptions = function (options) {
privates.checkDebugMode(options);
privates.listener = (options && options.listener) || document;
privates.afterCodeSequenceCallback =
(typeof options === "function" && options) ||
(options && typeof options.callback === "function" && options.callback) ||
privates.defaultCallback;
};
privates.init = function () {
privates.input = "";
privates.konamiCodeChar = "38384040373937396665";
privates.konamiCodeGesture = "upupdndnltrtltrttptp";
privates.startX = 0;
privates.startY = 0;
privates.stopX = 0;
privates.stopY = 0;
privates.tap = false;
privates.capture = false;
statics._numberOfInstance = (statics._numberOfInstance) ? statics._numberOfInstance + 1 : 1;
privates.initOptions(options);
privates.listenCodeCharSequence();
privates.listenCodeGestureSequence();
};
privates.init();
}));