Base for multi-host support
Must do further testing; it's too late for me to continue now.
This commit is contained in:
parent
482d352f30
commit
f90869e370
|
@ -24,6 +24,12 @@ body, html {
|
|||
color: #00DD00;
|
||||
}
|
||||
|
||||
.good { color: #99FF99; }
|
||||
.bad { color: #ff7777; }
|
||||
.info { color:#99FFFF; }
|
||||
.neutral { color: #eeeeee; }
|
||||
|
||||
|
||||
/*------------------------------------*\
|
||||
CHAT
|
||||
\*------------------------------------*/
|
||||
|
@ -58,7 +64,7 @@ body, html {
|
|||
#chat i.fatal { color: #ff7777; }
|
||||
|
||||
/*------------------------------------*\
|
||||
INPUT
|
||||
INPUT & LOADER
|
||||
\*------------------------------------*/
|
||||
#input_wrapper {
|
||||
right:0;
|
||||
|
@ -69,7 +75,8 @@ body, html {
|
|||
height:30px;
|
||||
}
|
||||
|
||||
#input {
|
||||
#input,
|
||||
#loader {
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
|
@ -78,9 +85,28 @@ body, html {
|
|||
border: 0;
|
||||
outline: 0;
|
||||
|
||||
|
||||
|
||||
padding: 5px 5px 5px 15px;
|
||||
|
||||
color: #FFFFFF;
|
||||
background-color:#141414;
|
||||
height:30px;
|
||||
}
|
||||
|
||||
#input { z-index: 1; }
|
||||
#loader { z-index: 0; line-height: 20px; font-size: 14px; font-weight: 100; font-family: tahoma;}
|
||||
|
||||
/*------------------------------------*\
|
||||
SPINNER
|
||||
\*------------------------------------*/
|
||||
.loading #loader { z-index: 2; }
|
||||
.loading #loader span {
|
||||
margin-left:-2px;
|
||||
-webkit-animation: rotation 1s infinite linear;
|
||||
}
|
||||
|
||||
@-webkit-keyframes rotation {
|
||||
from {-webkit-transform: rotate(0deg);}
|
||||
to {-webkit-transform: rotate(359deg);}
|
||||
}
|
|
@ -15,7 +15,8 @@
|
|||
</ul>
|
||||
|
||||
<!-- Message input -->
|
||||
<div id="input_wrapper">
|
||||
<div id="input_wrapper" class="loading">
|
||||
<div id="loader"><span>|</span></div>
|
||||
<input type="text" id="input" />
|
||||
</div>
|
||||
|
||||
|
|
|
@ -5,6 +5,9 @@ fandango.defaults({
|
|||
baseUrl: 'js/cryptalk_modules/',
|
||||
paths: {
|
||||
websocket: 'https://cdnjs.cloudflare.com/ajax/libs/socket.io/0.9.16/socket.io.min.js',
|
||||
// Newer version:
|
||||
// We'll have to fix the Access Control issue first though (https://github.com/Automattic/socket.io-client/issues/641).
|
||||
// websocket: 'https://cdn.socket.io/socket.io-1.1.0.js',
|
||||
aes: 'https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/aes.js',
|
||||
domReady: 'https://cdnjs.cloudflare.com/ajax/libs/require-domReady/2.0.1/domReady.min.js'
|
||||
},
|
||||
|
|
|
@ -9,7 +9,16 @@ define(['fandango', 'websocket', 'aes'], function (fandango, websocket, aes) {
|
|||
utils = exports.utilities,
|
||||
proto = exports.prototype,
|
||||
|
||||
each = fandango.each;
|
||||
each = fandango.each,
|
||||
|
||||
/**
|
||||
* Regex for matching NaN.
|
||||
*
|
||||
* @property reNaN
|
||||
* @type {Regex}
|
||||
* @private
|
||||
*/
|
||||
reDigits = /^\d+$/;
|
||||
|
||||
// The DOM selector engine
|
||||
exports.selector = function (selector) {
|
||||
|
@ -61,6 +70,20 @@ define(['fandango', 'websocket', 'aes'], function (fandango, websocket, aes) {
|
|||
try { return document.activeElement; } catch (e) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all characters but 0 - 9 from given string.
|
||||
*
|
||||
* @method digits
|
||||
* @param {String} str The string to sanitize
|
||||
* @return {String} The sanitized string
|
||||
* @example
|
||||
* $.digits('foo8bar'); // `8`
|
||||
* $.digits('->#5*duckM4N!!!111'); // `54111`
|
||||
*/
|
||||
utils.isDigits = function(value) {
|
||||
return reDigits.test(value);
|
||||
};
|
||||
|
||||
/**
|
||||
* A very simple templating function.
|
||||
* @param {} str [description]
|
||||
|
@ -73,6 +96,28 @@ define(['fandango', 'websocket', 'aes'], function (fandango, websocket, aes) {
|
|||
});
|
||||
};
|
||||
|
||||
utils.getJSON = function (path, onSuccess, onError) {
|
||||
var data, request = new XMLHttpRequest();
|
||||
request.open('GET', path, true);
|
||||
|
||||
request.onreadystatechange = function() {
|
||||
if (this.readyState === 4) {
|
||||
if (this.status >= 200 && this.status < 400) {
|
||||
try {
|
||||
onSuccess && onSuccess(JSON.parse(this.responseText));
|
||||
} catch (e) {
|
||||
onError && onError();
|
||||
}
|
||||
} else {
|
||||
onError && onError();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
request.send();
|
||||
request = null;
|
||||
};
|
||||
|
||||
// Part of this is originating from mustasche.js
|
||||
// Code: https://github.com/janl/mustache.js/blob/master/mustache.js#L43
|
||||
// License: https://github.com/janl/mustache.js/blob/master/LICENSE
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Main cryptalk module
|
||||
define({
|
||||
compiles: ['$'],
|
||||
requires: ['settings', 'templates', 'sound', 'fandango']
|
||||
requires: ['hosts', 'templates', 'sound', 'fandango']
|
||||
}, function ($, requires, data) {
|
||||
var socket,
|
||||
key,
|
||||
|
@ -9,8 +9,9 @@ define({
|
|||
room,
|
||||
hash,
|
||||
nick,
|
||||
mute,
|
||||
|
||||
mute = false,
|
||||
settings = {},
|
||||
|
||||
history = [],
|
||||
history_pos = -1,
|
||||
|
@ -20,15 +21,27 @@ define({
|
|||
// Collection of DOM components
|
||||
components = {
|
||||
chat: $('#chat'),
|
||||
input: $('#input')
|
||||
input: $('#input'),
|
||||
inputWrapper: $('#input_wrapper')
|
||||
},
|
||||
|
||||
// Shortcut
|
||||
settings = requires.settings;
|
||||
hosts = requires.hosts.hosts;
|
||||
fandango = requires.fandango;
|
||||
templates = requires.templates;
|
||||
sound = requires.sound;
|
||||
|
||||
lockInput = function () {
|
||||
components.input[0].setAttribute('disabled', 'disabled');
|
||||
components.inputWrapper[0].className = 'loading';
|
||||
},
|
||||
|
||||
unlockInput = function () {
|
||||
components.input[0].removeAttribute('disabled');
|
||||
components.inputWrapper[0].className = '';
|
||||
components.input.focus();
|
||||
},
|
||||
|
||||
// Adds a new message to the DOM
|
||||
post = function (type, text, clearChat, clearBuffer, nick) {
|
||||
var tpl = templates.post[type],
|
||||
|
@ -53,8 +66,205 @@ define({
|
|||
|
||||
// Chat related commands
|
||||
commands = {
|
||||
help: function () {
|
||||
help: function (payload, done) {
|
||||
post('motd', templates.help);
|
||||
done();
|
||||
},
|
||||
|
||||
hosts: function (force, done) {
|
||||
var i = 0,
|
||||
left = hosts.length,
|
||||
host,
|
||||
strhosts = '\n',
|
||||
callback = function (host, index, isUp) {
|
||||
return function (hostSettings) {
|
||||
host.settings = (isUp ? hostSettings : 0);
|
||||
|
||||
strhosts += $.template(templates.messages[(isUp ? 'host_available' : 'host_unavailable')], {
|
||||
name: host.name,
|
||||
path: host.path,
|
||||
index: index
|
||||
});
|
||||
|
||||
if (!--left) {
|
||||
post('info', strhosts);
|
||||
done();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
force = (force && force.toLowerCase() === 'force');
|
||||
|
||||
// Loop through all the hosts
|
||||
while (host = hosts[i]) {
|
||||
if (!force && host.settings !== undefined) {
|
||||
if (host.settings) {
|
||||
callback(host, i, 1)();
|
||||
} else {
|
||||
callback(host, i, 0)();
|
||||
}
|
||||
} else {
|
||||
require([host.path], callback(host, i, 1), callback(host, i, 0));
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
},
|
||||
|
||||
connect: function (toHost, done) {
|
||||
var request;
|
||||
|
||||
if (host && host.connected) {
|
||||
done();
|
||||
return post('error', $.template(templates.messages.already_connected, {
|
||||
host: host.name || 'localhost'
|
||||
}));
|
||||
}
|
||||
|
||||
if ($.isDigits(toHost)) {
|
||||
if (host = hosts[+toHost]) {
|
||||
if (host.settings) {
|
||||
settings = host.settings;
|
||||
} else {
|
||||
request = host.path;
|
||||
}
|
||||
} else {
|
||||
return post('error', 'Undefined host index: ' + toHost);
|
||||
}
|
||||
} else if (fandango.is(toHost, 'untyped')) {
|
||||
settings = toHost.settings;
|
||||
} else { // Assume string
|
||||
request = toHost;
|
||||
}
|
||||
|
||||
if (request) {
|
||||
return require([request], function (settings) {
|
||||
host.settings = settings;
|
||||
commands.connect(toHost, done);
|
||||
}, function () {
|
||||
return post('error', 'Could not fetch host settings: ' + request);
|
||||
});
|
||||
}
|
||||
|
||||
// Push 'Connecting...' message
|
||||
post('info', $.template(templates.messages.connecting, {
|
||||
host: host.name || 'localhost'
|
||||
}));
|
||||
|
||||
// The one and only socket
|
||||
socket = $.Websocket.connect(host.host, {
|
||||
forceNew: true,
|
||||
'force new connection': true
|
||||
});
|
||||
|
||||
// Bind socket events
|
||||
socket
|
||||
.on('room:generated', function (data) {
|
||||
var sanitized = $.escapeHtml(data);
|
||||
post('server', $.template(templates.server.room_generated, { payload: sanitized }));
|
||||
socket.emit('room:join', sanitized);
|
||||
})
|
||||
|
||||
.on('room:joined', function (data) {
|
||||
room = data;
|
||||
post('info', $.template(templates.messages.joined_room, { roomName: room }));
|
||||
|
||||
// Automatically count persons on join
|
||||
socket.emit('room:count');
|
||||
})
|
||||
|
||||
.on('room:left', function () {
|
||||
post('info', $.template(templates.messages.left_room, { roomName: room }));
|
||||
|
||||
// Clear history on leaving room
|
||||
clearHistory();
|
||||
|
||||
room = false;
|
||||
})
|
||||
|
||||
.on('message:send', function (data) {
|
||||
var decrypted = $.AES.decrypt(data.msg, room + key),
|
||||
sanitized = $.escapeHtml(decrypted),
|
||||
nick = (data.nick == undefined || !data.nick ) ? templates.default_nick : $.escapeHtml($.AES.decrypt(data.nick, room + key));
|
||||
|
||||
if (!decrypted) {
|
||||
post('error', templates.messages.unable_to_decrypt);
|
||||
} else {
|
||||
post('message', sanitized, false, false, nick);
|
||||
if( !mute ) sound.playTones(sound.messages.message);
|
||||
}
|
||||
})
|
||||
|
||||
.on('message:server', function (data) {
|
||||
if( data.msg ) {
|
||||
var sanitized = $.escapeHtml(data.msg);
|
||||
if( templates.server[sanitized] ) {
|
||||
if( data.payload !== undefined ) {
|
||||
var sanitized_payload = $.escapeHtml(data.payload);
|
||||
post('server', $.template(templates.server[sanitized], { payload: sanitized_payload }));
|
||||
} else {
|
||||
post('server', templates.server[sanitized]);
|
||||
}
|
||||
|
||||
// Play sound
|
||||
if (sound.messages[sanitized] !== undefined && !mute ) sound.playTones(sound.messages[sanitized]);
|
||||
|
||||
} else {
|
||||
post('error', templates.server.bogus);
|
||||
}
|
||||
} else {
|
||||
post('error', templates.server.bogus);
|
||||
}
|
||||
})
|
||||
|
||||
.on('connect', function () {
|
||||
// Tell the user that the chat is ready to interact with
|
||||
post('info', $.template(templates.messages.connected, {
|
||||
host: host.name || 'localhost'
|
||||
}));
|
||||
|
||||
host.connected = 1;
|
||||
|
||||
done();
|
||||
})
|
||||
|
||||
.on('disconnect', function () {
|
||||
room = 0;
|
||||
key = 0;
|
||||
host.connected = 0;
|
||||
|
||||
// Tell the user that the chat is ready to interact with
|
||||
post('info', $.template(templates.messages.disconnected, {
|
||||
host: host.name || 'localhost'
|
||||
}));
|
||||
})
|
||||
|
||||
.on('error', function () {
|
||||
room = 0;
|
||||
key = 0;
|
||||
host.connected = 0;
|
||||
post('error', templates.messages.socket_error);
|
||||
done();
|
||||
});
|
||||
},
|
||||
|
||||
reconnect: function (foo, done) {
|
||||
if (host) {
|
||||
if (host.connected) {
|
||||
commands.disconnect()
|
||||
commands.connect(host, done);
|
||||
} else {
|
||||
commands.connect(host, done);
|
||||
}
|
||||
} else {
|
||||
done();
|
||||
return post('error', templates.messages.reconnect_no_host);
|
||||
}
|
||||
},
|
||||
|
||||
disconnect: function () {
|
||||
socket.disconnect();
|
||||
},
|
||||
|
||||
clear: function () {
|
||||
|
@ -81,6 +291,10 @@ define({
|
|||
},
|
||||
|
||||
key: function (payload) {
|
||||
if (!host) {
|
||||
return post('error', templates.messages.key_no_host);
|
||||
}
|
||||
|
||||
// Make sure the key meets the length requirements
|
||||
if (payload.length > settings.key_maxLen) {
|
||||
return post('error', templates.messages.key_to_long);
|
||||
|
@ -119,6 +333,10 @@ define({
|
|||
},
|
||||
|
||||
join: function (payload) {
|
||||
if (!host) {
|
||||
return post('error', templates.messages.join_no_host);
|
||||
}
|
||||
|
||||
return (
|
||||
room
|
||||
? post('error', templates.messages.already_in_room)
|
||||
|
@ -169,7 +387,7 @@ define({
|
|||
// The Document object is bound to this element.
|
||||
// If the active element is not the input, focus on it and exit the function.
|
||||
// Ignore this when ctrl and/or alt is pressed!
|
||||
if (components.input[0] !== $.activeElement() && !e.ctrlKey && !e.altKey) {
|
||||
if (!e.ctrlKey && !e.altKey && components.input[0] !== $.activeElement()) {
|
||||
return components.input.focus();
|
||||
}
|
||||
|
||||
|
@ -178,7 +396,7 @@ define({
|
|||
history_timer = setTimeout(clearHistory, 60000);
|
||||
|
||||
// Check for escape key, this does nothing but clear the input buffer and reset history position
|
||||
if ( e.keyCode == 27 ) {
|
||||
if (e.keyCode == 27) {
|
||||
history_pos = -1;
|
||||
clearInput();
|
||||
|
||||
|
@ -186,7 +404,7 @@ define({
|
|||
}
|
||||
|
||||
// Check for up or down-keys, they handle the history position
|
||||
if( e.keyCode == 38 || e.keyCode == 40) {
|
||||
if (e.keyCode == 38 || e.keyCode == 40) {
|
||||
|
||||
if (e.keyCode == 38 ) { history_pos = (history_pos > history.length - 2) ? -1 : history_pos = history_pos + 1; }
|
||||
else { history_pos = (history_pos <= 0) ? -1 : history_pos = history_pos - 1; }
|
||||
|
@ -220,8 +438,18 @@ define({
|
|||
return post('error', $.template(templates.messages.unrecognized_command, { commandName: command }));
|
||||
}
|
||||
|
||||
// Execute command handler
|
||||
commands[command](payload);
|
||||
// Some commands are asynchrounous;
|
||||
// If the command expects more than one argument, the second argument is a callback that is called when the command is done.
|
||||
if (commands[command].length > 1) {
|
||||
// Lock the input from further interaction
|
||||
lockInput();
|
||||
|
||||
// Execute command handler with callback function.
|
||||
commands[command](payload, unlockInput);
|
||||
} else {
|
||||
// Execute normally.
|
||||
commands[command](payload);
|
||||
}
|
||||
|
||||
// Clear input field
|
||||
clearInput();
|
||||
|
@ -257,103 +485,24 @@ define({
|
|||
}
|
||||
};
|
||||
|
||||
host = settings.host;
|
||||
// Bind the necessary DOM events
|
||||
$(document).on('keydown', onKeyDown);
|
||||
|
||||
// Put focus on the message input
|
||||
components.input.focus();
|
||||
|
||||
// Post the help/welcome message
|
||||
post('motd', templates.motd, true);
|
||||
|
||||
// Push 'Connecting...' message
|
||||
post('info', $.template(templates.messages.connecting, {
|
||||
host: host || 'localhost'
|
||||
}));
|
||||
unlockInput();
|
||||
|
||||
// The one and only socket
|
||||
socket = $.Websocket.connect(host);
|
||||
// It's possible to provide room and key using the hashtag.
|
||||
// The room and key is then seperated by semicolon (room:key).
|
||||
// If there is no semicolon present, the complete hash will be treated as the room name and the key has to be set manually.
|
||||
if (host && (hash = window.location.hash)) {
|
||||
parts = hash.slice(1).split(':');
|
||||
|
||||
// Bind socket events
|
||||
socket
|
||||
.on('room:generated', function (data) {
|
||||
var sanitized = $.escapeHtml(data);
|
||||
post('server', $.template(templates.server.room_generated, { payload: sanitized }));
|
||||
socket.emit('room:join', sanitized);
|
||||
})
|
||||
|
||||
.on('room:joined', function (data) {
|
||||
room = data;
|
||||
post('info', $.template(templates.messages.joined_room, { roomName: room }));
|
||||
|
||||
// Automatically count persons on join
|
||||
socket.emit('room:count');
|
||||
})
|
||||
|
||||
.on('room:left', function () {
|
||||
post('info', $.template(templates.messages.left_room, { roomName: room }));
|
||||
|
||||
// Clear history on leaving room
|
||||
clearHistory();
|
||||
|
||||
room = false;
|
||||
})
|
||||
|
||||
.on('message:send', function (data) {
|
||||
var decrypted = $.AES.decrypt(data.msg, room + key),
|
||||
sanitized = $.escapeHtml(decrypted),
|
||||
nick = (data.nick == undefined || !data.nick ) ? templates.default_nick : $.escapeHtml($.AES.decrypt(data.nick, room + key));
|
||||
|
||||
if (!decrypted) {
|
||||
post('error', templates.messages.unable_to_decrypt);
|
||||
} else {
|
||||
post('message', sanitized, false, false, nick);
|
||||
if( !mute ) sound.playTones(sound.messages.message);
|
||||
}
|
||||
})
|
||||
|
||||
.on('message:server', function (data) {
|
||||
if( data.msg ) {
|
||||
var sanitized = $.escapeHtml(data.msg);
|
||||
if( templates.server[sanitized] ) {
|
||||
if( data.payload !== undefined ) {
|
||||
var sanitized_payload = $.escapeHtml(data.payload);
|
||||
post('server', $.template(templates.server[sanitized], { payload: sanitized_payload }));
|
||||
} else {
|
||||
post('server', templates.server[sanitized]);
|
||||
}
|
||||
|
||||
// Play sound
|
||||
if (sound.messages[sanitized] !== undefined && !mute ) sound.playTones(sound.messages[sanitized]);
|
||||
|
||||
} else {
|
||||
post('error', templates.server.bogus);
|
||||
}
|
||||
} else {
|
||||
post('error', templates.server.bogus);
|
||||
}
|
||||
})
|
||||
|
||||
.on('connect', function () {
|
||||
// Bind the necessary DOM events
|
||||
$(document).on('keydown', onKeyDown);
|
||||
|
||||
// Put focus on the message input
|
||||
components.input.focus();
|
||||
|
||||
// Tell the user that the chat is ready to interact with
|
||||
post('info', $.template(templates.messages.connected, {
|
||||
host: host || 'localhost'
|
||||
}));
|
||||
|
||||
// It's possible to provide room and key using the hashtag.
|
||||
// The room and key is then seperated by semicolon (room:key).
|
||||
// If there is no semicolon present, the complete hash will be treated as the room name and the key has to be set manually.
|
||||
if (hash = window.location.hash) {
|
||||
parts = hash.slice(1).split(':');
|
||||
|
||||
parts[0] && commands.join(parts[0]);
|
||||
parts[1] && commands.key(parts[1]);
|
||||
}
|
||||
})
|
||||
|
||||
.on('error', function () {
|
||||
post('error', templates.messages.socket_error);
|
||||
});
|
||||
parts[0] && commands.join(parts[0]);
|
||||
parts[1] && commands.key(parts[1]);
|
||||
}
|
||||
});
|
|
@ -0,0 +1,15 @@
|
|||
define({
|
||||
// Used to autoconnect to specific host.
|
||||
// Points to a specific index in the 'hosts' array.
|
||||
// Use -1 to not autoconnect.
|
||||
autoconnect: 0,
|
||||
|
||||
// A collection of hosts to choose from
|
||||
hosts: [
|
||||
{
|
||||
name: 'localhost',
|
||||
host: 'http://localhost:8080',
|
||||
path: 'http://localhost:8080/js/cryptalk_modules/settings.js'
|
||||
}
|
||||
]
|
||||
});
|
|
@ -1,7 +1,4 @@
|
|||
define({
|
||||
// If no host is given it will default to localhost.
|
||||
host: '',
|
||||
|
||||
nick_maxLen: 20,
|
||||
nick_minLen: 3,
|
||||
|
||||
|
|
|
@ -65,6 +65,9 @@ define({
|
|||
key_to_long: 'Man that\'s a long key. Make it a tad short, \'kay?',
|
||||
key_ok_ready: 'Key set, you can now start communicating.',
|
||||
key_ok_but_no_room: 'Key set, you can now join a room and start communicating.',
|
||||
key_no_host: 'You have to connect to a host before setting the key.',
|
||||
|
||||
join_no_host: 'You have to connect to a host before joining a room.',
|
||||
|
||||
nick_to_short: 'Nickname is too short, it has to be at least {nick_minLen} characters long. Try again.',
|
||||
nick_to_long: 'Nickname is too long, it can be at most {nick_maxLen} characters long. Try again.',
|
||||
|
@ -90,7 +93,13 @@ define({
|
|||
|
||||
socket_error: 'A network error has occurred. A restart may be required to bring back full functionality.<br>Examine the logs for more details.',
|
||||
connecting: 'Connecting to host {host}...',
|
||||
connected: 'A connection to the server has been established. Happy chatting!'
|
||||
connected: 'A connection to the server has been established. Happy chatting!',
|
||||
disconnected: 'Disconnected from host {host}.',
|
||||
already_connected: 'You have to disconnect from {host} before joining another.',
|
||||
reconnect_no_host: 'There is no host to reconnect with.',
|
||||
|
||||
host_available: '<span class="info">{index}</span> <span class="good">[AVAILABLE]</span> <span class="neutral">{name}</span>\n',
|
||||
host_unavailable: '<span class="info">{index}</span> <span class="bad">[UNAVAILABLE]</span> <span class="neutral">{name}</span>\n'
|
||||
},
|
||||
|
||||
server: {
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
(function(r){function A(f){this.name="TimeoutError";this.message=f||""}function B(f){this.name="RejectedError";this.message=f||""}function F(f,c,e,g){var d,a,b=[],m,p,k,h=function(a){f.length===b.push(l[a].exports)&&(g&&clearTimeout(m),c(b))};g=g||v.timeout;for(k=0;p=f[k++];)if((d=l[p])&&1!==d.state)if(2===d.state)if(a=new B('Could resolve all dependencies; dependency "'+p+'" has been rejected.'),e)e(a);else throw a;else 3===d.state&&h(p);else(u[p]=u[p]||[]).push(h);g&&(m=setTimeout(function(){for(var c,
|
||||
d,m=0,p=0;c=f[m++];)for(p=0;d=b[p++];)c===d&&(b.splice(--p,1),f.splice(--m,1));a=new A("Load timeout of "+g+'ms exceeded for module(s) "'+f.join('", "')+'".');if(e)e(a);else throw a;},g))}function y(){var f=!1,c,e,g,d,a,b,m;if(arguments[0]!==C){for(c=0;(e=arguments[c++])&&(_type=(typeof e)[0]);)if("s"===_type?d?g=1:d=e:"f"===_type?b?m?g=1:m=e:b=e:"o"===_type&&(h.is(e,"array")?(a={requires:e},f=!0):a?b=e:a=e),g)throw new TypeError("define called with unrecognized signature; `"+Array.prototype.join.call(arguments,
|
||||
", ")+"`.");a=a||{};d=d||a.UID;b=b||a.factory;m=m||a.onRejected}else if(c=D.pop())d=arguments[1],a=c[0],b=c[1],m=c[2],f=c[3];else throw Error("Inconsistent naming queue");if(!b)if(a)b=a,a={};else throw Error('Missing factory for module "'+d+'"');if(l[d])throw Error('Duplicate entry for module "'+d+'"');d?(c=l[d]=a,c.UID=d,c.amdStyle=f,c.factory=b,c.state=1,c.requires=h.is(c.requires,"array")&&c.requires,c.inherits=h.is(c.inherits,"array")&&c.inherits,c.compiles=h.is(c.compiles,"array")&&c.compiles,
|
||||
c.instances||(c.instances={instance1:{}})):D.unshift([a,b,m,f])}var l={},v={deepCopy:!0,baseUrl:"",namespace:"default",timeout:1E3,paths:{},shim:{}},h={},C={a:1},u={},D=[],z=Array.prototype.push;A.prototype=Error.prototype;B.prototype=Error.prototype;h.is=function(){var f=Object.prototype.hasOwnProperty,c=Object.prototype.toString,e={array:Array.isArray||function(a){return"[object Array]"==c.call(a)},arraylike:function(a){if(!a||!a.length&&0!==a.length||e.window(a))return!1;var b=a.length;return 1===
|
||||
(function(s){function A(f){this.name="TimeoutError";this.message=f||""}function B(f){this.name="RejectedError";this.message=f||""}function F(f,c,e,g){var d,a,b=[],n,m,k,h=function(a){f.length===b.push(l[a].exports)&&(g&&clearTimeout(n),c(b))};g=g||v.timeout;for(k=0;m=f[k++];)if((d=l[m])&&1!==d.state)if(2===d.state)if(a=new B('Could resolve all dependencies; dependency "'+m+'" has been rejected.'),e)e(a);else throw a;else 3===d.state&&h(m);else(u[m]=u[m]||[]).push(h);g&&(n=setTimeout(function(){for(var d,
|
||||
c,n=0,m=0;d=f[n++];)for(m=0;c=b[m++];)d===c&&(b.splice(--m,1),f.splice(--n,1));a=new A("Load timeout of "+g+'ms exceeded for module(s) "'+f.join('", "')+'".');if(e)e(a);else throw a;},g))}function y(){var f=!1,c,e,g,d,a,b,n;if(arguments[0]!==C){for(c=0;(e=arguments[c++])&&(_type=(typeof e)[0]);)if("s"===_type?d?g=1:d=e:"f"===_type?b?n?g=1:n=e:b=e:"o"===_type&&(h.is(e,"array")?(a={requires:e},f=!0):a?b=e:a=e),g)throw new TypeError("define called with unrecognized signature; `"+Array.prototype.join.call(arguments,
|
||||
", ")+"`.");a=a||{};d=d||a.UID;b=b||a.factory;n=n||a.onRejected}else if(c=D.pop())d=arguments[1],a=c[0],b=c[1],n=c[2],f=c[3];else throw Error("Inconsistent naming queue");if(!b)if(a)b=a,a={};else throw Error('Missing factory for module "'+d+'"');if(l[d])throw Error('Duplicate entry for module "'+d+'"');d?(c=l[d]=a,c.UID=d,c.amdStyle=f,c.factory=b,c.state=1,c.requires=h.is(c.requires,"array")&&c.requires,c.inherits=h.is(c.inherits,"array")&&c.inherits,c.compiles=h.is(c.compiles,"array")&&c.compiles,
|
||||
c.instances||(c.instances={instance1:{}})):D.unshift([a,b,n,f])}var l={},v={deepCopy:!0,baseUrl:"",namespace:"default",timeout:1E3,paths:{},shim:{}},h={},C={a:1},u={},D=[],z=Array.prototype.push;A.prototype=Error.prototype;B.prototype=Error.prototype;h.is=function(){var f=Object.prototype.hasOwnProperty,c=Object.prototype.toString,e={array:Array.isArray||function(a){return"[object Array]"==c.call(a)},arraylike:function(a){if(!a||!a.length&&0!==a.length||e.window(a))return!1;var b=a.length;return 1===
|
||||
a.nodeType||e.array(a)||!e["function"](a)&&(0===b||"number"===typeof b&&0<b&&!h.is(a,"primitive")&&b-1 in a)},"boolean":function(a){return!0===a||!1===a},element:function(a){return!(!a||1!==a.nodeType)},finite:function(a){return isFinite(a)&&!isNaN(parseFloat(a))},integer:Number.isInteger||function(a){return"number"===typeof a&&e.finite(a)&&-9007199254740992<a&&9007199254740992>a&&Math.floor(a)===a},iterable:function(a){try{1 in obj}catch(b){return!1}return!0},nan:function(a){return e.number(a)&&
|
||||
a!=+a},number:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},object:function(a){return a===Object(a)},primitive:function(a){return!0===a||!1===a||null==a||!!{string:1,number:1}[typeof a]},string:function(a){return"string"==typeof a||a instanceof String},undefined:function(a){return void 0===a},untyped:function(a){if(!a||a.nodeType||"[object Object]"!==c.call(a)||e.window(a))return!1;try{if(a.constructor&&!f.call(a,"constructor")&&!f.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(b){return!1}for(var d in a);
|
||||
return void 0===d||f.call(a,d)},window:function(a){return null!=a&&a==a.window},empty:function(a){if(a){if(h.is(a,"array"))return 0===a.length;for(var b in a)if(f.call(a,b))return!1}return!0}},g=0,d=["Arguments","Date","Function","RegExp"];for(;4>g;g++)e[d[g].toLowerCase()]=function(a){a="[object "+a+"]";return function(b){return c.call(b)==a}}(d[g]);e.args=e.arguments;e.bool=e["boolean"];e.plain=e.untyped;return function(a,b){if(e["function"](b))return a===b(a);if(!e.string(b))return a===b;if((b=
|
||||
b.toLowerCase())&&e[b])return e[b](a);throw'Unknown type "'+b+'"';}}();h.each=function(){var f=Array.prototype.some;return function(c,e,g){var d,a;if(void 0===c)return obj;g=g||h;if(f&&c.some===f)return c.some(e,g),c;if(h.is(c,"array")||h.is(c,"arraylike")){d=0;for(a=c.length;d<a&&(void 0===c[d]||!e.call(g,c[d],d,c));d++);return c}for(d in c)if(c.hasOwnProperty(d)&&e.call(g,c[d],d,c))break;return c}}();h.merge=function(f){var c,e,g,d,a;c=arguments.length;var b=!1;f=arguments[0];var m=1,p,k,l=0;if(!0===
|
||||
f||!1===f)b=f,f=arguments[m],m++;h.is(arguments[c-1],"function")&&(a=arguments[c-1],c--);if(void 0===f)f={};else if(h.is(f,"primitive"))throw new TypeError("Cannot merge primitive data types: merge("+Array.prototype.join.call(arguments,", ")+")");k=h.is(f,"array");if(m<c)for(;d=arguments[m++];){k=k&&h.is(d,"array");for(g in d)e=f[g],c=d[g],void 0===c||c===f?k&&l--:(b&&c&&((p=h.is(c,"array"))||h.is(c,"untyped"))&&(c=h.merge(b,e&&(p?h.is(e,"array")?e:[]:h.is(e,"untyped")?e:{}),c,a)),a&&a(g,f,d)||(l&&
|
||||
(g=+g+l),f[g]=c));l=0}return f};h.subordinate=function(){function f(a){if(!a||a.source===window&&a.data===g){var c=d.shift();a=c[0];var c=c[1],f=c.length;f?1===f?a(c[0]):2===f?a(c[0],c[1]):3===f?a(c[0],c[1],c[2]):4===f?a(c[0],c[1],c[2],c[3]):a.apply(0,c):a()}}var c=Array.prototype.slice,e=window.postMessage,g="__fandango@"+Math.random().toString(36),d=[],a=function(){return e?function(){e(g,"*")}:function(){setTimeout(f)}}();e&&window.addEventListener("message",f,!1);return function(b){a(d.push([arguments[arguments.length-
|
||||
1],c.call(arguments).slice(0,-1)])-1)}}();var G=function(){var f={},c=[].slice,e=function(){return[]};return function(g,d){function a(a,c){return new b(a,c)}function b(a,b){var c=0,d=m(a,b),f=d.length;this.context=b||document;this.selector=a;for(this.length=f;c<f;c++)this[c]=d[c];return this}var m,p,k,h;if(f[g])return f[g];for(h=d.length;p=d[--h];){p.selector&&(m=p.selector);if(source=p.prototype)if("function"===typeof source)source.call(b.prototype);else if(b.prototype.prototype)for(k in source)source.hasOwnProperty(k)&&
|
||||
(b.prototype[k]=source[k]);else b.prototype=source;if(source=p.utilities)if("function"===typeof source)source.utilities.call(a);else for(k in source)source.hasOwnProperty(k)&&(a[k]=source[k])}b.prototype.length=0;b.prototype.selector="";b.prototype.splice=c;b.prototype.fandango=1;m||(m=e);return f[g]=a}}(),E=function(){function f(c,f,g,d){var a,b=l[c],m=h.is(b.factory,"function"),p=m?b.factory.length:0,k=b.amdStyle,t,s;d&&(a=G(b.compiles+"",d));for(s in b.instances)d=b.instances[s],d.context=void 0===
|
||||
d.context?b.context:d.context,d.deepCopy=void 0===d.deepCopy?b.deepCopy:d.deepCopy,d.namespace=void 0===d.namespace?b.namespace:d.namespace,t=[],k?t=f||[]:(a&&t.push(a),f&&t.push(f),p>t.length&&t.push(d.data?h.merge(d.deepCopy,{},d.data,b.data):b.data),p>t.length&&t.push(h.merge(d.deepCopy,{},d,b))),d.exports=m?b.factory.apply(d.context,t)||{}:b.factory,void 0===b.exports&&(b.exports=g?d.exports?h.merge(!0,{},g,d.exports):g:d.exports);b.state=3;if(u[c])for(;u[c].length;)u[c].pop()(c)}return function e(g,
|
||||
d){var a,b=l[g],m=h.is(b.factory,"function")?b.factory.length:0,p=b.amdStyle,k=[],t,s,r;a=[];var q,n;if(!d&&(b.requires||b.compiles||b.inherits)){b.requires&&z.apply(a,b.requires);b.inherits&&z.apply(a,b.inherits);b.compiles&&z.apply(a,b.compiles);for(q=0;n=a[q++];)if(l[n])if(3===l[n].state)a.splice(--q,1);else if(2===l[n].state)throw Error('Could not instantiate "'+UID+'"; dependency "'+dependency+'" has been rejected.');if(0<a.length){h.subordinate(a,function(){e(g,!0)},x);return}}void 0===(a=b.deepCopy)&&
|
||||
(a=v.deepCopy);b=l[g]=h.merge(a,{},v,b);if(m&&b.requires)for(s=b.requires&&(p?[]:{}),q=0;n=b.requires[q++];)l[n]?p?s.push(l[n].exports):h.is(l[n].exports,"function")?s[n]=l[n].exports:h.merge(a,s[n]={},l[n].exports):k.push(n);if(b.inherits)for(r=b.inherits&&{},q=0;n=b.inherits[q++];)l[n]?h.merge(a,r,l[n].exports):k.push(n);if(m&&b.compiles)for(t=b.compiles&&[],q=0;n=b.compiles[q++];)l[n]?t.push(l[n].exports):k.push(n);k.length?x(k,function(){},onError):f(g,s,r,t)}}();y.amd={};var x=function(){var f=
|
||||
b.toLowerCase())&&e[b])return e[b](a);throw'Unknown type "'+b+'"';}}();h.each=function(){var f=Array.prototype.some;return function(c,e,g){var d,a;if(void 0===c)return obj;g=g||h;if(f&&c.some===f)return c.some(e,g),c;if(h.is(c,"array")||h.is(c,"arraylike")){d=0;for(a=c.length;d<a&&(void 0===c[d]||!e.call(g,c[d],d,c));d++);return c}for(d in c)if(c.hasOwnProperty(d)&&e.call(g,c[d],d,c))break;return c}}();h.merge=function(f){var c,e,g,d,a,b=arguments.length,n=!1;f=arguments[0];var m=1,k,l,q=0;if(!0===
|
||||
f||!1===f)n=f,f=arguments[m],m++;h.is(arguments[b-1],"function")&&(a=arguments[b-1],b--);if(void 0===f)f={};else if(h.is(f,"primitive"))throw new TypeError("Cannot merge primitive data types: merge("+Array.prototype.join.call(arguments,", ")+")");l=h.is(f,"array");if(m<b)for(;m<=b;)if(d=arguments[m++]){l=l&&h.is(d,"array");for(g in d)e=f[g],c=d[g],void 0===c||c===f?l&&q--:(n&&c&&((k=h.is(c,"array"))||h.is(c,"untyped"))&&(c=h.merge(n,e||(k?h.is(e,"array")?e:[]:h.is(e,"untyped")?e:{}),c,a)),a&&a(g,
|
||||
f,d)||(q&&(g=+g+q),f[g]=c));q=0}return f};h.subordinate=function(){function f(a){if(!a||a.source===window&&a.data===g){var c=d.shift();a=c[0];var c=c[1],f=c.length;f?1===f?a(c[0]):2===f?a(c[0],c[1]):3===f?a(c[0],c[1],c[2]):4===f?a(c[0],c[1],c[2],c[3]):a.apply(0,c):a()}}var c=Array.prototype.slice,e=window.postMessage,g="__fandango@"+Math.random().toString(36),d=[],a=function(){return e?function(){e(g,"*")}:function(){setTimeout(f)}}();e&&window.addEventListener("message",f,!1);return function(b){a(d.push([arguments[arguments.length-
|
||||
1],c.call(arguments).slice(0,-1)])-1)}}();var G=function(){var f={},c=[].slice,e=function(){return[]};return function(g,d){function a(a,c){return new b(a,c)}function b(a,b){var c=0,d=n(a,b),f=d.length;this.context=b||document;this.selector=a;for(this.length=f;c<f;c++)this[c]=d[c];return this}var n,m,k,h;if(f[g])return f[g];for(h=d.length;m=d[--h];){m.selector&&(n=m.selector);if(source=m.prototype)if("function"===typeof source)source.call(b.prototype);else if(b.prototype.prototype)for(k in source)source.hasOwnProperty(k)&&
|
||||
(b.prototype[k]=source[k]);else b.prototype=source;if(source=m.utilities)if("function"===typeof source)source.utilities.call(a);else for(k in source)source.hasOwnProperty(k)&&(a[k]=source[k])}b.prototype.length=0;b.prototype.selector="";b.prototype.splice=c;b.prototype.fandango=1;n||(n=e);return f[g]=a}}(),E=function(){function f(c,f,g,d){var a,b=l[c],n=h.is(b.factory,"function"),m=n?b.factory.length:0,k=b.amdStyle,t,q;d&&(a=G(b.compiles+"",d));for(q in b.instances)d=b.instances[q],d.context=void 0===
|
||||
d.context?b.context:d.context,d.deepCopy=void 0===d.deepCopy?b.deepCopy:d.deepCopy,d.namespace=void 0===d.namespace?b.namespace:d.namespace,t=[],k?t=f||[]:(a&&t.push(a),f&&t.push(f),m>t.length&&t.push(d.data?h.merge(d.deepCopy,{},d.data,b.data):b.data),m>t.length&&t.push(h.merge(d.deepCopy,{},d,b))),d.exports=n?b.factory.apply(d.context,t)||{}:b.factory,void 0===b.exports&&(b.exports=g?d.exports?h.merge(!0,{},g,d.exports):g:d.exports);b.state=3;if(u[c])for(;u[c].length;)u[c].pop()(c)}return function e(g,
|
||||
d){var a,b=l[g],n=h.is(b.factory,"function")?b.factory.length:0,m=b.amdStyle,k=[],t,q,s;a=[];var r,p;if(!d&&(b.requires||b.compiles||b.inherits)){b.requires&&z.apply(a,b.requires);b.inherits&&z.apply(a,b.inherits);b.compiles&&z.apply(a,b.compiles);for(r=0;p=a[r++];)if(l[p])if(3===l[p].state)a.splice(--r,1);else if(2===l[p].state)throw Error('Could not instantiate "'+UID+'"; dependency "'+dependency+'" has been rejected.');if(0<a.length){h.subordinate(a,function(){e(g,!0)},x);return}}void 0===(a=b.deepCopy)&&
|
||||
(a=v.deepCopy);b=l[g]=h.merge(a,{},v,b);if(n&&b.requires)for(q=b.requires&&(m?[]:{}),r=0;p=b.requires[r++];)l[p]?m?q.push(l[p].exports):h.is(l[p].exports,"function")?q[p]=l[p].exports:h.merge(a,q[p]={},l[p].exports):k.push(p);if(b.inherits)for(s=b.inherits&&{},r=0;p=b.inherits[r++];)l[p]?h.merge(a,s,l[p].exports):k.push(p);if(n&&b.compiles)for(t=b.compiles&&[],r=0;p=b.compiles[r++];)l[p]?t.push(l[p].exports):k.push(p);k.length?x(k,function(){},onError):f(g,q,s,t)}}();y.amd={};var x=function(){var f=
|
||||
{},c=document.getElementsByTagName("head")[0],e="undefined"!==typeof opera&&"[object Opera]"===opera.toString(),g=function(a){var b=document.createElement("script");b.setAttribute("id",a);b.type="text/javascript";b.charset="utf-8";b.async=!0;return b},d=!(!((d=g())&&d.attachEvent&&d.attachEvent.toString&&0<d.attachEvent.toString().indexOf("[native code"))||e);buildUrl=function(){var a={"http://":1,"https://":1,"file://":1};return function(b){var c=b.toLowerCase(),d=c[0];"/"===d||"\\"===d||"h"===d&&
|
||||
(a[c.slice(0,7)]||a[c.slice(0,8)])||"f"===d&&a[c.slice(0,7)]||(b=v.baseUrl+b);".js"!==b.slice(-3)&&(b+=".js");return b}}();onErrorEvent=function(a,b,c,d){return function(e){f[b]=0;a.error=e||!0;d.parentElement.removeChild(d);if(a.onError)a.onError(e,c,b)}};onLoadEvent=function(a,b,c,d,e){return function(){if(2===f[b]){f[b]=3;if(a.onPartial)a.onPartial(b,c,d);e?d.onreadystatechange=null:(d.removeEventListener("load",a.loadListener),d.removeEventListener("error",a.errorListener));if(a.loaded.push(b)===
|
||||
a.paths.length&&a.onDone)a.onDone(a.load)}}};get=function(a){for(var b=0,e,h,k;!a.error&&(e=a.paths[b++]);)h=a.names[b-1],f[e]=2,k=g(e),d?k.attachEvent("onreadystatechange",onLoadEvent(a,e,h,k,!0)):(a.loadListener=onLoadEvent(a,e,h,k),a.errorListener=onErrorEvent(a,e,h,k),k.addEventListener("load",a.loadListener,!1),k.addEventListener("error",a.errorListener,!1)),k.src=e,c.appendChild(k)};return function(a,b,c,d){var e=[],g=[],s={paths:[],names:[],loaded:[],error:null,loadListener:null,errorListener:null},
|
||||
u,q,n,w,x;for(x=0;q=a[x++];)if(l[q])if(3===l[q].state)g.push(l[q].exports);else{if(2===l[q].state)throw Error("require(): Rejected dependency. Cannot continue.");E(q);e.push(q)}else f[u]||(u=buildUrl(v.paths[q]||q),s.paths.push(u),s.names.push(q)),e.push(q);b&&!e.length?b.apply(null,g):(s.paths&&(s.onError=function(a,b,d){a instanceof Event&&(a=Error('Could require "'+b+'"; an error occurred while trying to load "'+d+'".'));if(c)c(a);else throw a;},s.onPartial=function(a,b,c){l[b]||((n=v.shim[b])?
|
||||
(w=h.is(n.exports,"function")?n.exports:function(){return r[n.exports]},y(b,w)):y(C,b));E(b);d&&d(a,c)},get(s)),F(e,function(a){b.apply(null,a)},s.onError))}}();y("fandango",h);var H=r.fandango,I=r.define,J=r.require,w={fn:h,define:y,require:x,noConflict:function(f){r.define===y&&(r.define=I);r.require===x&&(r.require=J);f&&r.fandango===w&&(r.fandango=H);return w},defaults:function(f){return f?h.merge(v,f):v}};r.define||(r.define=w.define);r.require||(r.require=w.require);r.fandango=w})(this);
|
||||
a.paths.length&&a.onDone)a.onDone(a.load)}}};get=function(a){for(var b=0,e,h,k;!a.error&&(e=a.paths[b++]);)h=a.names[b-1],f[e]=2,k=g(e),d?k.attachEvent("onreadystatechange",onLoadEvent(a,e,h,k,!0)):(a.loadListener=onLoadEvent(a,e,h,k),a.errorListener=onErrorEvent(a,e,h,k),k.addEventListener("load",a.loadListener,!1),k.addEventListener("error",a.errorListener,!1)),k.src=e,c.appendChild(k)};return function(a,b,c,d){var e=[],g=[],q={paths:[],names:[],loaded:[],error:null,loadListener:null,errorListener:null},
|
||||
u,r,p,w,x;for(x=0;r=a[x++];)if(l[r])if(3===l[r].state)g.push(l[r].exports);else{if(2===l[r].state)throw Error("require(): Rejected dependency. Cannot continue.");E(r);e.push(r)}else f[u]||(u=buildUrl(v.paths[r]||r),q.paths.push(u),q.names.push(r)),e.push(r);b&&!e.length?b.apply(null,g):(q.paths&&(q.onError=function(a,b,d){a instanceof Event&&(a=Error('Could require "'+b+'"; an error occurred while trying to load "'+d+'".'));if(c)c(a);else throw a;},q.onPartial=function(a,b,c){l[b]||((p=v.shim[b])?
|
||||
(w=h.is(p.exports,"function")?p.exports:function(){return s[p.exports]},y(b,w)):y(C,b));E(b);d&&d(a,c)},get(q)),F(e,function(a){b.apply(null,a)},q.onError))}}();y("fandango",h);var H=s.fandango,I=s.define,J=s.require,w={fn:h,define:y,require:x,noConflict:function(f){s.define===y&&(s.define=I);s.require===x&&(s.require=J);f&&s.fandango===w&&(s.fandango=H);return w},defaults:function(f){return f?h.merge(v,f):v}};s.define||(s.define=w.define);s.require||(s.require=w.require);s.fandango=w})(this);
|
Loading…
Reference in New Issue