Comparar commits
61 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| ac361419b8 | |||
| 7985251207 | |||
| 5805778a17 | |||
| f522e0874e | |||
| 58bdceef45 | |||
| b20f678a38 | |||
| ba32c3b727 | |||
| a6ef421f79 | |||
| 9f7c470b05 | |||
| 0a5b025c3e | |||
| c75b3d2f31 | |||
| bb3fc41c32 | |||
| 6f05609dab | |||
| 0893da7df5 | |||
| 7658637231 | |||
| 01df091f45 | |||
| 9e7ab46683 | |||
| 1c3c68c7db | |||
| 48f51255a1 | |||
| 1678ebb345 | |||
| acf9bffb7e | |||
| dff403f604 | |||
| 80d5d177f5 | |||
| 786aec2505 | |||
| 438ea86155 | |||
| ed404bffcb | |||
| 1b1a7a5159 | |||
| fd191229a0 | |||
| c8747974ee | |||
| d6caf96690 | |||
| 8b94d6c411 | |||
| 5226091385 | |||
| a89a9f0ac4 | |||
| 519ae5c751 | |||
| 014375eea3 | |||
| e1097a73d5 | |||
| 26282c4929 | |||
| b52aab4136 | |||
| ad03007044 | |||
| b38ba6a3c5 | |||
| 8c26db802f | |||
| 7a7015078a | |||
| 2742cdd014 | |||
| c1d9011d70 | |||
| 884e776d3e | |||
| 677587ca05 | |||
| d0afe8590d | |||
| 5be7d482e7 | |||
| ea69a15a62 | |||
| 6899d8e63d | |||
| c819c7ec43 | |||
| 8d2675e328 | |||
| c44ec4751d | |||
| 9a9bbfef50 | |||
| 3be668abaf | |||
| b98e531bca | |||
| 02896ecc4a | |||
| 43289d0d17 | |||
| eeac0be514 | |||
| f00a7fe1c3 | |||
| eb5a174e3b |
+21
-29
@@ -10,6 +10,7 @@ community experience.
|
||||
|
||||
* Instant communication between connected users
|
||||
* Robust backend server built on [Node.js](http://nodejs.org)
|
||||
* Support for [Socket.IO](http://socket.io), JSON and JSONP
|
||||
* Can be integrated with virtually any existing website
|
||||
* Seamless authentication
|
||||
* Works across an entire website, unobtrusively
|
||||
@@ -20,43 +21,34 @@ community experience.
|
||||
## Installation
|
||||
|
||||
Install `Node.js`:
|
||||
wget http://nodejs.org/dist/node-v0.2.5.tar.gz
|
||||
tar xzf node-v0.2.5.tar.gz
|
||||
cd node-v0.2.5
|
||||
|
||||
wget http://nodejs.org/dist/v0.10.32/node-v0.10.32-linux-x86.tar.gz
|
||||
tar xzf node-v0.10.32-linux-x86.tar.gz
|
||||
cd node-v0.10.32-linux-x86
|
||||
./configure
|
||||
make
|
||||
make install
|
||||
|
||||
Install Node Package Manager (`npm`):
|
||||
See instructions at http://github.com/isaacs/npm.
|
||||
Install Ajax IM:
|
||||
|
||||
Install `Express.js` and `Connect` (included automatically):
|
||||
npm install express
|
||||
|
||||
Compile the daemon add-on if you plan on letting the server daemonize itself:
|
||||
cd server/libs/daemon
|
||||
node-waf configure build
|
||||
cp build/default/daemon.node .
|
||||
rm -rf build
|
||||
|
||||
## Installation for Development
|
||||
|
||||
If you want to test Ajax IM as a standalone app for development, you will need
|
||||
to install [`Jade`](http://github.com/visionmedia/jade) as well.
|
||||
|
||||
To install `Jade`:
|
||||
npm install jade
|
||||
unzip AjaxIM_v4.0a4.zip
|
||||
cd AjaxIM_v4.0a4
|
||||
npm install
|
||||
|
||||
## Starting up the server
|
||||
|
||||
Starting the server in _development_ mode is as simple as:
|
||||
|
||||
node server/app.js
|
||||
|
||||
To start the server in _production_ mode:
|
||||
EXPRESS_ENV=production node server/app.js
|
||||
|
||||
To start the server as a _daemon_ in _production_ mode:
|
||||
node server/app.js start production
|
||||
NODE_ENV=production node server/app.js
|
||||
|
||||
To start the server using forever with a log file:
|
||||
|
||||
npm install forever
|
||||
forever -l ~/ajaxim.log start ~/AjaxIM_v4.0a4/server/app.js
|
||||
|
||||
## Testing it out
|
||||
|
||||
@@ -65,24 +57,23 @@ through the included development testing app. The below instructions are
|
||||
assuming that you have left all default configuration options. If not, please
|
||||
replace the host/port values with the correct ones.
|
||||
|
||||
To get started, first initialize a session cookie by going to:
|
||||
http://localhost:8000/dev/cookie
|
||||
To get started, head over to the development page:
|
||||
|
||||
Then head over to the development page that will initialize the client:
|
||||
http://localhost:8000/dev/
|
||||
|
||||
That's it!
|
||||
|
||||
## More Information
|
||||
|
||||
* Follow [endtwist](http://twitter.com/endtwist) on twitter for updates
|
||||
* Follow [ajaximrpg](http://twitter.com/ajaximrpg) on twitter for updates
|
||||
* [Google Group](http://groups.google.com/group/ajaxim) for discussion
|
||||
* [GitHub Wiki](https://github.com/endtwist/AjaxIM/wiki) for guidance
|
||||
|
||||
## Node Compatibility
|
||||
|
||||
The `master` branch of Ajax IM is compatible with node --version:
|
||||
v0.2.5
|
||||
|
||||
v0.10.32
|
||||
|
||||
## Contributing
|
||||
|
||||
@@ -220,6 +211,7 @@ Methods:
|
||||
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2012-2014 [Daniel Howard] (http://www.svexpertise.com)
|
||||
Copyright (c) 2010 [Joshua Gross](http://www.unwieldy.net)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
|
||||
Arquivo binário não exibido.
@@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Ajax IM</title>
|
||||
<script src="js/jquery-1.11.1.js" type="text/javascript"></script>
|
||||
<script src="js/md5.js" type="text/javascript"></script>
|
||||
<script src="js/store.js" type="text/javascript"></script>
|
||||
<script src="js/dateformat.js" type="text/javascript"></script>
|
||||
<script src="js/im.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
$(function(){
|
||||
var u = window.location.href.split("/");
|
||||
var p = 8000; // Node.js port
|
||||
u = u[0]+"//"+u[2]+":"+p;
|
||||
var im = AjaxIM.init({pollServer: u, theme: "themes/default"});
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
Hello.
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,48 +0,0 @@
|
||||
// Cookies API
|
||||
var cookies = {
|
||||
// === {{{AjaxIM.}}}**{{{cookies.set(name, value, days)}}}** ===
|
||||
//
|
||||
// Sets a cookie, stringifying the JSON value upon storing it.
|
||||
//
|
||||
// ==== Parameters ====
|
||||
// * {{{name}}} is the cookie name.\\
|
||||
// * {{{value}}} is the cookie data that you would like to store.\\
|
||||
// * {{{days}}} is the number of days that the cookie will be stored for.
|
||||
set: function(name, value, days) {
|
||||
if (days) {
|
||||
var date = new Date();
|
||||
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
|
||||
var expires = "; expires=" + date.toGMTString();
|
||||
} else var expires = "";
|
||||
document.cookie = name + "=" + JSON.stringify(value) + expires + "; path=/";
|
||||
},
|
||||
|
||||
// === {{{AjaxIM.}}}**{{{cookies.get(name)}}}** ===
|
||||
//
|
||||
// Gets a cookie, decoding the JSON value before returning the data.
|
||||
//
|
||||
// ==== Parameters ====
|
||||
// * {{{name}}} is the cookie name that you would like to retrieve.
|
||||
get: function(name) {
|
||||
var nameEQ = name + "=";
|
||||
var ca = document.cookie.split(';');
|
||||
for(var i = 0; i < ca.length; i++) {
|
||||
var c = ca[i];
|
||||
while (c.charAt(0) == ' ') c = c.substring(1, c.length);
|
||||
if (c.indexOf(nameEQ) == 0) {
|
||||
var cval = decodeURIComponent(c.substring(nameEQ.length, c.length));
|
||||
return JSON.parse(cval);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
// === {{{AjaxIM.}}}**{{{cookies.erase(name)}}}** ===
|
||||
//
|
||||
// Deletes a cookie.
|
||||
//
|
||||
// {{{name}}} is the existing cookie that you would like to delete.
|
||||
erase: function(name) {
|
||||
this.set(name, '', -1);
|
||||
}
|
||||
};
|
||||
+351
-212
@@ -47,75 +47,96 @@ AjaxIM = function(options, actions) {
|
||||
// requests rather than POST requests (such as how the Node.JS Ajax IM
|
||||
// server works).
|
||||
this.actions = $.extend({
|
||||
listen: this.settings.pollServer + '/listen',
|
||||
send: this.settings.pollServer + '/message',
|
||||
status: this.settings.pollServer + '/status',
|
||||
signoff: this.settings.pollServer + '/signoff'
|
||||
noop: this.settings.pollServer + '/app/noop',
|
||||
listen: this.settings.pollServer + '/app/listen',
|
||||
send: this.settings.pollServer + '/app/message',
|
||||
status: this.settings.pollServer + '/app/status',
|
||||
signoff: this.settings.pollServer + '/app/signoff'
|
||||
}, actions);
|
||||
|
||||
if (!store.get('sessionid')) {
|
||||
store.set('sessionid', AjaxIM.uid(40));
|
||||
}
|
||||
|
||||
// If Socket.IO is available, create a socket
|
||||
self.socket = null;
|
||||
$.getScript(this.settings.pollServer+'/socket.io/socket.io.js', function(){
|
||||
self.socket = io(self.settings.pollServer);
|
||||
self.socket.on('client', function(event) {
|
||||
event = $.extend(true, {}, event);
|
||||
self.dispatchEvent(event);
|
||||
});
|
||||
var event = {type: 'hello', from: store.get('user')};
|
||||
self.sendEvent(event, function() {}, function() {});
|
||||
});
|
||||
|
||||
// We load the theme dynamically based on the passed
|
||||
// settings. If the theme is set to false, we assume
|
||||
// that the user is going to load it himself.
|
||||
this.themeLoaded = false;
|
||||
if(this.settings.theme) {
|
||||
$('<div>').appendTo('body').load(this.settings.theme + '/theme.html #imjs-bar, .imjs-tooltip',
|
||||
if (this.settings.theme) {
|
||||
if(typeof document.createStyleSheet == 'function') {
|
||||
document.createStyleSheet(this.settings.theme + '/theme.css');
|
||||
} else {
|
||||
$('body').append('<link rel="stylesheet" href="' +
|
||||
this.settings.theme + '/theme.css" />');
|
||||
}
|
||||
$('<div>').appendTo('body').load(this.settings.theme +
|
||||
'/theme.html #imjs-bar, .imjs-tooltip',
|
||||
function() {
|
||||
self.themeLoaded = true;
|
||||
self.setup();
|
||||
}
|
||||
);
|
||||
if(typeof document.createStyleSheet == 'function')
|
||||
document.createStyleSheet(this.settings.theme + '/theme.css');
|
||||
else
|
||||
$('body').append('<link rel="stylesheet" href="' +
|
||||
this.settings.theme + '/theme.css" />');
|
||||
} else {
|
||||
this.themeLoaded = true;
|
||||
this.setup();
|
||||
}
|
||||
|
||||
// Allow a chatbox to be minimized
|
||||
$('.imjs-chatbox').live('click', function(e) {
|
||||
$(document).on('click', '.imjs-chatbox', function(e) {
|
||||
e.preventDefault();
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.imjs-chatbox .imjs-minimize').live('click', function() {
|
||||
$(document).on('click', '.imjs-chatbox .imjs-minimize', function() {
|
||||
$(this).parents('.imjs-selected').click();
|
||||
});
|
||||
|
||||
// Setup message sending for all chatboxes
|
||||
$('.imjs-chatbox .imjs-input').live('keydown', function(event) {
|
||||
$(document).on('keydown', '.imjs-chatbox .imjs-input', function(event) {
|
||||
var obj = $(this);
|
||||
if(event.keyCode == 13 && !($.browser.msie && $.browser.version < 8)) {
|
||||
// if(event.keyCode == 13 && !($.browser.msie && $.browser.version < 8)) {
|
||||
if(event.keyCode == 13) {
|
||||
self.send(obj.parents('.imjs-chatbox').data('username'), obj.val());
|
||||
}
|
||||
}).live('keyup', function(event) {
|
||||
}).on('keyup', '.imjs-chatbox .imjs-input', function(event) {
|
||||
if(event.keyCode == 13) {
|
||||
if($.browser.msie && $.browser.version < 8) {
|
||||
// if($.browser.msie && $.browser.version < 8) {
|
||||
if(false) {
|
||||
var obj = $(this);
|
||||
self.send(obj.parents('.imjs-chatbox').data('username'), obj.val());
|
||||
}
|
||||
|
||||
var obj = $(this);
|
||||
obj.val('');
|
||||
obj.height(obj.data('height'));
|
||||
}
|
||||
}).live('keypress', function(e) {
|
||||
}).on('keypress', '.imjs-chatbox .imjs-input', function(e) {
|
||||
var obj = $(this);
|
||||
if(!($.browser.msie && $.browser.opera)) obj.height(0);
|
||||
obj.height(0);
|
||||
if(true) obj.height(0);
|
||||
if(this.scrollHeight > obj.height() || this.scrollHeight < obj.height()) {
|
||||
obj.height(this.scrollHeight);
|
||||
}
|
||||
});
|
||||
|
||||
$('.imjs-msglog').live('click', function() {
|
||||
$(document).on('click', '.imjs-msglog', function() {
|
||||
var chatbox = $(this).parents('.imjs-chatbox');
|
||||
chatbox.find('.imjs-input').focus();
|
||||
});
|
||||
|
||||
// Create a chatbox when a buddylist item is clicked
|
||||
$('.imjs-friend').live('click', function() {
|
||||
$(document).on('click', '.imjs-friend', function() {
|
||||
var chatbox = self._createChatbox($(this).data('friend'));
|
||||
|
||||
if(chatbox.parents('.imjs-tab').data('state') != 'active') {
|
||||
@@ -126,13 +147,16 @@ AjaxIM = function(options, actions) {
|
||||
chatbox.find('.imjs-input').focus();
|
||||
if(!(input = chatbox.find('.imjs-input')).data('height')) {
|
||||
// store the height for resizing later
|
||||
if (!input.height()) {
|
||||
input.height(16);
|
||||
}
|
||||
input.data('height', input.height());
|
||||
}
|
||||
});
|
||||
|
||||
// Setup and hide the scrollers
|
||||
$('.imjs-scroll').css('display', 'none');
|
||||
$('#imjs-scroll-right').live('click', function() {
|
||||
$(document).on('click', '#imjs-scroll-right', function() {
|
||||
var hiddenTab = $(this)
|
||||
.prevAll('#imjs-bar li.imjs-tab:hidden')
|
||||
.filter(function() {
|
||||
@@ -153,7 +177,7 @@ AjaxIM = function(options, actions) {
|
||||
|
||||
return false;
|
||||
});
|
||||
$('#imjs-scroll-left').live('click', function() {
|
||||
$(document).on('click', '#imjs-scroll-left', function() {
|
||||
var hiddenTab = $(this)
|
||||
.nextAll('#imjs-bar li.imjs-tab:hidden')
|
||||
.filter(function() {
|
||||
@@ -176,7 +200,7 @@ AjaxIM = function(options, actions) {
|
||||
});
|
||||
|
||||
// Setup status buttons
|
||||
$('#imjs-status-panel .imjs-button').live('click', function() {
|
||||
$(document).on('click', '#imjs-status-panel .imjs-button', function() {
|
||||
var status = this.id.split('-')[2];
|
||||
|
||||
$('#imjs-away-message-text, #imjs-away-message-text-arrow').animate({
|
||||
@@ -200,8 +224,8 @@ AjaxIM = function(options, actions) {
|
||||
});
|
||||
|
||||
// Allow status message to be changed
|
||||
$('#imjs-away-message-text')
|
||||
.live('keyup', (function() {
|
||||
$(document)
|
||||
.on('keyup', '#imjs-away-message-text', (function() {
|
||||
var msg_type_timer = null;
|
||||
|
||||
return function() {
|
||||
@@ -220,7 +244,7 @@ AjaxIM = function(options, actions) {
|
||||
});
|
||||
|
||||
// Setup reconnect button
|
||||
$('#imjs-reconnect').live('click', function() {
|
||||
$(document).on('click', '#imjs-reconnect', function() {
|
||||
self.offline = false;
|
||||
store.remove(self.username + '-offline');
|
||||
$('#imjs-reconnect').hide();
|
||||
@@ -255,6 +279,13 @@ AjaxIM = function(options, actions) {
|
||||
self._scrollers();
|
||||
} catch(e) {}
|
||||
});
|
||||
|
||||
// Set up event handling
|
||||
$(this).on('hello', AjaxIM.onObj(this, this.onHello));
|
||||
$(this).on('message', AjaxIM.onObj(this, this.onMessage));
|
||||
$(this).on('status', AjaxIM.onObj(this, this.onStatus));
|
||||
$(this).on('notice', AjaxIM.onObj(this, this.onNotice));
|
||||
$(this).on('goodbye', AjaxIM.onObj(this, this.onGoodbye));
|
||||
} else {
|
||||
return AjaxIM.init(options);
|
||||
}
|
||||
@@ -263,8 +294,10 @@ AjaxIM = function(options, actions) {
|
||||
$.extend(AjaxIM.prototype, {
|
||||
// == Main ==
|
||||
setup: function() {
|
||||
var self = this;
|
||||
$(this).trigger('loadComplete');
|
||||
|
||||
$('.imjs-scroll').css('display', 'none');
|
||||
this.initTabBar();
|
||||
this._scrollers();
|
||||
|
||||
@@ -274,7 +307,6 @@ $.extend(AjaxIM.prototype, {
|
||||
if(this.username && store.get(this.username + '-offline') == true) {
|
||||
this.offline = true;
|
||||
|
||||
var self = this;
|
||||
setTimeout(function() { self._showReconnect(); }, 0);
|
||||
return;
|
||||
}
|
||||
@@ -282,7 +314,7 @@ $.extend(AjaxIM.prototype, {
|
||||
if(this.username)
|
||||
this.storage();
|
||||
|
||||
this.listen();
|
||||
setTimeout(function() { if (!self.socket) self.listen(); }, 2000);
|
||||
},
|
||||
|
||||
// === {{{AjaxIM.}}}**{{{storage()}}}** ===
|
||||
@@ -340,7 +372,7 @@ $.extend(AjaxIM.prototype, {
|
||||
var msglog = this.chats[activeTab].find('.imjs-msglog');
|
||||
msglog[0].scrollTop = msglog[0].scrollHeight;
|
||||
}
|
||||
|
||||
|
||||
// Set username in Friends list
|
||||
var header = $('#imjs-friends-panel .imjs-header');
|
||||
header.html(header.html().replace('{username}', this.username));
|
||||
@@ -375,14 +407,23 @@ $.extend(AjaxIM.prototype, {
|
||||
if(this.offline) return;
|
||||
|
||||
var self = this;
|
||||
AjaxIM.get(
|
||||
self.request(
|
||||
this.actions.listen,
|
||||
{},
|
||||
function(response) {
|
||||
if(response)
|
||||
self._parseMessage(response);
|
||||
'GET',
|
||||
{type: 'hello', from: store.get('user'), sessionid: store.get('sessionid')},
|
||||
function(event) {
|
||||
if($.isArray(event)) {
|
||||
$.each(event, function(key, event) {
|
||||
$(self).trigger(event.type, event);
|
||||
});
|
||||
}
|
||||
else if($.isPlainObject(event)) {
|
||||
$(self).trigger(event.type, event);
|
||||
}
|
||||
|
||||
setTimeout(function() { self.listen(); }, 0);
|
||||
if (!self.socket) {
|
||||
setTimeout(function() { self.listen(); }, 0);
|
||||
}
|
||||
},
|
||||
function(error) {
|
||||
self._notConnected();
|
||||
@@ -393,67 +434,57 @@ $.extend(AjaxIM.prototype, {
|
||||
? 1000
|
||||
: Math.min(self._reconnectIn * 2, 16000);
|
||||
self._lastReconnect = new Date();
|
||||
setTimeout(function() { self.listen(); }, self._reconnectIn);
|
||||
if (!self.socket) {
|
||||
setTimeout(function() { self.listen(); }, self._reconnectIn);
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
// === //private// {{{AjaxIM.}}}**{{{_parseMessages(messages)}}}** ===
|
||||
//
|
||||
_parseMessage: function(message) {
|
||||
onHello: function(message) {
|
||||
var self = this;
|
||||
$(this).trigger('parseMessage', [message]);
|
||||
this._clearSession();
|
||||
|
||||
switch(message.type) {
|
||||
case 'hello':
|
||||
this._clearSession();
|
||||
this.username = message.username;
|
||||
this.current_status = ['available', ''];
|
||||
store.set('user', message.username);
|
||||
store.set(this.username + '-status', this.current_status);
|
||||
|
||||
this.username = message.username;
|
||||
this.current_status = ['available', ''];
|
||||
store.set('user', message.username);
|
||||
store.set(this.username + '-status', this.current_status);
|
||||
$('#imjs-friends').attr('class', 'imjs-available');
|
||||
$.each(message.friends, function() {
|
||||
var friend;
|
||||
if(this.length == 2)
|
||||
friend = this;
|
||||
else
|
||||
friend = [this.toString(), ['offline', '']];
|
||||
self.addFriend(friend[0], friend[1], 'Friends');
|
||||
});
|
||||
store.set(this.username + '-friends', this.friends);
|
||||
|
||||
$('#imjs-friends').attr('class', 'imjs-available');
|
||||
$.each(message.friends, function() {
|
||||
var friend;
|
||||
if(this.length == 2)
|
||||
friend = this;
|
||||
else
|
||||
friend = [this.toString(), ['offline', '']];
|
||||
self.addFriend(friend[0], friend[1], 'Friends');
|
||||
});
|
||||
store.set(this.username + '-friends', this.friends);
|
||||
|
||||
// Set username in Friends list
|
||||
var header = $('#imjs-friends-panel .imjs-header');
|
||||
header.html(header.html().replace('{username}', this.username));
|
||||
|
||||
// Set status available
|
||||
$('#imjs-away-message-text, #imjs-away-message-text-arrow').hide();
|
||||
$('#imjs-status-panel .imjs-button').removeClass('imjs-toggled');
|
||||
$('#imjs-button-available').addClass('imjs-toggled');
|
||||
break;
|
||||
// Set username in Friends list
|
||||
var header = $('#imjs-friends-panel .imjs-header');
|
||||
header.html(header.html().replace('{username}', this.username));
|
||||
|
||||
case 'message':
|
||||
this.incoming(message.user, message.body);
|
||||
break;
|
||||
// Set status available
|
||||
$('#imjs-away-message-text, #imjs-away-message-text-arrow').hide();
|
||||
$('#imjs-status-panel .imjs-button').removeClass('imjs-toggled');
|
||||
$('#imjs-button-available').addClass('imjs-toggled');
|
||||
},
|
||||
|
||||
case 'status':
|
||||
this._friendUpdate(message.user, message.status,
|
||||
message.message);
|
||||
this._storeFriends();
|
||||
break;
|
||||
onMessage: function(event) {
|
||||
this.incoming(event.from, event.body);
|
||||
},
|
||||
|
||||
case 'notice':
|
||||
break;
|
||||
|
||||
case 'goodbye':
|
||||
this._notConnected();
|
||||
break;
|
||||
onStatus: function(event) {
|
||||
this._friendUpdate(event.from, event.status, event.message);
|
||||
this._storeFriends();
|
||||
},
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
onNotice: function(event) {
|
||||
},
|
||||
|
||||
onGoodbye: function(event) {
|
||||
this._notConnected();
|
||||
},
|
||||
|
||||
// === {{{AjaxIM.}}}**{{{incoming(from, message)}}}** ===
|
||||
@@ -516,8 +547,8 @@ $.extend(AjaxIM.prototype, {
|
||||
.attr('id', user_id)
|
||||
.data('friend', username)
|
||||
.appendTo(group_item.find('ul'));
|
||||
if(status[0] == 'offline')
|
||||
user_item.hide();
|
||||
// if(status[0] == 'offline')
|
||||
// user_item.hide();
|
||||
user_item.html(
|
||||
user_item.html()
|
||||
.replace('{username}', username)
|
||||
@@ -622,7 +653,7 @@ $.extend(AjaxIM.prototype, {
|
||||
this.notification(tab);
|
||||
}
|
||||
|
||||
setTimeout(function() { self._scrollers() }, 0);
|
||||
setTimeout(function() { self._scrollers(); }, 0);
|
||||
}
|
||||
|
||||
return chatbox;
|
||||
@@ -837,7 +868,7 @@ $.extend(AjaxIM.prototype, {
|
||||
|
||||
var date_stamp_date = date_stamp.find('.imjs-date-date').html(
|
||||
AjaxIM.l10n[
|
||||
'chat' + status.toUpperCase() + status.slice(1)
|
||||
'chat' + status.toUpperCase().slice(0, 1) + status.slice(1)
|
||||
].replace(/%s/g, friend));
|
||||
|
||||
var msglog = this.chats[friend].find('.imjs-msglog');
|
||||
@@ -845,6 +876,9 @@ $.extend(AjaxIM.prototype, {
|
||||
msglog[0].scrollTop = msglog[0].scrollHeight;
|
||||
}
|
||||
|
||||
if (!this.friends[friend]) {
|
||||
this.addFriend(friend, [status, statusMessage], 'Friends');
|
||||
}
|
||||
if(this.friends[friend]) {
|
||||
var friend_id = 'imjs-friend-' + md5.hex(friend + this.friends[friend].group);
|
||||
$('#' + friend_id).attr('class', 'imjs-friend imjs-' + status);
|
||||
@@ -876,7 +910,7 @@ $.extend(AjaxIM.prototype, {
|
||||
if($('#imjs-friends').hasClass('imjs-selected'))
|
||||
this.activateTab($('#imjs-friends'));
|
||||
},
|
||||
|
||||
|
||||
_showReconnect: function() {
|
||||
$('#imjs-reconnect').show();
|
||||
},
|
||||
@@ -913,23 +947,17 @@ $.extend(AjaxIM.prototype, {
|
||||
|
||||
$(this).trigger('sendingMessage', [username, body]);
|
||||
|
||||
AjaxIM.post(
|
||||
this.actions.send,
|
||||
{to: username, body: body},
|
||||
function(result) {
|
||||
if(result.type == 'success' && result.success == 'sent') {
|
||||
$(self).trigger('sendMessageSuccessful',
|
||||
[username, body]);
|
||||
var event = {type: 'message', from: this.username, to: username, body: body};
|
||||
this.sendEvent(event, function(result) {
|
||||
if(result._status.sent) {
|
||||
$(self).trigger('sendMessageSuccessful', [username, body]);
|
||||
} else if(result.type == 'error') {
|
||||
if(result.error == 'not online')
|
||||
$(self).trigger('sendMessageFailed',
|
||||
['offline', username, body]);
|
||||
$(self).trigger('sendMessageFailed', ['offline', username, body]);
|
||||
else
|
||||
$(self).trigger('sendMessageFailed',
|
||||
[result.error, username, body]);
|
||||
$(self).trigger('sendMessageFailed', [result.error, username, body]);
|
||||
}
|
||||
},
|
||||
function(error) {
|
||||
}, function(error) {
|
||||
self._notConnected();
|
||||
var error = self._addError(
|
||||
self.chats[username],
|
||||
@@ -937,11 +965,13 @@ $.extend(AjaxIM.prototype, {
|
||||
'server is not available. Please ensure ' +
|
||||
'that you are signed in and try again.');
|
||||
self._store(error);
|
||||
|
||||
$(self).trigger('sendMessageFailed',
|
||||
['not connected', username, body]);
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
|
||||
signOff: function() {
|
||||
this.status('offline', '');
|
||||
},
|
||||
|
||||
// === {{{AjaxIM.}}}**{{{status(s, message)}}}** ===
|
||||
@@ -976,13 +1006,10 @@ $.extend(AjaxIM.prototype, {
|
||||
self.offline = true;
|
||||
$('.imjs-input').attr('disabled', true);
|
||||
|
||||
AjaxIM.post(
|
||||
this.actions.signoff,
|
||||
{},
|
||||
function(result) {
|
||||
if(result.type == 'success')
|
||||
$(self).trigger('changeStatusSuccessful',
|
||||
[value, null]);
|
||||
var event = {type: 'signoff', message: message};
|
||||
this.sendEvent(event, function(result) {
|
||||
if(result.type == 'success')
|
||||
$(self).trigger('changeStatusSuccessful', [value, null]);
|
||||
},
|
||||
function(error) {
|
||||
$(self).trigger('changeStatusFailed',
|
||||
@@ -990,31 +1017,27 @@ $.extend(AjaxIM.prototype, {
|
||||
}
|
||||
);
|
||||
} else {
|
||||
AjaxIM.post(
|
||||
this.actions.status,
|
||||
{status: value, message: message},
|
||||
function(result) {
|
||||
switch(result.type) {
|
||||
case 'success':
|
||||
$(self).trigger('changeStatusSuccessful',
|
||||
[value, message]);
|
||||
self.current_status = [value, message];
|
||||
store.set(self.username + '-status',
|
||||
self.current_status);
|
||||
break;
|
||||
|
||||
case 'error':
|
||||
default:
|
||||
$(self).trigger('changeStatusFailed',
|
||||
[result.e, value, message]);
|
||||
break;
|
||||
}
|
||||
},
|
||||
function(error) {
|
||||
$(self).trigger('changeStatusFailed',
|
||||
['not connected', value, message]);
|
||||
}
|
||||
);
|
||||
var event = {type: 'status', status: value, message: message};
|
||||
this.sendEvent(event, function(result) {
|
||||
if(result._status.send) {
|
||||
$(self).trigger('sendMessageSuccessful', [username, body]);
|
||||
} else if(result.type == 'error') {
|
||||
if(result.error == 'not online')
|
||||
$(self).trigger('sendMessageFailed', ['offline', username, body]);
|
||||
else
|
||||
$(self).trigger('sendMessageFailed', [result.error, username, body]);
|
||||
}
|
||||
}, function(error) {
|
||||
self._notConnected();
|
||||
var error = self._addError(
|
||||
self.chats[username],
|
||||
'You are currently not connected or the ' +
|
||||
'server is not available. Please ensure ' +
|
||||
'that you are signed in and try again.');
|
||||
self._store(error);
|
||||
$(self).trigger('sendMessageFailed',
|
||||
['not connected', username, body]);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1045,13 +1068,13 @@ $.extend(AjaxIM.prototype, {
|
||||
var self = this;
|
||||
|
||||
// Set up your standard tab actions
|
||||
$('.imjs-tab')
|
||||
.live('click', function() {
|
||||
$(document)
|
||||
.on('click', '.imjs-tab', function() {
|
||||
return self.activateTab.call(self, $(this));
|
||||
});
|
||||
|
||||
$('.imjs-tab .imjs-close')
|
||||
.live('click', function() {
|
||||
$(document)
|
||||
.on('click', '.imjs-tab .imjs-close', function() {
|
||||
return self.closeTab.call(self, $(this));
|
||||
});
|
||||
|
||||
@@ -1167,13 +1190,16 @@ $.extend(AjaxIM.prototype, {
|
||||
if(chatbox) {
|
||||
if((input = chatbox.find('.imjs-input')).length &&
|
||||
!input.data('height')) {
|
||||
if(!($.browser.msie && $.browser.opera)) input.height(0);
|
||||
input.height(0);
|
||||
if(input[0].scrollHeight > input.height() ||
|
||||
input[0].scrollHeight < input.height()) {
|
||||
input.height(input[0].scrollHeight);
|
||||
}
|
||||
|
||||
// store the height for resizing later
|
||||
if (!input.height()) {
|
||||
input.height(16);
|
||||
}
|
||||
input.data('height', input.height());
|
||||
}
|
||||
|
||||
@@ -1281,8 +1307,8 @@ $.extend(AjaxIM.prototype, {
|
||||
|
||||
var tab_pos = tab.position();
|
||||
if(tab_pos.top >= $('#imjs-bar').height() ||
|
||||
tab_pos.left < 0 ||
|
||||
tab_pos.right > $(document).width()) {
|
||||
tab_pos.left < 0 ||
|
||||
tab_pos.right > $(document).width()) {
|
||||
$('.imjs-scroll').css('display', '');
|
||||
tab.css('display', 'none');
|
||||
needScrollers = true;
|
||||
@@ -1311,20 +1337,177 @@ $.extend(AjaxIM.prototype, {
|
||||
.nextAll('#imjs-bar li.imjs-tab:hidden')
|
||||
.not('.imjs-default')
|
||||
.filter(function() {
|
||||
return $(this).data('state') != 'closed'
|
||||
return $(this).data('state') != 'closed';
|
||||
}).length;
|
||||
|
||||
var hiddenLeft = $('#imjs-bar li.imjs-tab:visible').eq(0)
|
||||
.prevAll('#imjs-bar li.imjs-tab:hidden')
|
||||
.not('.imjs-default')
|
||||
.filter(function() {
|
||||
return $(this).data('state') != 'closed'
|
||||
return $(this).data('state') != 'closed';
|
||||
}).length;
|
||||
|
||||
$('#imjs-scroll-left').html(hiddenLeft);
|
||||
$('#imjs-scroll-right').html(hiddenRight);
|
||||
},
|
||||
|
||||
unconfirmedEvents: {},
|
||||
eventId: 1,
|
||||
|
||||
createEvent: function() {
|
||||
var event = {};
|
||||
event.id = this.eventId++;;
|
||||
this.unconfirmedEvents[event.id] = evt;
|
||||
},
|
||||
|
||||
sendEvent: function(event, successFunc, failureFunc) {
|
||||
event.sessionid = store.get('sessionid');
|
||||
event.id = this.eventId++;
|
||||
var evt = $.extend({}, event);
|
||||
evt['_status'] = {
|
||||
successFunc: successFunc,
|
||||
failureFunc: failureFunc
|
||||
};
|
||||
this.unconfirmedEvents[event.id] = evt;
|
||||
if (this.socket) {
|
||||
this.socket.emit('server', event);
|
||||
} else {
|
||||
var self = this;
|
||||
var url = null;
|
||||
switch (event.type) {
|
||||
case 'message':
|
||||
url = this.actions.send;
|
||||
break;
|
||||
case 'status':
|
||||
url = this.actions.status;
|
||||
break;
|
||||
case 'signoff':
|
||||
url = this.actions.signoff;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
self.request(url, 'POST', event,
|
||||
function(result) {
|
||||
if (result) {
|
||||
for (var e=0; e < result.length; ++e) {
|
||||
self.dispatchEvent(events[e]);
|
||||
}
|
||||
}
|
||||
},
|
||||
function(error) {
|
||||
if (self.unconfirmedEvents[event.id]) {
|
||||
event = self.unconfirmedEvents[event.id];
|
||||
event['_status']['sent'] = false;
|
||||
self.dispatchEvent(event);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
dispatchEvent: function(event) {
|
||||
if (event.id && this.unconfirmedEvents[event.id]) {
|
||||
event['_status'] = $.extend({}, this.unconfirmedEvents[event.id]['_status'], event['_status']);
|
||||
delete this.unconfirmedEvents[event.id];
|
||||
if (event['_status']['sent']) {
|
||||
event['_status']['successFunc'](event);
|
||||
} else {
|
||||
event['_status']['failureFunc'](event);
|
||||
}
|
||||
} else {
|
||||
$(this).trigger(event.type, event);
|
||||
}
|
||||
},
|
||||
|
||||
// === {{{AjaxIM.}}}**{{{request(url, data, successFunc, failureFunc)}}}** ===
|
||||
//
|
||||
// Wrapper around {{{$.jsonp}}}, the JSON-P library for jQuery, and {{{$.ajax}}},
|
||||
// jQuery's ajax library. Allows either function to be called, automatically,
|
||||
// depending on the request's URL array (see {{{AjaxIM.actions}}}).
|
||||
//
|
||||
// ==== Parameters ====
|
||||
// {{{url}}} is the URL of the request.
|
||||
// {{{data}}} are any arguments that go along with the request.
|
||||
// {{{success}}} is a callback function called when a request has completed
|
||||
// without issue.
|
||||
// {{{_ignore_}}} is simply to provide compatability with {{{$.post}}}.
|
||||
// {{{failure}}} is a callback function called when a request hasn't not
|
||||
// completed successfully.
|
||||
request: function(url, type, data, successFunc, failureFunc, noopurl) {
|
||||
var self = this;
|
||||
var errorTypes = ['timeout', 'error', 'notmodified', 'parseerror'];
|
||||
if(typeof failureFunc != 'function')
|
||||
failureFunc = function(){};
|
||||
|
||||
var jsonp = (url.substring(0, 1) !== '/');
|
||||
var success = false;
|
||||
$.ajax({
|
||||
url: url,
|
||||
data: data,
|
||||
dataType: jsonp? 'jsonp': 'json',
|
||||
type: type,
|
||||
cache: false,
|
||||
timeout: 299000
|
||||
}).done(function(data) {
|
||||
success = true;
|
||||
_dbg(JSON.stringify(data));
|
||||
successFunc(data);
|
||||
}).fail(function(jqXHR, textStatus) {
|
||||
_dbg(textStatus);
|
||||
failureFunc(textStatus);
|
||||
});
|
||||
|
||||
if (jsonp) {
|
||||
setTimeout(function() {
|
||||
var failfn = function() {
|
||||
if (!success) {
|
||||
var textStatus = 'error';
|
||||
_dbg(textStatus);
|
||||
failureFunc(textStatus);
|
||||
}
|
||||
};
|
||||
var noopfn = function() {
|
||||
var noopdone = false;
|
||||
var event = {type: 'noop', from: store.get('user'), sessionid: store.get('sessionid')};
|
||||
$.ajax({
|
||||
url: self.actions.noop,
|
||||
data: event,
|
||||
dataType: 'jsonp',
|
||||
type: type,
|
||||
cache: false,
|
||||
timeout: 299000
|
||||
}).done(function(data) {
|
||||
noopdone = true;
|
||||
if (!success) {
|
||||
setTimeout(noopfn, 3000);
|
||||
}
|
||||
}).fail(function(jqXHR, textStatus) {
|
||||
// since JSONP, never called
|
||||
});
|
||||
setTimeout(function() {
|
||||
if (!noopdone) {
|
||||
failfn();
|
||||
}
|
||||
}, 3000);
|
||||
};
|
||||
noopfn();
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
// This prevents Firefox from spinning indefinitely
|
||||
// while it waits for a response.
|
||||
/*
|
||||
if(url == 'jsonp' && $.browser.mozilla) {
|
||||
$.jsonp({
|
||||
'url': 'about:',
|
||||
timeout: 0
|
||||
});
|
||||
}
|
||||
*/
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// == Static functions and variables ==
|
||||
//
|
||||
@@ -1351,64 +1534,6 @@ AjaxIM.init = function(options, actions) {
|
||||
AjaxIM.client = new AjaxIM(options, actions);
|
||||
|
||||
return AjaxIM.client;
|
||||
}
|
||||
|
||||
|
||||
// === {{{AjaxIM.}}}**{{{request(url, data, successFunc, failureFunc)}}}** ===
|
||||
//
|
||||
// Wrapper around {{{$.jsonp}}}, the JSON-P library for jQuery, and {{{$.ajax}}},
|
||||
// jQuery's ajax library. Allows either function to be called, automatically,
|
||||
// depending on the request's URL array (see {{{AjaxIM.actions}}}).
|
||||
//
|
||||
// ==== Parameters ====
|
||||
// {{{url}}} is the URL of the request.
|
||||
// {{{data}}} are any arguments that go along with the request.
|
||||
// {{{success}}} is a callback function called when a request has completed
|
||||
// without issue.
|
||||
// {{{_ignore_}}} is simply to provide compatability with {{{$.post}}}.
|
||||
// {{{failure}}} is a callback function called when a request hasn't not
|
||||
// completed successfully.
|
||||
AjaxIM.post = function(url, data, successFunc, failureFunc) {
|
||||
AjaxIM.request(url, 'POST', data, successFunc, failureFunc);
|
||||
};
|
||||
|
||||
AjaxIM.get = function(url, data, successFunc, failureFunc) {
|
||||
AjaxIM.request(url, 'GET', data, successFunc, failureFunc);
|
||||
};
|
||||
|
||||
AjaxIM.request = function(url, type, data, successFunc, failureFunc) {
|
||||
var errorTypes = ['timeout', 'error', 'notmodified', 'parseerror'];
|
||||
if(typeof failureFunc != 'function')
|
||||
failureFunc = function(){};
|
||||
|
||||
$.ajax({
|
||||
url: url,
|
||||
data: data,
|
||||
dataType: 'json',
|
||||
type: type,
|
||||
cache: false,
|
||||
timeout: 299000,
|
||||
success: function(json, textStatus, xhr) {
|
||||
if('status' in xhr && xhr.status == '0') return;
|
||||
_dbg(json);
|
||||
successFunc(json);
|
||||
},
|
||||
complete: function(xhr, textStatus) {
|
||||
if(~errorTypes.indexOf(textStatus) || xhr.status == '0')
|
||||
failureFunc(textStatus);
|
||||
}
|
||||
});
|
||||
|
||||
// This prevents Firefox from spinning indefinitely
|
||||
// while it waits for a response.
|
||||
/*
|
||||
if(url == 'jsonp' && $.browser.mozilla) {
|
||||
$.jsonp({
|
||||
'url': 'about:',
|
||||
timeout: 0
|
||||
});
|
||||
}
|
||||
*/
|
||||
};
|
||||
|
||||
// === {{{AjaxIM.}}}**{{{incoming(data)}}}** ===
|
||||
@@ -1419,13 +1544,27 @@ AjaxIM.request = function(url, type, data, successFunc, failureFunc) {
|
||||
// //Note:// There are two {{{AjaxIM.incoming()}}} functions. This one is a
|
||||
// static function called outside of the initialized AjaxIM object; the other
|
||||
// is only called within the initalized AjaxIM object.
|
||||
AjaxIM.incoming = function(data) {
|
||||
AjaxIM.incoming = function(event) {
|
||||
if(!AjaxIM.client)
|
||||
return false;
|
||||
|
||||
if(data.length)
|
||||
AjaxIM.client._parseMessages(data);
|
||||
}
|
||||
if(event.length)
|
||||
$(AjaxIM.client).trigger(event.type, event);
|
||||
};
|
||||
|
||||
AjaxIM.uid = function(n){
|
||||
var chars='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', nn='';
|
||||
for(var c=0; c < n; c++){
|
||||
nn += chars.substr(0|Math.random() * chars.length, 1);
|
||||
}
|
||||
return nn;
|
||||
};
|
||||
|
||||
AjaxIM.onObj = function(obj, func) {
|
||||
return function(evt, event) {
|
||||
$.proxy(func, obj)(event);
|
||||
};
|
||||
};
|
||||
|
||||
// === {{{AjaxIM.}}}**{{{l10n}}}** ===
|
||||
//
|
||||
@@ -1457,7 +1596,7 @@ AjaxIM.l10n = {
|
||||
notConnected: 'You are currently not connected or the server is not available. ' +
|
||||
'Please ensure that you are signed in and try again.',
|
||||
notConnectedTip: 'You are currently not connected.',
|
||||
|
||||
|
||||
defaultAway: 'I\'m away.'
|
||||
};
|
||||
|
||||
|
||||
externo
+1
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
@@ -1,22 +0,0 @@
|
||||
/*!
|
||||
* Ajax IM
|
||||
* Ajax Instant Messeneger
|
||||
* http://ajaxim.com/
|
||||
*
|
||||
* Copyright 2010, Joshua Gross
|
||||
* Licensed under the MIT license.
|
||||
* [License URL]
|
||||
*
|
||||
* Includes:
|
||||
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
|
||||
* v2.1, Copyright 2002, Paul Johnston
|
||||
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
|
||||
* Distributed under the BSD License
|
||||
* See http://pajhome.org.uk/crypt/md5 for more info
|
||||
*
|
||||
* Date Format 1.2.3
|
||||
* http://blog.stevenlevithan.com/archives/date-time-format
|
||||
* Copyright 2009 Steven Levithan
|
||||
* MIT license
|
||||
*/
|
||||
(function($) {
|
||||
externo
+10308
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
externo
+4
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
externo
-6078
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
externo
-152
@@ -1,152 +0,0 @@
|
||||
/*!
|
||||
* jQuery JavaScript Library v1.4.1
|
||||
* http://jquery.com/
|
||||
*
|
||||
* Copyright 2010, John Resig
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* Includes Sizzle.js
|
||||
* http://sizzlejs.com/
|
||||
* Copyright 2010, The Dojo Foundation
|
||||
* Released under the MIT, BSD, and GPL Licenses.
|
||||
*
|
||||
* Date: Mon Jan 25 19:43:33 2010 -0500
|
||||
*/
|
||||
(function(z,v){function la(){if(!c.isReady){try{r.documentElement.doScroll("left")}catch(a){setTimeout(la,1);return}c.ready()}}function Ma(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,i){var j=a.length;if(typeof b==="object"){for(var n in b)X(a,n,b[n],f,e,d);return a}if(d!==v){f=!i&&f&&c.isFunction(d);for(n=0;n<j;n++)e(a[n],b,f?d.call(a[n],n,e(a[n],b)):d,i);return a}return j?
|
||||
e(a[0],b):null}function J(){return(new Date).getTime()}function Y(){return false}function Z(){return true}function ma(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function na(a){var b,d=[],f=[],e=arguments,i,j,n,o,m,s,x=c.extend({},c.data(this,"events").live);if(!(a.button&&a.type==="click")){for(o in x){j=x[o];if(j.live===a.type||j.altLive&&c.inArray(a.type,j.altLive)>-1){i=j.data;i.beforeFilter&&i.beforeFilter[a.type]&&!i.beforeFilter[a.type](a)||f.push(j.selector)}else delete x[o]}i=c(a.target).closest(f,
|
||||
a.currentTarget);m=0;for(s=i.length;m<s;m++)for(o in x){j=x[o];n=i[m].elem;f=null;if(i[m].selector===j.selector){if(j.live==="mouseenter"||j.live==="mouseleave")f=c(a.relatedTarget).closest(j.selector)[0];if(!f||f!==n)d.push({elem:n,fn:j})}}m=0;for(s=d.length;m<s;m++){i=d[m];a.currentTarget=i.elem;a.data=i.fn.data;if(i.fn.apply(i.elem,e)===false){b=false;break}}return b}}function oa(a,b){return"live."+(a?a+".":"")+b.replace(/\./g,"`").replace(/ /g,"&")}function pa(a){return!a||!a.parentNode||a.parentNode.nodeType===
|
||||
11}function qa(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var i in f)for(var j in f[i])c.event.add(this,i,f[i][j],f[i][j].data)}}})}function ra(a,b,d){var f,e,i;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&a[0].indexOf("<option")<0&&(c.support.checkClone||!sa.test(a[0]))){e=true;if(i=c.fragments[a[0]])if(i!==1)f=i}if(!f){b=b&&b[0]?b[0].ownerDocument||b[0]:r;f=b.createDocumentFragment();
|
||||
c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=i?f:1;return{fragment:f,cacheable:e}}function K(a,b){var d={};c.each(ta.concat.apply([],ta.slice(0,b)),function(){d[this]=a});return d}function ua(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Na=z.jQuery,Oa=z.$,r=z.document,S,Pa=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Qa=/^.[^:#\[\.,]*$/,Ra=/\S/,Sa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Ta=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,O=navigator.userAgent,
|
||||
va=false,P=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,Q=Array.prototype.slice,wa=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(typeof a==="string")if((d=Pa.exec(a))&&(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:r;if(a=Ta.exec(a))if(c.isPlainObject(b)){a=[r.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=ra([d[1]],
|
||||
[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}}else{if(b=r.getElementById(d[2])){if(b.id!==d[2])return S.find(a);this.length=1;this[0]=b}this.context=r;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=r;a=r.getElementsByTagName(a)}else return!b||b.jquery?(b||S).find(a):c(b).find(a);else if(c.isFunction(a))return S.ready(a);if(a.selector!==v){this.selector=a.selector;this.context=a.context}return c.isArray(a)?this.setArray(a):c.makeArray(a,
|
||||
this)},selector:"",jquery:"1.4.1",length:0,size:function(){return this.length},toArray:function(){return Q.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){a=c(a||null);a.prevObject=this;a.context=this.context;if(b==="find")a.selector=this.selector+(this.selector?" ":"")+d;else if(b)a.selector=this.selector+"."+b+"("+d+")";return a},setArray:function(a){this.length=0;ba.apply(this,a);return this},each:function(a,b){return c.each(this,
|
||||
a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(r,c);else P&&P.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(Q.apply(this,arguments),"slice",Q.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};
|
||||
c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,i,j,n;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(i in e){j=a[i];n=e[i];if(a!==n)if(f&&n&&(c.isPlainObject(n)||c.isArray(n))){j=j&&(c.isPlainObject(j)||c.isArray(j))?j:c.isArray(n)?[]:{};a[i]=c.extend(f,j,n)}else if(n!==v)a[i]=n}return a};c.extend({noConflict:function(a){z.$=
|
||||
Oa;if(a)z.jQuery=Na;return c},isReady:false,ready:function(){if(!c.isReady){if(!r.body)return setTimeout(c.ready,13);c.isReady=true;if(P){for(var a,b=0;a=P[b++];)a.call(r,c);P=null}c.fn.triggerHandler&&c(r).triggerHandler("ready")}},bindReady:function(){if(!va){va=true;if(r.readyState==="complete")return c.ready();if(r.addEventListener){r.addEventListener("DOMContentLoaded",L,false);z.addEventListener("load",c.ready,false)}else if(r.attachEvent){r.attachEvent("onreadystatechange",L);z.attachEvent("onload",
|
||||
c.ready);var a=false;try{a=z.frameElement==null}catch(b){}r.documentElement.doScroll&&a&&la()}}},isFunction:function(a){return $.call(a)==="[object Function]"},isArray:function(a){return $.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,"isPrototypeOf"))return false;var b;for(b in a);return b===v||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return false;
|
||||
return true},error:function(a){throw a;},parseJSON:function(a){if(typeof a!=="string"||!a)return null;if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return z.JSON&&z.JSON.parse?z.JSON.parse(a):(new Function("return "+a))();else c.error("Invalid JSON: "+a)},noop:function(){},globalEval:function(a){if(a&&Ra.test(a)){var b=r.getElementsByTagName("head")[0]||
|
||||
r.documentElement,d=r.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(r.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,i=a.length,j=i===v||c.isFunction(a);if(d)if(j)for(f in a){if(b.apply(a[f],d)===false)break}else for(;e<i;){if(b.apply(a[e++],d)===false)break}else if(j)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d=
|
||||
a[0];e<i&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Sa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=0,f=b.length;d<f;d++)if(b[d]===a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!==
|
||||
v;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,i=a.length;e<i;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,i=0,j=a.length;i<j;i++){e=b(a[i],i,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b==="string"){d=a;a=d[b];b=v}else if(b&&!c.isFunction(b)){d=b;b=v}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b},
|
||||
uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});O=c.uaMatch(O);if(O.browser){c.browser[O.browser]=true;c.browser.version=O.version}if(c.browser.webkit)c.browser.safari=true;if(wa)c.inArray=function(a,b){return wa.call(b,a)};S=c(r);if(r.addEventListener)L=function(){r.removeEventListener("DOMContentLoaded",
|
||||
L,false);c.ready()};else if(r.attachEvent)L=function(){if(r.readyState==="complete"){r.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var a=r.documentElement,b=r.createElement("script"),d=r.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML=" <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";var e=d.getElementsByTagName("*"),i=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!i)){c.support=
|
||||
{leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(i.getAttribute("style")),hrefNormalized:i.getAttribute("href")==="/a",opacity:/^0.55$/.test(i.style.opacity),cssFloat:!!i.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:r.createElement("select").appendChild(r.createElement("option")).selected,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};
|
||||
b.type="text/javascript";try{b.appendChild(r.createTextNode("window."+f+"=1;"))}catch(j){}a.insertBefore(b,a.firstChild);if(z[f]){c.support.scriptEval=true;delete z[f]}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function n(){c.support.noCloneEvent=false;d.detachEvent("onclick",n)});d.cloneNode(true).fireEvent("onclick")}d=r.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=r.createDocumentFragment();a.appendChild(d.firstChild);
|
||||
c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var n=r.createElement("div");n.style.width=n.style.paddingLeft="1px";r.body.appendChild(n);c.boxModel=c.support.boxModel=n.offsetWidth===2;r.body.removeChild(n).style.display="none"});a=function(n){var o=r.createElement("div");n="on"+n;var m=n in o;if(!m){o.setAttribute(n,"return;");m=typeof o[n]==="function"}return m};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=i=null}})();c.props=
|
||||
{"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ua=0,xa={},Va={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==z?xa:a;var f=a[G],e=c.cache;if(!b&&!f)return null;f||(f=++Ua);if(typeof b==="object"){a[G]=f;e=e[f]=c.extend(true,
|
||||
{},b)}else e=e[f]?e[f]:typeof d==="undefined"?Va:(e[f]={});if(d!==v){a[G]=f;e[b]=d}return typeof b==="string"?e[b]:e}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==z?xa:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{try{delete a[G]}catch(i){a.removeAttribute&&a.removeAttribute(G)}delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,
|
||||
a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===v){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===v&&this.length)f=c.data(this[0],a);return f===v&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);
|
||||
return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===v)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||
|
||||
a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var ya=/[\n\t]/g,ca=/\s+/,Wa=/\r/g,Xa=/href|src|style/,Ya=/(button|input)/i,Za=/(button|input|object|select|textarea)/i,$a=/^(a|area)$/i,za=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(o){var m=
|
||||
c(this);m.addClass(a.call(this,o,m.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className)for(var i=" "+e.className+" ",j=0,n=b.length;j<n;j++){if(i.indexOf(" "+b[j]+" ")<0)e.className+=" "+b[j]}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(o){var m=c(this);m.removeClass(a.call(this,o,m.attr("class")))});if(a&&typeof a==="string"||a===v)for(var b=(a||"").split(ca),
|
||||
d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var i=(" "+e.className+" ").replace(ya," "),j=0,n=b.length;j<n;j++)i=i.replace(" "+b[j]+" "," ");e.className=i.substring(1,i.length-1)}else e.className=""}return this},toggleClass:function(a,b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var i=c(this);i.toggleClass(a.call(this,e,i.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,i=0,j=c(this),n=b,o=
|
||||
a.split(ca);e=o[i++];){n=f?n:!j.hasClass(e);j[n?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(ya," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===v){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||
|
||||
{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var i=b?d:0;for(d=b?d+1:e.length;i<d;i++){var j=e[i];if(j.selected){a=c(j).val();if(b)return a;f.push(a)}}return f}if(za.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Wa,"")}return v}var n=c.isFunction(a);return this.each(function(o){var m=c(this),s=a;if(this.nodeType===1){if(n)s=a.call(this,o,m.val());
|
||||
if(typeof s==="number")s+="";if(c.isArray(s)&&za.test(this.type))this.checked=c.inArray(m.val(),s)>=0;else if(c.nodeName(this,"select")){var x=c.makeArray(s);c("option",this).each(function(){this.selected=c.inArray(c(this).val(),x)>=0});if(!x.length)this.selectedIndex=-1}else this.value=s}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return v;if(f&&b in c.attrFn)return c(a)[b](d);
|
||||
f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==v;b=f&&c.props[b]||b;if(a.nodeType===1){var i=Xa.test(b);if(b in a&&f&&!i){if(e){b==="type"&&Ya.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:Za.test(a.nodeName)||$a.test(a.nodeName)&&a.href?0:v;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=
|
||||
""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&i?a.getAttribute(b,2):a.getAttribute(b);return a===null?v:a}return c.style(a,b,d)}});var ab=function(a){return a.replace(/[^\w\s\.\|`]/g,function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==z&&!a.frameElement)a=z;if(!d.guid)d.guid=c.guid++;if(f!==v){d=c.proxy(d);d.data=f}var e=c.data(a,"events")||c.data(a,"events",{}),i=c.data(a,"handle"),j;if(!i){j=
|
||||
function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(j.elem,arguments):v};i=c.data(a,"handle",j)}if(i){i.elem=a;b=b.split(/\s+/);for(var n,o=0;n=b[o++];){var m=n.split(".");n=m.shift();if(o>1){d=c.proxy(d);if(f!==v)d.data=f}d.type=m.slice(0).sort().join(".");var s=e[n],x=this.special[n]||{};if(!s){s=e[n]={};if(!x.setup||x.setup.call(a,f,m,d)===false)if(a.addEventListener)a.addEventListener(n,i,false);else a.attachEvent&&a.attachEvent("on"+n,i)}if(x.add)if((m=x.add.call(a,
|
||||
d,f,m,s))&&c.isFunction(m)){m.guid=m.guid||d.guid;m.data=m.data||d.data;m.type=m.type||d.type;d=m}s[d.guid]=d;this.global[n]=true}a=null}}},global:{},remove:function(a,b,d){if(!(a.nodeType===3||a.nodeType===8)){var f=c.data(a,"events"),e,i,j;if(f){if(b===v||typeof b==="string"&&b.charAt(0)===".")for(i in f)this.remove(a,i+(b||""));else{if(b.type){d=b.handler;b=b.type}b=b.split(/\s+/);for(var n=0;i=b[n++];){var o=i.split(".");i=o.shift();var m=!o.length,s=c.map(o.slice(0).sort(),ab);s=new RegExp("(^|\\.)"+
|
||||
s.join("\\.(?:.*\\.)?")+"(\\.|$)");var x=this.special[i]||{};if(f[i]){if(d){j=f[i][d.guid];delete f[i][d.guid]}else for(var A in f[i])if(m||s.test(f[i][A].type))delete f[i][A];x.remove&&x.remove.call(a,o,j);for(e in f[i])break;if(!e){if(!x.teardown||x.teardown.call(a,o)===false)if(a.removeEventListener)a.removeEventListener(i,c.data(a,"handle"),false);else a.detachEvent&&a.detachEvent("on"+i,c.data(a,"handle"));e=null;delete f[i]}}}}for(e in f)break;if(!e){if(A=c.data(a,"handle"))A.elem=null;c.removeData(a,
|
||||
"events");c.removeData(a,"handle")}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();this.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return v;a.result=v;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,
|
||||
b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(i){}if(!a.isPropagationStopped()&&f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){d=a.target;var j;if(!(c.nodeName(d,"a")&&e==="click")&&!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()])){try{if(d[e]){if(j=d["on"+e])d["on"+e]=null;this.triggered=true;d[e]()}}catch(n){}if(j)d["on"+e]=j;this.triggered=false}}},handle:function(a){var b,
|
||||
d;a=arguments[0]=c.event.fix(a||z.event);a.currentTarget=this;d=a.type.split(".");a.type=d.shift();b=!d.length&&!a.exclusive;var f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)");d=(c.data(this,"events")||{})[a.type];for(var e in d){var i=d[e];if(b||f.test(i.type)){a.handler=i;a.data=i.data;i=i.apply(this,arguments);if(i!==v){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
|
||||
fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||r;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=r.documentElement;d=r.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
|
||||
d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==v)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a,b){c.extend(a,b||{});a.guid+=b.selector+b.live;b.liveProxy=a;c.event.add(this,b.live,na,b)},remove:function(a){if(a.length){var b=
|
||||
0,d=new RegExp("(^|\\.)"+a[0]+"(\\.|$)");c.each(c.data(this,"events").live||{},function(){d.test(this.type)&&b++});b<1&&c.event.remove(this,a[0],na)}},special:{}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=a;this.type=a.type}else this.type=a;this.timeStamp=J();this[G]=true};
|
||||
c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,isImmediatePropagationStopped:Y};var Aa=function(a){for(var b=
|
||||
a.relatedTarget;b&&b!==this;)try{b=b.parentNode}catch(d){break}if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}},Ba=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ba:Aa,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ba:Aa)}}});if(!c.support.submitBubbles)c.event.special.submit={setup:function(a,b,d){if(this.nodeName.toLowerCase()!==
|
||||
"form"){c.event.add(this,"click.specialSubmit."+d.guid,function(f){var e=f.target,i=e.type;if((i==="submit"||i==="image")&&c(e).closest("form").length)return ma("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit."+d.guid,function(f){var e=f.target,i=e.type;if((i==="text"||i==="password")&&c(e).closest("form").length&&f.keyCode===13)return ma("submit",this,arguments)})}else return false},remove:function(a,b){c.event.remove(this,"click.specialSubmit"+(b?"."+b.guid:""));c.event.remove(this,
|
||||
"keypress.specialSubmit"+(b?"."+b.guid:""))}};if(!c.support.changeBubbles){var da=/textarea|input|select/i;function Ca(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d}function ea(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Ca(d);if(a.type!=="focusout"||
|
||||
d.type!=="radio")c.data(d,"_change_data",e);if(!(f===v||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}}c.event.special.change={filters:{focusout:ea,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return ea.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return ea.call(this,a)},beforeactivate:function(a){a=
|
||||
a.target;a.nodeName.toLowerCase()==="input"&&a.type==="radio"&&c.data(a,"_change_data",Ca(a))}},setup:function(a,b,d){for(var f in T)c.event.add(this,f+".specialChange."+d.guid,T[f]);return da.test(this.nodeName)},remove:function(a,b){for(var d in T)c.event.remove(this,d+".specialChange"+(b?"."+b.guid:""),T[d]);return da.test(this.nodeName)}};var T=c.event.special.change.filters}r.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,
|
||||
f)}c.event.special[b]={setup:function(){this.addEventListener(a,d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var i in d)this[b](i,f,d[i],e);return this}if(c.isFunction(f)){e=f;f=v}var j=b==="one"?c.proxy(e,function(n){c(this).unbind(n,j);return e.apply(this,arguments)}):e;return d==="unload"&&b!=="one"?this.one(d,f,e):this.each(function(){c.event.add(this,d,j,f)})}});c.fn.extend({unbind:function(a,
|
||||
b){if(typeof a==="object"&&!a.preventDefault){for(var d in a)this.unbind(d,a[d]);return this}return this.each(function(){c.event.remove(this,a,b)})},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+
|
||||
a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e){var i,j=0;if(c.isFunction(f)){e=f;f=v}for(d=(d||"").split(/\s+/);(i=d[j++])!=null;){i=i==="focus"?"focusin":i==="blur"?"focusout":i==="hover"?d.push("mouseleave")&&"mouseenter":i;b==="live"?c(this.context).bind(oa(i,this.selector),{data:f,selector:this.selector,
|
||||
live:i},e):c(this.context).unbind(oa(i,this.selector),e?{guid:e.guid+this.selector+i}:null)}return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),function(a,b){c.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});z.attachEvent&&!z.addEventListener&&z.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});
|
||||
(function(){function a(g){for(var h="",k,l=0;g[l];l++){k=g[l];if(k.nodeType===3||k.nodeType===4)h+=k.nodeValue;else if(k.nodeType!==8)h+=a(k.childNodes)}return h}function b(g,h,k,l,q,p){q=0;for(var u=l.length;q<u;q++){var t=l[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===k){y=l[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=k;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}l[q]=y}}}function d(g,h,k,l,q,p){q=0;for(var u=l.length;q<u;q++){var t=l[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===
|
||||
k){y=l[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=k;t.sizset=q}if(typeof h!=="string"){if(t===h){y=true;break}}else if(o.filter(h,[t]).length>0){y=t;break}}t=t[g]}l[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e=0,i=Object.prototype.toString,j=false,n=true;[0,0].sort(function(){n=false;return 0});var o=function(g,h,k,l){k=k||[];var q=h=h||r;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||
|
||||
typeof g!=="string")return k;for(var p=[],u,t,y,R,H=true,M=w(h),I=g;(f.exec(""),u=f.exec(I))!==null;){I=u[3];p.push(u[1]);if(u[2]){R=u[3];break}}if(p.length>1&&s.exec(g))if(p.length===2&&m.relative[p[0]])t=fa(p[0]+p[1],h);else for(t=m.relative[p[0]]?[h]:o(p.shift(),h);p.length;){g=p.shift();if(m.relative[g])g+=p.shift();t=fa(g,t)}else{if(!l&&p.length>1&&h.nodeType===9&&!M&&m.match.ID.test(p[0])&&!m.match.ID.test(p[p.length-1])){u=o.find(p.shift(),h,M);h=u.expr?o.filter(u.expr,u.set)[0]:u.set[0]}if(h){u=
|
||||
l?{expr:p.pop(),set:A(l)}:o.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=u.expr?o.filter(u.expr,u.set):u.set;if(p.length>0)y=A(t);else H=false;for(;p.length;){var D=p.pop();u=D;if(m.relative[D])u=p.pop();else D="";if(u==null)u=h;m.relative[D](y,u,M)}}else y=[]}y||(y=t);y||o.error(D||g);if(i.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))k.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&
|
||||
y[g].nodeType===1&&k.push(t[g]);else k.push.apply(k,y);else A(y,k);if(R){o(R,q,k,l);o.uniqueSort(k)}return k};o.uniqueSort=function(g){if(C){j=n;g.sort(C);if(j)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};o.matches=function(g,h){return o(g,null,null,h)};o.find=function(g,h,k){var l,q;if(!g)return[];for(var p=0,u=m.order.length;p<u;p++){var t=m.order[p];if(q=m.leftMatch[t].exec(g)){var y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");l=m.find[t](q,
|
||||
h,k);if(l!=null){g=g.replace(m.match[t],"");break}}}}l||(l=h.getElementsByTagName("*"));return{set:l,expr:g}};o.filter=function(g,h,k,l){for(var q=g,p=[],u=h,t,y,R=h&&h[0]&&w(h[0]);g&&h.length;){for(var H in m.filter)if((t=m.leftMatch[H].exec(g))!=null&&t[2]){var M=m.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-1)!=="\\"){if(u===p)p=[];if(m.preFilter[H])if(t=m.preFilter[H](t,u,k,p,l,R)){if(t===true)continue}else y=I=true;if(t)for(var U=0;(D=u[U])!=null;U++)if(D){I=M(D,t,U,u);var Da=
|
||||
l^!!I;if(k&&I!=null)if(Da)y=true;else u[U]=false;else if(Da){p.push(D);y=true}}if(I!==v){k||(u=p);g=g.replace(m.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)o.error(g);else break;q=g}return u};o.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var m=o.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
|
||||
TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},relative:{"+":function(g,h){var k=typeof h==="string",l=k&&!/\W/.test(h);k=k&&!l;if(l)h=h.toLowerCase();l=0;for(var q=g.length,
|
||||
p;l<q;l++)if(p=g[l]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[l]=k||p&&p.nodeName.toLowerCase()===h?p||false:p===h}k&&o.filter(h,g,true)},">":function(g,h){var k=typeof h==="string";if(k&&!/\W/.test(h)){h=h.toLowerCase();for(var l=0,q=g.length;l<q;l++){var p=g[l];if(p){k=p.parentNode;g[l]=k.nodeName.toLowerCase()===h?k:false}}}else{l=0;for(q=g.length;l<q;l++)if(p=g[l])g[l]=k?p.parentNode:p.parentNode===h;k&&o.filter(h,g,true)}},"":function(g,h,k){var l=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=
|
||||
h=h.toLowerCase();q=b}q("parentNode",h,l,g,p,k)},"~":function(g,h,k){var l=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("previousSibling",h,l,g,p,k)}},find:{ID:function(g,h,k){if(typeof h.getElementById!=="undefined"&&!k)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var k=[];h=h.getElementsByName(g[1]);for(var l=0,q=h.length;l<q;l++)h[l].getAttribute("name")===g[1]&&k.push(h[l]);return k.length===0?null:k}},
|
||||
TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,k,l,q,p){g=" "+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var u;(u=h[p])!=null;p++)if(u)if(q^(u.className&&(" "+u.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))k||l.push(u);else if(k)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&
|
||||
"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,k,l,q,p){h=g[1].replace(/\\/g,"");if(!p&&m.attrMap[h])g[1]=m.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,k,l,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=o(g[3],null,null,h);else{g=o.filter(g[3],h,k,true^q);k||l.push.apply(l,g);return false}else if(m.match.POS.test(g[0])||m.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);
|
||||
return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,k){return!!o(k[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===
|
||||
g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},setFilters:{first:function(g,h){return h===0},last:function(g,h,k,l){return h===l.length-1},even:function(g,h){return h%2===
|
||||
0},odd:function(g,h){return h%2===1},lt:function(g,h,k){return h<k[3]-0},gt:function(g,h,k){return h>k[3]-0},nth:function(g,h,k){return k[3]-0===h},eq:function(g,h,k){return k[3]-0===h}},filter:{PSEUDO:function(g,h,k,l){var q=h[1],p=m.filters[q];if(p)return p(g,k,h,l);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h=h[3];k=0;for(l=h.length;k<l;k++)if(h[k]===g)return false;return true}else o.error("Syntax error, unrecognized expression: "+
|
||||
q)},CHILD:function(g,h){var k=h[1],l=g;switch(k){case "only":case "first":for(;l=l.previousSibling;)if(l.nodeType===1)return false;if(k==="first")return true;l=g;case "last":for(;l=l.nextSibling;)if(l.nodeType===1)return false;return true;case "nth":k=h[2];var q=h[3];if(k===1&&q===0)return true;h=h[0];var p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var u=0;for(l=p.firstChild;l;l=l.nextSibling)if(l.nodeType===1)l.nodeIndex=++u;p.sizcache=h}g=g.nodeIndex-q;return k===0?g===0:g%k===0&&g/k>=
|
||||
0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var k=h[1];g=m.attrHandle[k]?m.attrHandle[k](g):g[k]!=null?g[k]:g.getAttribute(k);k=g+"";var l=h[2];h=h[4];return g==null?l==="!=":l==="="?k===h:l==="*="?k.indexOf(h)>=0:l==="~="?(" "+k+" ").indexOf(h)>=0:!h?k&&g!==false:l==="!="?k!==h:l==="^="?
|
||||
k.indexOf(h)===0:l==="$="?k.substr(k.length-h.length)===h:l==="|="?k===h||k.substr(0,h.length+1)===h+"-":false},POS:function(g,h,k,l){var q=m.setFilters[h[2]];if(q)return q(g,k,h,l)}}},s=m.match.POS;for(var x in m.match){m.match[x]=new RegExp(m.match[x].source+/(?![^\[]*\])(?![^\(]*\))/.source);m.leftMatch[x]=new RegExp(/(^(?:.|\r|\n)*?)/.source+m.match[x].source.replace(/\\(\d+)/g,function(g,h){return"\\"+(h-0+1)}))}var A=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};
|
||||
try{Array.prototype.slice.call(r.documentElement.childNodes,0)}catch(B){A=function(g,h){h=h||[];if(i.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var k=0,l=g.length;k<l;k++)h.push(g[k]);else for(k=0;g[k];k++)h.push(g[k]);return h}}var C;if(r.documentElement.compareDocumentPosition)C=function(g,h){if(!g.compareDocumentPosition||!h.compareDocumentPosition){if(g==h)j=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===
|
||||
h?0:1;if(g===0)j=true;return g};else if("sourceIndex"in r.documentElement)C=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)j=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)j=true;return g};else if(r.createRange)C=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)j=true;return g.ownerDocument?-1:1}var k=g.ownerDocument.createRange(),l=h.ownerDocument.createRange();k.setStart(g,0);k.setEnd(g,0);l.setStart(h,0);l.setEnd(h,0);g=k.compareBoundaryPoints(Range.START_TO_END,
|
||||
l);if(g===0)j=true;return g};(function(){var g=r.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var k=r.documentElement;k.insertBefore(g,k.firstChild);if(r.getElementById(h)){m.find.ID=function(l,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(l[1]))?q.id===l[1]||typeof q.getAttributeNode!=="undefined"&&q.getAttributeNode("id").nodeValue===l[1]?[q]:v:[]};m.filter.ID=function(l,q){var p=typeof l.getAttributeNode!=="undefined"&&l.getAttributeNode("id");
|
||||
return l.nodeType===1&&p&&p.nodeValue===q}}k.removeChild(g);k=g=null})();(function(){var g=r.createElement("div");g.appendChild(r.createComment(""));if(g.getElementsByTagName("*").length>0)m.find.TAG=function(h,k){k=k.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var l=0;k[l];l++)k[l].nodeType===1&&h.push(k[l]);k=h}return k};g.innerHTML="<a href='#'></a>";if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")m.attrHandle.href=function(h){return h.getAttribute("href",
|
||||
2)};g=null})();r.querySelectorAll&&function(){var g=o,h=r.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){o=function(l,q,p,u){q=q||r;if(!u&&q.nodeType===9&&!w(q))try{return A(q.querySelectorAll(l),p)}catch(t){}return g(l,q,p,u)};for(var k in g)o[k]=g[k];h=null}}();(function(){var g=r.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===
|
||||
0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){m.order.splice(1,0,"CLASS");m.find.CLASS=function(h,k,l){if(typeof k.getElementsByClassName!=="undefined"&&!l)return k.getElementsByClassName(h[1])};g=null}}})();var E=r.compareDocumentPosition?function(g,h){return g.compareDocumentPosition(h)&16}:function(g,h){return g!==h&&(g.contains?g.contains(h):true)},w=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},fa=function(g,h){var k=[],
|
||||
l="",q;for(h=h.nodeType?[h]:h;q=m.match.PSEUDO.exec(g);){l+=q[0];g=g.replace(m.match.PSEUDO,"")}g=m.relative[g]?g+"*":g;q=0;for(var p=h.length;q<p;q++)o(g,h[q],k);return o.filter(l,k)};c.find=o;c.expr=o.selectors;c.expr[":"]=c.expr.filters;c.unique=o.uniqueSort;c.getText=a;c.isXMLDoc=w;c.contains=E})();var bb=/Until$/,cb=/^(?:parents|prevUntil|prevAll)/,db=/,/;Q=Array.prototype.slice;var Ea=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,i){return!!b.call(e,i,e)===d});else if(b.nodeType)return c.grep(a,
|
||||
function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Qa.test(b))return c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;c.find(a,this[f],b);if(f>0)for(var i=d;i<b.length;i++)for(var j=0;j<d;j++)if(b[j]===b[i]){b.splice(i--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=
|
||||
0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Ea(this,a,false),"not",a)},filter:function(a){return this.pushStack(Ea(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,i={},j;if(f&&a.length){e=0;for(var n=a.length;e<n;e++){j=a[e];i[j]||(i[j]=c.expr.match.POS.test(j)?c(j,b||this.context):j)}for(;f&&f.ownerDocument&&f!==b;){for(j in i){e=i[j];if(e.jquery?e.index(f)>
|
||||
-1:c(f).is(e)){d.push({selector:j,elem:f});delete i[j]}}f=f.parentNode}}return d}var o=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(m,s){for(;s&&s.ownerDocument&&s!==b;){if(o?o.index(s)>-1:c(s).is(a))return s;s=s.parentNode}return null})},index:function(a){if(!a||typeof a==="string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),
|
||||
a);return this.pushStack(pa(a[0])||pa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},
|
||||
nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);bb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):
|
||||
e;if((this.length>1||db.test(f))&&cb.test(a))e=e.reverse();return this.pushStack(e,a,Q.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===v||a.nodeType!==1||!c(a).is(d));){a.nodeType===1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==
|
||||
b&&d.push(a);return d}});var Fa=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ga=/(<([\w:]+)[^>]*?)\/>/g,eb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,Ha=/<([\w:]+)/,fb=/<tbody/i,gb=/<|&\w+;/,sa=/checked\s*(?:[^=]|=\s*.checked.)/i,Ia=function(a,b,d){return eb.test(d)?a:b+"></"+d+">"},F={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],
|
||||
col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==v)return this.empty().append((this[0]&&this[0].ownerDocument||r).createTextNode(a));return c.getText(this)},
|
||||
wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?
|
||||
d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,
|
||||
false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&
|
||||
!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Fa,"").replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){qa(this,b);qa(this.find("*"),b.find("*"))}return b},html:function(a){if(a===v)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Fa,""):null;else if(typeof a==="string"&&!/<script/i.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(Ha.exec(a)||
|
||||
["",""])[1].toLowerCase()]){a=a.replace(Ga,Ia);try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else c.isFunction(a)?this.each(function(e){var i=c(this),j=i.html();i.empty().append(function(){return a.call(this,e,j)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=c(this),f=d.html();d.replaceWith(a.call(this,
|
||||
b,f))});else a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(s){return c.nodeName(s,"table")?s.getElementsByTagName("tbody")[0]||s.appendChild(s.ownerDocument.createElement("tbody")):s}var e,i,j=a[0],n=[];if(!c.support.checkClone&&arguments.length===3&&typeof j===
|
||||
"string"&&sa.test(j))return this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(j))return this.each(function(s){var x=c(this);a[0]=j.call(this,s,b?x.html():v);x.domManip(a,b,d)});if(this[0]){e=a[0]&&a[0].parentNode&&a[0].parentNode.nodeType===11?{fragment:a[0].parentNode}:ra(a,this,n);if(i=e.fragment.firstChild){b=b&&c.nodeName(i,"tr");for(var o=0,m=this.length;o<m;o++)d.call(b?f(this[o],i):this[o],e.cacheable||this.length>1||o>0?e.fragment.cloneNode(true):e.fragment)}n&&c.each(n,
|
||||
Ma)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);for(var e=0,i=d.length;e<i;e++){var j=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),j);f=f.concat(j)}return this.pushStack(f,a,d.selector)}});c.each({remove:function(a,b){if(!a||c.filter(a,[this]).length){if(!b&&this.nodeType===1){c.cleanData(this.getElementsByTagName("*"));c.cleanData([this])}this.parentNode&&
|
||||
this.parentNode.removeChild(this)}},empty:function(){for(this.nodeType===1&&c.cleanData(this.getElementsByTagName("*"));this.firstChild;)this.removeChild(this.firstChild)}},function(a,b){c.fn[a]=function(){return this.each(b,arguments)}});c.extend({clean:function(a,b,d,f){b=b||r;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||r;var e=[];c.each(a,function(i,j){if(typeof j==="number")j+="";if(j){if(typeof j==="string"&&!gb.test(j))j=b.createTextNode(j);else if(typeof j===
|
||||
"string"){j=j.replace(Ga,Ia);var n=(Ha.exec(j)||["",""])[1].toLowerCase(),o=F[n]||F._default,m=o[0];i=b.createElement("div");for(i.innerHTML=o[1]+j+o[2];m--;)i=i.lastChild;if(!c.support.tbody){m=fb.test(j);n=n==="table"&&!m?i.firstChild&&i.firstChild.childNodes:o[1]==="<table>"&&!m?i.childNodes:[];for(o=n.length-1;o>=0;--o)c.nodeName(n[o],"tbody")&&!n[o].childNodes.length&&n[o].parentNode.removeChild(n[o])}!c.support.leadingWhitespace&&V.test(j)&&i.insertBefore(b.createTextNode(V.exec(j)[0]),i.firstChild);
|
||||
j=c.makeArray(i.childNodes)}if(j.nodeType)e.push(j);else e=c.merge(e,j)}});if(d)for(a=0;e[a];a++)if(f&&c.nodeName(e[a],"script")&&(!e[a].type||e[a].type.toLowerCase()==="text/javascript"))f.push(e[a].parentNode?e[a].parentNode.removeChild(e[a]):e[a]);else{e[a].nodeType===1&&e.splice.apply(e,[a+1,0].concat(c.makeArray(e[a].getElementsByTagName("script"))));d.appendChild(e[a])}return e},cleanData:function(a){for(var b=0,d;(d=a[b])!=null;b++){c.event.remove(d);c.removeData(d)}}});var hb=/z-?index|font-?weight|opacity|zoom|line-?height/i,
|
||||
Ja=/alpha\([^)]*\)/,Ka=/opacity=([^)]*)/,ga=/float/i,ha=/-([a-z])/ig,ib=/([A-Z])/g,jb=/^-?\d+(?:px)?$/i,kb=/^-?\d/,lb={position:"absolute",visibility:"hidden",display:"block"},mb=["Left","Right"],nb=["Top","Bottom"],ob=r.defaultView&&r.defaultView.getComputedStyle,La=c.support.cssFloat?"cssFloat":"styleFloat",ia=function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===v)return c.curCSS(d,f);if(typeof e==="number"&&!hb.test(f))e+="px";c.style(d,f,e)})};
|
||||
c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return v;if((b==="width"||b==="height")&&parseFloat(d)<0)d=v;var f=a.style||a,e=d!==v;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=Ja.test(a)?a.replace(Ja,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Ka.exec(f.filter)[1])/100+"":""}if(ga.test(b))b=La;b=b.replace(ha,ia);if(e)f[b]=d;return f[b]},css:function(a,
|
||||
b,d,f){if(b==="width"||b==="height"){var e,i=b==="width"?mb:nb;function j(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(i,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,"border"+this+"Width",true))||0})}a.offsetWidth!==0?j():c.swap(a,lb,j);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&
|
||||
a.currentStyle){f=Ka.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ga.test(b))b=La;if(!d&&e&&e[b])f=e[b];else if(ob){if(ga.test(b))b="float";b=b.replace(ib,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ha,ia);f=a.currentStyle[b]||a.currentStyle[d];if(!jb.test(f)&&kb.test(f)){b=e.left;var i=a.runtimeStyle.left;a.runtimeStyle.left=
|
||||
a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=i}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var pb=
|
||||
J(),qb=/<script(.|\s)*?\/script>/gi,rb=/select|textarea/i,sb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ja=/\?/,tb=/(\?|&)_=.*?(&|$)/,ub=/^(\w+:)?\/\/([^\/?#]+)/,vb=/%20/g;c.fn.extend({_load:c.fn.load,load:function(a,b,d){if(typeof a!=="string")return this._load(a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=
|
||||
c.param(b,c.ajaxSettings.traditional);f="POST"}var i=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(j,n){if(n==="success"||n==="notmodified")i.html(e?c("<div />").append(j.responseText.replace(qb,"")).find(e):j.responseText);d&&i.each(d,[j.responseText,n,j])}});return this},serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&
|
||||
(this.checked||rb.test(this.nodeName)||sb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,
|
||||
b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:z.XMLHttpRequest&&(z.location.protocol!=="file:"||!z.ActiveXObject)?function(){return new z.XMLHttpRequest}:
|
||||
function(){try{return new z.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&e.success.call(o,n,j,w);e.global&&f("ajaxSuccess",[w,e])}function d(){e.complete&&e.complete.call(o,w,j);e.global&&f("ajaxComplete",[w,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}
|
||||
function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),i,j,n,o=a&&a.context||e,m=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(m==="GET")N.test(e.url)||(e.url+=(ja.test(e.url)?"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||
|
||||
N.test(e.url))){i=e.jsonpCallback||"jsonp"+pb++;if(e.data)e.data=(e.data+"").replace(N,"="+i+"$1");e.url=e.url.replace(N,"="+i+"$1");e.dataType="script";z[i]=z[i]||function(q){n=q;b();d();z[i]=v;try{delete z[i]}catch(p){}A&&A.removeChild(B)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===false&&m==="GET"){var s=J(),x=e.url.replace(tb,"$1_="+s+"$2");e.url=x+(x===e.url?(ja.test(e.url)?"&":"?")+"_="+s:"")}if(e.data&&m==="GET")e.url+=(ja.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&
|
||||
c.event.trigger("ajaxStart");s=(s=ub.exec(e.url))&&(s[1]&&s[1]!==location.protocol||s[2]!==location.host);if(e.dataType==="script"&&m==="GET"&&s){var A=r.getElementsByTagName("head")[0]||r.documentElement,B=r.createElement("script");B.src=e.url;if(e.scriptCharset)B.charset=e.scriptCharset;if(!i){var C=false;B.onload=B.onreadystatechange=function(){if(!C&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){C=true;b();d();B.onload=B.onreadystatechange=null;A&&B.parentNode&&
|
||||
A.removeChild(B)}}}A.insertBefore(B,A.firstChild);return v}var E=false,w=e.xhr();if(w){e.username?w.open(m,e.url,e.async,e.username,e.password):w.open(m,e.url,e.async);try{if(e.data||a&&a.contentType)w.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&w.setRequestHeader("If-Modified-Since",c.lastModified[e.url]);c.etag[e.url]&&w.setRequestHeader("If-None-Match",c.etag[e.url])}s||w.setRequestHeader("X-Requested-With","XMLHttpRequest");w.setRequestHeader("Accept",
|
||||
e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(fa){}if(e.beforeSend&&e.beforeSend.call(o,w,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");w.abort();return false}e.global&&f("ajaxSend",[w,e]);var g=w.onreadystatechange=function(q){if(!w||w.readyState===0||q==="abort"){E||d();E=true;if(w)w.onreadystatechange=c.noop}else if(!E&&w&&(w.readyState===4||q==="timeout")){E=true;w.onreadystatechange=c.noop;j=q==="timeout"?"timeout":!c.httpSuccess(w)?
|
||||
"error":e.ifModified&&c.httpNotModified(w,e.url)?"notmodified":"success";var p;if(j==="success")try{n=c.httpData(w,e.dataType,e)}catch(u){j="parsererror";p=u}if(j==="success"||j==="notmodified")i||b();else c.handleError(e,w,j,p);d();q==="timeout"&&w.abort();if(e.async)w=null}};try{var h=w.abort;w.abort=function(){w&&h.call(w);g("abort")}}catch(k){}e.async&&e.timeout>0&&setTimeout(function(){w&&!E&&g("timeout")},e.timeout);try{w.send(m==="POST"||m==="PUT"||m==="DELETE"?e.data:null)}catch(l){c.handleError(e,
|
||||
w,null,l);d()}e.async||g();return w}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=
|
||||
f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b==="json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(j,n){if(c.isArray(n))c.each(n,
|
||||
function(o,m){b?f(j,m):d(j+"["+(typeof m==="object"||c.isArray(m)?o:"")+"]",m)});else!b&&n!=null&&typeof n==="object"?c.each(n,function(o,m){d(j+"["+o+"]",m)}):f(j,n)}function f(j,n){n=c.isFunction(n)?n():n;e[e.length]=encodeURIComponent(j)+"="+encodeURIComponent(n)}var e=[];if(b===v)b=c.ajaxSettings.traditional;if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var i in a)d(i,a[i]);return e.join("&").replace(vb,"+")}});var ka={},wb=/toggle|show|hide/,xb=/^([+-]=)?([\d+-.]+)(.*)$/,
|
||||
W,ta=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(ka[d])f=ka[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();
|
||||
ka[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a||a===0)return this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&&
|
||||
c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var i=c.extend({},e),j,n=this.nodeType===1&&c(this).is(":hidden"),
|
||||
o=this;for(j in a){var m=j.replace(ha,ia);if(j!==m){a[m]=a[j];delete a[j];j=m}if(a[j]==="hide"&&n||a[j]==="show"&&!n)return i.complete.call(this);if((j==="height"||j==="width")&&this.style){i.display=c.css(this,"display");i.overflow=this.style.overflow}if(c.isArray(a[j])){(i.specialEasing=i.specialEasing||{})[j]=a[j][1];a[j]=a[j][0]}}if(i.overflow!=null)this.style.overflow="hidden";i.curAnim=c.extend({},a);c.each(a,function(s,x){var A=new c.fx(o,i,s);if(wb.test(x))A[x==="toggle"?n?"show":"hide":x](a);
|
||||
else{var B=xb.exec(x),C=A.cur(true)||0;if(B){x=parseFloat(B[2]);var E=B[3]||"px";if(E!=="px"){o.style[s]=(x||1)+E;C=(x||1)/A.cur(true)*C;o.style[s]=C+E}if(B[1])x=(B[1]==="-="?-1:1)*x+C;A.custom(C,x,E)}else A.custom(C,x,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",
|
||||
1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration==="number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,
|
||||
b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==
|
||||
null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(i){return e.step(i)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop===
|
||||
"width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=
|
||||
this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=
|
||||
c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=
|
||||
null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in r.documentElement?function(a){var b=this[0];if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(),
|
||||
f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=this[0];if(a)return this.each(function(s){c.offset.setOffset(this,a,s)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f=
|
||||
b,e=b.ownerDocument,i,j=e.documentElement,n=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var o=b.offsetTop,m=b.offsetLeft;(b=b.parentNode)&&b!==n&&b!==j;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;i=e?e.getComputedStyle(b,null):b.currentStyle;o-=b.scrollTop;m-=b.scrollLeft;if(b===d){o+=b.offsetTop;m+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){o+=parseFloat(i.borderTopWidth)||
|
||||
0;m+=parseFloat(i.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&i.overflow!=="visible"){o+=parseFloat(i.borderTopWidth)||0;m+=parseFloat(i.borderLeftWidth)||0}f=i}if(f.position==="relative"||f.position==="static"){o+=n.offsetTop;m+=n.offsetLeft}if(c.offset.supportsFixedPosition&&f.position==="fixed"){o+=Math.max(j.scrollTop,n.scrollTop);m+=Math.max(j.scrollLeft,n.scrollLeft)}return{top:o,left:m}};c.offset={initialize:function(){var a=r.body,b=r.createElement("div"),
|
||||
d,f,e,i=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";a.insertBefore(b,a.firstChild);
|
||||
d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i;a.removeChild(b);c.offset.initialize=c.noop},
|
||||
bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),i=parseInt(c.curCSS(a,"top",true),10)||0,j=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,d,e);d={top:b.top-e.top+i,left:b.left-
|
||||
e.left+j};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=
|
||||
this.offsetParent||r.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],i;if(!e)return null;if(f!==v)return this.each(function(){if(i=ua(this))i.scrollTo(!a?f:c(i).scrollLeft(),a?f:c(i).scrollTop());else this[d]=f});else return(i=ua(e))?"pageXOffset"in i?i[a?"pageYOffset":"pageXOffset"]:c.support.boxModel&&i.document.documentElement[d]||i.document.body[d]:e[d]}});
|
||||
c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(i){var j=c(this);j[d](f.call(this,i,j[d]()))});return"scrollTo"in e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||
|
||||
e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===v?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});z.jQuery=z.$=c})(window);
|
||||
@@ -1,2 +0,0 @@
|
||||
|
||||
})(jQuery || $);
|
||||
@@ -3,6 +3,7 @@ var store = (function(){
|
||||
var api = {},
|
||||
win = window,
|
||||
doc = win.document,
|
||||
sessionStorageName = 'sessionStorage',
|
||||
localStorageName = 'localStorage',
|
||||
globalStorageName = 'globalStorage',
|
||||
storage
|
||||
@@ -20,7 +21,14 @@ var store = (function(){
|
||||
return JSON.parse(value)
|
||||
}
|
||||
|
||||
if (localStorageName in win && win[localStorageName]) {
|
||||
if (sessionStorageName in win && win[sessionStorageName]) {
|
||||
storage = win[sessionStorageName]
|
||||
api.set = function(key, val) { storage[key] = serialize(val) }
|
||||
api.get = function(key) { return deserialize(storage[key]) }
|
||||
api.remove = function(key) { delete storage[key] }
|
||||
api.clear = function() { storage.clear() }
|
||||
|
||||
} else if (localStorageName in win && win[localStorageName]) {
|
||||
storage = win[localStorageName]
|
||||
api.set = function(key, val) { storage[key] = serialize(val) }
|
||||
api.get = function(key) { return deserialize(storage[key]) }
|
||||
|
||||
@@ -269,6 +269,7 @@ ul#imjs-bar {
|
||||
font-size: 9px;
|
||||
font-weight: 700;
|
||||
background-repeat: no-repeat;
|
||||
display: none;
|
||||
}
|
||||
|
||||
ul#imjs-bar li#imjs-scroll-left {
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "AjaxIM",
|
||||
"description": "instant messaging framework",
|
||||
"author": "ajaximrpg <ajaximrpg@svexpertise.com>",
|
||||
"version": "4.0.0",
|
||||
"dependencies": {
|
||||
"express": ">= 4.0.0",
|
||||
"connect": ">= 2.14.0",
|
||||
"method-override": ">= 1.0.0",
|
||||
"body-parser": ">= 1.0.0",
|
||||
"express-error-handler": ">= 0.5.0",
|
||||
"morgan": ">= 1.0.0",
|
||||
"cookie": ">= 0.1.0",
|
||||
"jade": ">= 1.3.0",
|
||||
"socket.io": ">= 1.0.6"
|
||||
}
|
||||
}
|
||||
+37
-83
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env node
|
||||
var sys = require('sys'),
|
||||
var sys = require('util'),
|
||||
express = require('express'),
|
||||
packages = require('./libs/packages'),
|
||||
o_ = require('./libs/utils');
|
||||
@@ -7,107 +7,59 @@ var sys = require('sys'),
|
||||
o_.merge(global, require('./settings'));
|
||||
try { o_.merge(global, require('./settings.local')); } catch(e) {}
|
||||
|
||||
try {
|
||||
var daemon = require('./libs/daemon/daemon'),
|
||||
start = function() {
|
||||
daemon.init({
|
||||
lock: PID_FILE,
|
||||
stdin: '/dev/null',
|
||||
stdout: LOG_FILE,
|
||||
stderr: LOG_FILE,
|
||||
umask: 0,
|
||||
chroot: null,
|
||||
chdir: '.'
|
||||
});
|
||||
},
|
||||
stop = function() {
|
||||
process.kill(parseInt(require('fs').readFileSync(PID_FILE)));
|
||||
};
|
||||
var app = express();
|
||||
//app.set('env', 'development');
|
||||
app.use( require('request-param')() )
|
||||
|
||||
switch(process.argv[2]) {
|
||||
case 'stop':
|
||||
stop();
|
||||
process.exit(0);
|
||||
break;
|
||||
|
||||
case 'start':
|
||||
if(process.argv[3])
|
||||
process.env.EXPRESS_ENV = process.argv[3];
|
||||
start();
|
||||
break;
|
||||
|
||||
case 'restart':
|
||||
stop();
|
||||
start();
|
||||
process.exit(0);
|
||||
break;
|
||||
|
||||
case 'help':
|
||||
sys.puts('Usage: node app.js [start|stop|restart]');
|
||||
process.exit(0);
|
||||
break;
|
||||
}
|
||||
} catch(e) {
|
||||
sys.puts('Daemon library not found! Please compile ' +
|
||||
'./libs/daemon/daemon.node if you would like to use it.');
|
||||
}
|
||||
|
||||
var app = express.createServer(
|
||||
express.methodOverride(),
|
||||
express.cookieDecoder(),
|
||||
express.bodyDecoder(),
|
||||
require('./middleware/im')({
|
||||
maxAge: 15 * 60 * 1000,
|
||||
reapInterval: 60 * 1000,
|
||||
authentication: require('./libs/authentication/' + AUTH_LIBRARY)
|
||||
})
|
||||
);
|
||||
app.use(require('method-override')());
|
||||
app.use(require('cookie-parser')());;
|
||||
//app.use(require('body-parser')());;
|
||||
app.use(require('body-parser').urlencoded({extended: true}));;
|
||||
app.use(require('body-parser').json());;
|
||||
app.use(require('./middleware/im')({
|
||||
maxAge: 15 * 60 * 1000,
|
||||
reapInterval: 60 * 1000,
|
||||
authentication: require('./libs/authentication/' + AUTH_LIBRARY)
|
||||
}));
|
||||
|
||||
app.set('root', __dirname);
|
||||
|
||||
app.configure('development', function() {
|
||||
app.set('view engine', 'jade');
|
||||
if ('development' == app.get('env')) {
|
||||
app.set('views', __dirname + '/dev/views');
|
||||
|
||||
app.stack.unshift({
|
||||
route: '/dev',
|
||||
handle: function(req, res, next) {
|
||||
req.dev = true;
|
||||
next();
|
||||
}
|
||||
});
|
||||
|
||||
app.use(express.logger());
|
||||
app.use('/dev', express.router(require('./dev/app')));
|
||||
app.use(express.staticProvider(
|
||||
app.set('view engine', 'jade');
|
||||
|
||||
app.use(require("morgan")("dev"));
|
||||
require('./dev/app')('/dev', app);
|
||||
app.use(express.static(
|
||||
require('path').join(__dirname, '../client')));
|
||||
app.use(express.errorHandler({dumpExceptions: true, showStack: true}));
|
||||
});
|
||||
app.use(require('express-error-handler')({dumpExceptions: true, showStack: true}));
|
||||
}
|
||||
|
||||
app.listen(APP_PORT, APP_HOST);
|
||||
|
||||
// Listener endpoint; handled in middleware
|
||||
app.get('/listen', function(){});
|
||||
app.get('/app/listen', function(){});
|
||||
|
||||
app.post('/message', function(req, res) {
|
||||
res.find(req.body['to'], function(user) {
|
||||
app.use('/app/message', function(req, res) {
|
||||
|
||||
res.find(req.param('to'), function(user) {
|
||||
if(!user)
|
||||
return res.send(new packages.Error('not online'));
|
||||
|
||||
res.message(user, new packages.Message(
|
||||
req.session.data('username'),
|
||||
req.body.body
|
||||
req.param('body')
|
||||
));
|
||||
});
|
||||
});
|
||||
|
||||
app.post('/message/typing', function(req, res) {
|
||||
if(~packages.TYPING_STATES.indexOf('typing' + req.body['state'])) {
|
||||
res.find(req.body['to'], function(user) {
|
||||
app.use('/app/message/typing', function(req, res) {
|
||||
if(~packages.TYPING_STATES.indexOf('typing' + req.param('state'))) {
|
||||
res.find(req.param('to'), function(user) {
|
||||
if(user) {
|
||||
res.message(user, new packages.Status(
|
||||
req.session.data('username'),
|
||||
'typing' + req.body.state
|
||||
'typing' + req.param('state')
|
||||
));
|
||||
}
|
||||
|
||||
@@ -120,16 +72,18 @@ app.post('/message/typing', function(req, res) {
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/status', function(req, res) {
|
||||
if(~packages.STATUSES.indexOf(req.body['status'])) {
|
||||
res.status(req.body.status, req.body.message);
|
||||
app.use('/app/status', function(req, res) {
|
||||
if(~packages.STATUSES.indexOf(req.param('status'))) {
|
||||
res.status(req.param('status'), req.param('message'));
|
||||
res.send(new packages.Success('status updated'));
|
||||
} else {
|
||||
res.send(new packages.Error('invalid status'));
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/signoff', function(req, res) {
|
||||
app.use('/app/signoff', function(req, res) {
|
||||
res.signOff();
|
||||
res.send(new packages.Success('goodbye'));
|
||||
});
|
||||
|
||||
console.log('Ajax IM server started...');
|
||||
|
||||
+2
-12
@@ -1,16 +1,6 @@
|
||||
var utils = require('connect/utils');
|
||||
|
||||
module.exports = function(app) {
|
||||
app.get('/', function(req, res) {
|
||||
module.exports = function(route, app) {
|
||||
app.get(route+'/', function(req, res) {
|
||||
res.render('chat', {
|
||||
locals: {}
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/cookie', function(req, res) {
|
||||
res.send('cookie set', {
|
||||
'Set-Cookie': utils.serializeCookie('sessionid', utils.uid(),
|
||||
{path: '/'})
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -1,13 +1,13 @@
|
||||
!!! 5
|
||||
html
|
||||
doctype html
|
||||
html(lang="en")
|
||||
head
|
||||
title Ajax IM
|
||||
script(src: '/js/jquery-1.4.1.js', type: 'text/javascript')
|
||||
script(src: '/js/md5.js', type: 'text/javascript')
|
||||
script(src: '/js/store.js', type: 'text/javascript')
|
||||
script(src: '/js/cookies.js', type: 'text/javascript')
|
||||
script(src: '/js/dateformat.js', type: 'text/javascript')
|
||||
script(src: '/js/im.js', type: 'text/javascript')
|
||||
script(type: 'text/javascript')
|
||||
| $(function(){var im = AjaxIM.init({theme: "/themes/default"});});
|
||||
body Hello.
|
||||
script(src='/js/jquery-1.11.1.js', type='text/javascript')
|
||||
script(src='/js/md5.js', type='text/javascript')
|
||||
script(src='/js/store.js', type='text/javascript')
|
||||
script(src='/js/dateformat.js', type='text/javascript')
|
||||
script(src='/js/im.js', type='text/javascript')
|
||||
script(type='text/javascript').
|
||||
$(function(){var im = AjaxIM.init({theme: "/themes/default"});});
|
||||
body.
|
||||
Hello.
|
||||
@@ -1,24 +1,53 @@
|
||||
// Cookie that stores the session ID
|
||||
// Will be set as request.sessionID in `authenticate` and `friends` functions
|
||||
exports.cookie = 'sessionid';
|
||||
var o_ = require('../../utils');
|
||||
var User = require('../../../middleware/im/user');
|
||||
|
||||
exports.authenticate = function(request, callback) {
|
||||
// Verify user based on request.
|
||||
// On failure, redirect user to auth form
|
||||
exports.authenticate = function(store, event, callback) {
|
||||
// remove authentication from event
|
||||
var sessionid = event.sessionid;
|
||||
delete event.sessionid;
|
||||
|
||||
callback({
|
||||
username: 'username' + Math.floor(Math.random() * 1000),
|
||||
displayname: 'John Smith',
|
||||
otherinfo: 'any other relevant key/values'
|
||||
});
|
||||
// find the user
|
||||
var user = event.from? store.sessions[event.from]: undefined;
|
||||
|
||||
// create, validate or reject user
|
||||
if (user) {
|
||||
// found the user so check authentication
|
||||
if (sessionid && (sessionid === user.data('sessionid'))) {
|
||||
event.from = user.data('username');
|
||||
callback(event, user);
|
||||
} else {
|
||||
event._status = {sent: false, e: 'not authenticated'};
|
||||
callback(event);
|
||||
}
|
||||
} else if (event.type == 'hello') {
|
||||
store.find('sessionid', sessionid, function(user) {
|
||||
if (user) {
|
||||
// relogin as same user
|
||||
event.from = user.data('username');
|
||||
callback(event, user);
|
||||
} else {
|
||||
// if no username requested, assign user name
|
||||
if (!event.from) {
|
||||
event.from = 'username' + (++store.uid);
|
||||
}
|
||||
// everybody is your friend!
|
||||
var friends = o_.values(store.sessions).map(function(friend) {
|
||||
return friend.data('username');
|
||||
});
|
||||
// you're even friends with yourself!
|
||||
friends.push(event.from);
|
||||
// create new user
|
||||
user = new User(store, {
|
||||
username: event.from,
|
||||
sessionid: sessionid,
|
||||
displayname: 'John Smith',
|
||||
otherinfo: 'any other relevant key/values'
|
||||
}, friends);
|
||||
callback(event, user);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
event._status = {sent: false, e: 'not authenticated'};
|
||||
callback(event);
|
||||
}
|
||||
};
|
||||
|
||||
exports.friends = function(request, data, callback) {
|
||||
// Create a friends list based on given user data
|
||||
|
||||
callback([
|
||||
'username1',
|
||||
'username2',
|
||||
'username3'
|
||||
]);
|
||||
};
|
||||
@@ -1,301 +0,0 @@
|
||||
/*
|
||||
* Daemon.node
|
||||
*** A node.JS addon that allows creating Unix/Linux Daemons in pure Javascript.
|
||||
*** Copyright 2010 (c) <arthur@norgic.com>
|
||||
* Under MIT License. See LICENSE file.
|
||||
*/
|
||||
|
||||
#include <node/node.h>
|
||||
#include <v8.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
|
||||
#define PID_MAXLEN 10
|
||||
|
||||
using namespace v8;
|
||||
|
||||
// Go through special routines to become a daemon.
|
||||
// if successful, returns daemon's PID
|
||||
Handle<Value> Start(const Arguments& args) {
|
||||
pid_t pid;
|
||||
|
||||
pid = fork();
|
||||
if(pid > 0) exit(0);
|
||||
if(pid < 0) exit(1);
|
||||
|
||||
// Can be changed after with process.umaks
|
||||
umask(0);
|
||||
|
||||
setsid();
|
||||
|
||||
// Can be changed with process.chdir
|
||||
chdir("/");
|
||||
|
||||
return Integer::New(getpid());
|
||||
}
|
||||
|
||||
// Close Standard IN/OUT/ERR Streams
|
||||
Handle<Value> CloseIO(const Arguments& args) {
|
||||
close(STDIN_FILENO);
|
||||
close(STDOUT_FILENO);
|
||||
close(STDERR_FILENO);
|
||||
}
|
||||
|
||||
// File-lock to make sure that only one instance of daemon is running.. also for storing PID
|
||||
/* lock ( filename )
|
||||
*** filename: a path to a lock-file.
|
||||
*** Note: if filename doesn't exist, it will be created when function is called.
|
||||
*/
|
||||
Handle<Value> LockD(const Arguments& args) {
|
||||
if(!args[0]->IsString())
|
||||
return Boolean::New(false);
|
||||
|
||||
String::Utf8Value data(args[0]->ToString());
|
||||
char pid_str[PID_MAXLEN+1];
|
||||
|
||||
int lfp = open(*data, O_RDWR | O_CREAT, 0640);
|
||||
if(lfp < 0) exit(1);
|
||||
if(lockf(lfp, F_TLOCK, 0) < 0) exit(0);
|
||||
|
||||
int len = snprintf(pid_str, PID_MAXLEN, "%d", getpid());
|
||||
write(lfp, pid_str, len);
|
||||
|
||||
return Boolean::New(true);
|
||||
}
|
||||
|
||||
class StreamPtr : public node::ObjectWrap
|
||||
{
|
||||
public:
|
||||
explicit StreamPtr(FILE** fpp, const char *pmode);
|
||||
~StreamPtr();
|
||||
|
||||
static Handle<Value> Open(const Arguments& args);
|
||||
static Handle<Value> Close(const Arguments& args);
|
||||
static Handle<Value> Redirect(const Arguments& args);
|
||||
|
||||
static void Initialize(Handle<Object> target);
|
||||
static Handle<Value> New(const Arguments& args);
|
||||
|
||||
FILE** stream;
|
||||
const char *mode;
|
||||
private:
|
||||
static Persistent<FunctionTemplate> constructor_template;
|
||||
};
|
||||
|
||||
Persistent<FunctionTemplate> StreamPtr::constructor_template;
|
||||
|
||||
StreamPtr::StreamPtr(FILE** fpp, const char *pmode)
|
||||
: stream(fpp)
|
||||
, mode( pmode )
|
||||
{
|
||||
}
|
||||
|
||||
StreamPtr::~StreamPtr()
|
||||
{
|
||||
fclose(*stream);
|
||||
}
|
||||
|
||||
Handle<Value> StreamPtr::Open(const Arguments& args)
|
||||
{
|
||||
HandleScope scope;
|
||||
|
||||
StreamPtr *fp = ObjectWrap::Unwrap<StreamPtr>(args.This());
|
||||
char *new_file = *String::Utf8Value(args[0]->ToString());
|
||||
*fp->stream = fopen(new_file, fp->mode);
|
||||
|
||||
// return if the creation of the new FILE* was successful;
|
||||
return Boolean::New( *fp->stream != NULL );
|
||||
}
|
||||
|
||||
Handle<Value> StreamPtr::Close(const Arguments& args)
|
||||
{
|
||||
HandleScope handle_scope;
|
||||
|
||||
StreamPtr *fp = ObjectWrap::Unwrap<StreamPtr>(args.This());
|
||||
assert( fp && "object had no InternalField" );
|
||||
int ret = fclose(*fp->stream);
|
||||
|
||||
return Boolean::New(ret == 0);
|
||||
}
|
||||
|
||||
Handle<Value> StreamPtr::Redirect(const Arguments& args)
|
||||
{
|
||||
HandleScope scope;
|
||||
if (Close(args)->ToBoolean()->Value())
|
||||
{
|
||||
return Open(args);
|
||||
} else {
|
||||
return Boolean::New(false);
|
||||
}
|
||||
}
|
||||
|
||||
Persistent<Object> stdin_obj;
|
||||
Persistent<Object> stdout_obj;
|
||||
Persistent<Object> stderr_obj;
|
||||
|
||||
void StreamPtr::Initialize(Handle<Object> target)
|
||||
{
|
||||
HandleScope scope;
|
||||
|
||||
Local<FunctionTemplate> file_pointer = FunctionTemplate::New(StreamPtr::New);
|
||||
constructor_template = Persistent<FunctionTemplate>::New(file_pointer);
|
||||
constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
|
||||
|
||||
NODE_SET_PROTOTYPE_METHOD(constructor_template, "open", StreamPtr::Open);
|
||||
NODE_SET_PROTOTYPE_METHOD(constructor_template, "close", StreamPtr::Close);
|
||||
NODE_SET_PROTOTYPE_METHOD(constructor_template, "sendTo", StreamPtr::Redirect);
|
||||
|
||||
// Although we could expose the prototype directly, I see no reason to, as it's not
|
||||
// very useful for anything other than the intended purpose.
|
||||
//target->Set(String::NewSymbol("StreamPtr"), constructor_template->GetFunction());
|
||||
|
||||
stdin_obj = Persistent<Object>::New( constructor_template->GetFunction()->NewInstance() );
|
||||
Handle<External> stdin_ptr = External::New( new StreamPtr( &stdin, "r" ) );
|
||||
stdin_obj->SetInternalField(0, stdin_ptr);
|
||||
target->Set(String::NewSymbol("stdin"), stdin_obj);
|
||||
|
||||
stdout_obj = Persistent<Object>::New( constructor_template->GetFunction()->NewInstance() );
|
||||
Handle<External> stdout_ptr = External::New( new StreamPtr( &stdout, "w" ) );
|
||||
stdout_obj->SetInternalField(0, stdout_ptr);
|
||||
target->Set(String::NewSymbol("stdout"), stdout_obj);
|
||||
|
||||
stderr_obj = Persistent<Object>::New( constructor_template->GetFunction()->NewInstance() );
|
||||
Handle<External> stderr_ptr = External::New( new StreamPtr( &stderr, "w" ) );
|
||||
stderr_obj->SetInternalField(0, stderr_ptr);
|
||||
target->Set(String::NewSymbol("stderr"), stderr_obj);
|
||||
}
|
||||
|
||||
Handle<Value> StreamPtr::New(const Arguments& args)
|
||||
{
|
||||
HandleScope scope;
|
||||
return scope.Close(args.This());
|
||||
}
|
||||
|
||||
/* The default object:
|
||||
* {
|
||||
* "fork": true,
|
||||
* "lock": "daemon.pid"
|
||||
* "stdout": null,
|
||||
* "stderr": null,
|
||||
* "stdin": null,
|
||||
* "umask": 0,
|
||||
* "chroot": null,
|
||||
* "chdir": ".",
|
||||
* }
|
||||
*/
|
||||
|
||||
#define SET_DEFAULT(obj, name, value) \
|
||||
do { \
|
||||
Local<String> str_##name = String::New(#name); \
|
||||
if( !obj->Has( str_##name ) ) \
|
||||
obj->Set( str_##name, (value) ); \
|
||||
} while (0)
|
||||
|
||||
static inline void setDefaults(Handle<Object> &arg)
|
||||
{
|
||||
HandleScope scope;
|
||||
|
||||
SET_DEFAULT( arg, fork, Boolean::New(true) );
|
||||
SET_DEFAULT( arg, lock, String::New("daemon.pid") );
|
||||
SET_DEFAULT( arg, stdin, Null() );
|
||||
SET_DEFAULT( arg, stdout, Null() );
|
||||
SET_DEFAULT( arg, stderr, Null() );
|
||||
SET_DEFAULT( arg, umask, Integer::New(0) );
|
||||
SET_DEFAULT( arg, chroot, Null() );
|
||||
SET_DEFAULT( arg, chdir, String::New(".") );
|
||||
//SET_DEFAULT( arg, close_fds, Boolean::New(false) );
|
||||
//SET_DEFAULT( arg, catch_signals, Boolean::New(false) );
|
||||
}
|
||||
|
||||
#undef SET_DEFAULT
|
||||
|
||||
Handle<Value> Init(const Arguments& args)
|
||||
{
|
||||
HandleScope scope;
|
||||
|
||||
Local<Object> arg = args[0]->ToObject();
|
||||
setDefaults( arg );
|
||||
|
||||
pid_t pid = 0;
|
||||
if( arg->Get( String::New("fork") )->IsTrue() )
|
||||
{
|
||||
pid = fork();
|
||||
if(pid > 0) exit(0);
|
||||
if(pid < 0) exit(1);
|
||||
}
|
||||
|
||||
if( !arg->Get( String::New("lock") )->IsNull() )
|
||||
{
|
||||
Local<String> file = arg->Get( String::New( "lock" ) )->ToString();
|
||||
String::Utf8Value data(file);
|
||||
char pid_str[PID_MAXLEN+1];
|
||||
|
||||
int lfp = open(*data, O_RDWR | O_CREAT, 0640);
|
||||
if(lfp < 0) exit(1);
|
||||
if(lockf(lfp, F_TLOCK, 0) < 0) exit(0);
|
||||
|
||||
int len = snprintf(pid_str, PID_MAXLEN, "%d", getpid());
|
||||
write(lfp, pid_str, len);
|
||||
}
|
||||
|
||||
if( arg->Get( String::New("stdin") )->IsNull() )
|
||||
{
|
||||
Local<Function> close = Function::Cast( *stdin_obj->Get( String::New("close") ) );
|
||||
close->Call( stdin_obj, 0, NULL );
|
||||
} else {
|
||||
Local<Function> send_to = Function::Cast( *stdin_obj->Get( String::New("sendTo") ) );
|
||||
Local<Value> string_arg = arg->Get( String::New("stdin") );
|
||||
send_to->Call( stdin_obj, 1, &string_arg );
|
||||
}
|
||||
|
||||
if( arg->Get( String::New("stdout") )->IsNull() )
|
||||
{
|
||||
Local<Function> close = Function::Cast( *stdout_obj->Get( String::New("close") ) );
|
||||
close->Call( stdout_obj, 0, NULL );
|
||||
} else {
|
||||
Local<Function> send_to = Function::Cast( *stdout_obj->Get( String::New("sendTo") ) );
|
||||
Local<Value> string_arg = arg->Get( String::New("stdout") );
|
||||
send_to->Call( stdout_obj, 1, &string_arg );
|
||||
}
|
||||
|
||||
if( arg->Get( String::New("stderr") )->IsNull() )
|
||||
{
|
||||
Local<Function> close = Function::Cast( *stderr_obj->Get( String::New("close") ) );
|
||||
close->Call( stderr_obj, 0, NULL );
|
||||
} else {
|
||||
Local<Function> send_to = Function::Cast( *stderr_obj->Get( String::New("sendTo") ) );
|
||||
Local<Value> string_arg = arg->Get( String::New("stderr") );
|
||||
send_to->Call( stderr_obj, 1, &string_arg );
|
||||
}
|
||||
|
||||
Local<Integer> umask_arg = arg->Get( String::New("umask") )->ToInteger();
|
||||
umask( umask_arg->Value() );
|
||||
|
||||
if( !arg->Get( String::New("chroot") )->IsNull() )
|
||||
{
|
||||
char* dir = *String::AsciiValue( arg->Get( String::New("chroot") ) );
|
||||
chroot( dir );
|
||||
}
|
||||
|
||||
if( !arg->Get( String::New("chdir") )->IsNull() )
|
||||
{
|
||||
char* dir = *String::AsciiValue( arg->Get( String::New("chdir") ) );
|
||||
chdir( dir );
|
||||
}
|
||||
|
||||
return Integer::New(pid);
|
||||
}
|
||||
|
||||
extern "C" void init(Handle<Object> target) {
|
||||
HandleScope scope;
|
||||
|
||||
target->Set(String::New("start"), FunctionTemplate::New(Start)->GetFunction());
|
||||
target->Set(String::New("lock"), FunctionTemplate::New(LockD)->GetFunction());
|
||||
target->Set(String::New("closeIO"), FunctionTemplate::New(CloseIO)->GetFunction());
|
||||
target->Set(String::New("init"), FunctionTemplate::New(Init)->GetFunction());
|
||||
|
||||
StreamPtr::Initialize(target);
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
srcdir = "."
|
||||
blddir = "build"
|
||||
VERSION = "0.0.1"
|
||||
|
||||
def set_options(opt):
|
||||
opt.tool_options("compiler_cxx")
|
||||
|
||||
def configure(conf):
|
||||
conf.check_tool("compiler_cxx")
|
||||
conf.check_tool("node_addon")
|
||||
|
||||
def build(bld):
|
||||
obj = bld.new_task_gen("cxx", "shlib", "node_addon")
|
||||
obj.target = "daemon"
|
||||
obj.source = "daemon.cc"
|
||||
@@ -1,88 +1,2 @@
|
||||
var sys = require('sys');
|
||||
|
||||
var Package = function() {};
|
||||
Package.prototype._sanitize = function(content) {
|
||||
// strip HTML
|
||||
return content.replace(/<(.|\n)*?>/g, '');
|
||||
};
|
||||
|
||||
var Error = exports.Error = function(error) {
|
||||
this.error = error;
|
||||
};
|
||||
sys.inherits(Error, Package);
|
||||
Error.prototype.toJSON = function() {
|
||||
return {
|
||||
type: 'error',
|
||||
error: this.error
|
||||
};
|
||||
};
|
||||
|
||||
var Success = exports.Success = function(success) {
|
||||
this.success = success;
|
||||
};
|
||||
sys.inherits(Success, Package);
|
||||
Success.prototype.toJSON = function() {
|
||||
return {
|
||||
type: 'success',
|
||||
success: this.success
|
||||
};
|
||||
};
|
||||
|
||||
var Message = exports.Message = function(from, body) {
|
||||
this.from = from;
|
||||
this.body = body;
|
||||
};
|
||||
sys.inherits(Message, Package);
|
||||
Message.prototype.toJSON = function() {
|
||||
return {
|
||||
type: 'message',
|
||||
user: this.from,
|
||||
body: this._sanitize(this.body)
|
||||
};
|
||||
};
|
||||
|
||||
var Notice = exports.Notice = function(username, info) {
|
||||
this.username = username;
|
||||
this.info = info;
|
||||
};
|
||||
sys.inherits(Notice, Package);
|
||||
Notice.prototype.toJSON = function() {
|
||||
return {
|
||||
type: 'notice',
|
||||
user: this.username,
|
||||
info: this.info
|
||||
};
|
||||
};
|
||||
|
||||
exports.TYPING_STATES = ['typing+', 'typing~', 'typing-'];
|
||||
exports.STATUSES = ['available', 'away', 'idle'];
|
||||
var Status = exports.Status = function(username, status, message) {
|
||||
var statuses = exports.STATUSES + exports.TYPING_STATES;
|
||||
|
||||
this.username = username;
|
||||
this.status = -~statuses.indexOf(status) ? status : statuses[0];
|
||||
this.message = message;
|
||||
};
|
||||
sys.inherits(Status, Package);
|
||||
Status.prototype.toJSON = function() {
|
||||
return {
|
||||
type: 'status',
|
||||
user: this.username,
|
||||
status: this.status,
|
||||
message: this._sanitize(this.message || '')
|
||||
};
|
||||
};
|
||||
|
||||
var Offline = exports.Offline = function(username) {
|
||||
this.username = username;
|
||||
};
|
||||
sys.inherits(Offline, Package);
|
||||
Offline.prototype.toJSON = function() {
|
||||
// A special type of status
|
||||
return {
|
||||
type: 'status',
|
||||
user: this.username,
|
||||
status: 'offline',
|
||||
message: ''
|
||||
};
|
||||
};
|
||||
|
||||
@@ -9,6 +9,21 @@ module.exports = o_ = {
|
||||
a[keys[i]] = b[keys[i]];
|
||||
return a;
|
||||
},
|
||||
|
||||
extend: function() {
|
||||
var o = {};
|
||||
for (var a=0; a < arguments.length; ++a) {
|
||||
this.merge(o, arguments[a]);
|
||||
}
|
||||
return o;
|
||||
},
|
||||
|
||||
deletekey: function(o, key) {
|
||||
if (o.hasOwnProperty(key)) {
|
||||
delete o[key];
|
||||
}
|
||||
return o;
|
||||
},
|
||||
|
||||
values: function(obj) {
|
||||
if(typeof obj == 'array')
|
||||
|
||||
+64
-43
@@ -1,67 +1,88 @@
|
||||
var url = require('url'),
|
||||
Hub = require('./im/hub');
|
||||
Hub = require('./im/hub'),
|
||||
packages = require('../libs/packages'),
|
||||
o_ = require('../libs/utils');
|
||||
|
||||
module.exports = function setupHub(options) {
|
||||
options = options || {};
|
||||
|
||||
store = new Hub(options);
|
||||
var store = new Hub(options);
|
||||
|
||||
return function session(req, res, next) {
|
||||
return {store: store, session: function session(req, res, next) {
|
||||
req.sessionStore = store;
|
||||
req.sessionID = req.cookies[options.authentication.cookie];
|
||||
|
||||
if(!req.cookies) {
|
||||
next(new Error('session requires cookieDecoder to work properly'));
|
||||
return;
|
||||
}
|
||||
|
||||
if(req.dev) {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
// create the event object
|
||||
req.event = o_.extend({}, req.query, req.body, req.params);
|
||||
o_.deletekey(req.event, 'callback');
|
||||
o_.deletekey(req.event, '_');
|
||||
|
||||
if(req.sessionID) {
|
||||
store.get(req, function(err, sess) {
|
||||
if(err) {
|
||||
next(err);
|
||||
req.event.reply = function(status) {
|
||||
if (status) {
|
||||
this._status = status;
|
||||
}
|
||||
delete this.reply;
|
||||
res.jsonp(this);
|
||||
};
|
||||
|
||||
var unauthenticated = function() {
|
||||
req.event.reply({sent: false, e: 'unauthenticated'});
|
||||
};
|
||||
|
||||
// set event handlers to unauthenticated by default
|
||||
res.message = res.typing = res.status = res.signOff = unauthenticated;
|
||||
|
||||
if(url.parse(req.url).pathname.substring(0, 5) === '/app/') {
|
||||
store.get(req.event, function(event, user) {
|
||||
if(!user) {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
if(!sess) {
|
||||
next(new Error(JSON.stringify({
|
||||
type: 'error',
|
||||
error: 'not authenticated'})));
|
||||
return;
|
||||
}
|
||||
|
||||
sess.touch();
|
||||
if(url.parse(req.url).pathname === '/listen') {
|
||||
user.touch();
|
||||
if(url.parse(req.url).pathname === '/app/listen') {
|
||||
req.connection.setTimeout(5 * 60 * 1000);
|
||||
sess.listener(res);
|
||||
store.set(req.sessionID, sess);
|
||||
user.listener(res);
|
||||
store.set(user.data('username'), user);
|
||||
|
||||
if(msg = sess.message_queue.shift())
|
||||
sess._send.apply(sess, msg);
|
||||
if(msg = user.message_queue.shift()) {
|
||||
user._send.apply(user, msg);
|
||||
}
|
||||
} else {
|
||||
sess.connection = res;
|
||||
req.event.from = user.data('username');
|
||||
}
|
||||
|
||||
req.session = sess;
|
||||
res.find = store.find.bind(store);
|
||||
res.message = function(to, package) {
|
||||
store.message(req.session, to, package);
|
||||
res.message = function() {
|
||||
user.message(req.event);
|
||||
};
|
||||
res.status = function(value, message) {
|
||||
req.session.status(value, message);
|
||||
res.typing = function() {
|
||||
if(~packages.TYPING_STATES.indexOf('typing' + req.event.state)) {
|
||||
store.find('username', req.event.to, function(to) {
|
||||
if(to) {
|
||||
req.event.status = 'typing' + req.event.state;
|
||||
user.message(req.event);
|
||||
} else {
|
||||
// Typing updates do not receive confirmations,
|
||||
// as they are not important enough.
|
||||
req.event.reply({sent: true});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
req.event.reply({sent: false, e: 'invalid state'});
|
||||
}
|
||||
};
|
||||
res.status = function() {
|
||||
user.status(req.event);
|
||||
};
|
||||
res.signOff = function() {
|
||||
user.signOff(req.event);
|
||||
};
|
||||
res.signOff = function() { store.signOff(req.sessionID); };
|
||||
|
||||
next();
|
||||
if(url.parse(req.url).pathname !== '/app/listen') {
|
||||
next();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
next(new Error(JSON.stringify({
|
||||
type: 'error',
|
||||
error: 'not authenticated'})));
|
||||
next();
|
||||
}
|
||||
};
|
||||
}};
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@ var events = require('events'),
|
||||
User = require('./user');
|
||||
|
||||
var Hub = module.exports = function Hub(options) {
|
||||
this.uid = 0;
|
||||
this.events = new events.EventEmitter();
|
||||
this.auth = options.authentication;
|
||||
this.sessions = {};
|
||||
@@ -14,19 +15,19 @@ var Hub = module.exports = function Hub(options) {
|
||||
|
||||
if(this.reapInterval !== -1) {
|
||||
setInterval(function(self) {
|
||||
self.reap(self.maxAge);
|
||||
self.reapCheck(self.maxAge);
|
||||
}, this.reapInterval, this);
|
||||
}
|
||||
|
||||
this.events.addListener('update', o_.bind(function(package) {
|
||||
var _package = package.toJSON();
|
||||
if(package.type == 'status' && package.status == 'offline') {
|
||||
this.events.addListener('update', o_.bind(function(event) {
|
||||
if(event.type == 'status' && event.status == 'offline') {
|
||||
var sids = Object.keys(this.sessions), sid, sess;
|
||||
for(sid in this.sessions) {
|
||||
sess = this.sessions[sid];
|
||||
if(sess.data('username') == package.username) {
|
||||
if(sess.listeners.length)
|
||||
sess.send(200, {type: 'goodbye'});
|
||||
if (sess.data('username') == event.from) {
|
||||
if (sess.listeners.length) {
|
||||
sess.send({type: 'goodbye'});
|
||||
}
|
||||
delete this.sessions[sid];
|
||||
break;
|
||||
}
|
||||
@@ -35,60 +36,56 @@ var Hub = module.exports = function Hub(options) {
|
||||
}, this));
|
||||
};
|
||||
|
||||
Hub.prototype.destroy = function(sid, fn) {
|
||||
this.set(sid, null, fn);
|
||||
};
|
||||
|
||||
Hub.prototype.reap = function(ms) {
|
||||
var threshold = +new Date - ms,
|
||||
sids = Object.keys(this.sessions);
|
||||
Hub.prototype.reapCheck = function(ms) {
|
||||
var threshold = +new Date - ms;
|
||||
var sids = Object.keys(this.sessions);
|
||||
for(var i = 0, len = sids.length; i < len; ++i) {
|
||||
var sid = sids[i], sess = this.sessions[sid];
|
||||
if(sess.lastAccess < threshold) {
|
||||
this.events.emit('update', new packages.Offline(sess.data('username')));
|
||||
var sid = sids[i];
|
||||
if(this.sessions[sid].lastAccess < threshold) {
|
||||
this.reap(sid);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Hub.prototype.get = function(req, fn) {
|
||||
if(this.sessions[req.sessionID]) {
|
||||
fn(null, this.sessions[req.sessionID]);
|
||||
} else {
|
||||
this.auth.authenticate(req, o_.bind(function(data) {
|
||||
if(data) {
|
||||
var session = new User(req.sessionID, data);
|
||||
this.set(req.sessionID, session);
|
||||
Hub.prototype.reap = function(sid) {
|
||||
var sess = this.sessions[sid];
|
||||
console.log('reaping '+sess.data('username'));
|
||||
var event = {type: 'status', from: sess.data('username'), status: 'offline', message: ''};
|
||||
this.events.emit('update', event);
|
||||
delete this.sessions[sid];
|
||||
sess.close();
|
||||
};
|
||||
|
||||
this.auth.friends(req, data, o_.bind(function(friends) {
|
||||
var friends_copy = friends.slice();
|
||||
o_.values(this.sessions).filter(function(friend) {
|
||||
return ~friends.indexOf(friend.data('username'));
|
||||
}).forEach(function(friend) {
|
||||
var username = friend.data('username');
|
||||
friends_copy[friends_copy.indexOf(username)] =
|
||||
[username, friend.status()];
|
||||
}, this);
|
||||
|
||||
session._friends(friends_copy);
|
||||
session.events.addListener('status',
|
||||
o_.bind(function(value, message) {
|
||||
this.events.emit(
|
||||
'update',
|
||||
new packages.Status(session.data('username'),
|
||||
value,
|
||||
message)
|
||||
);
|
||||
}, this));
|
||||
this.events.addListener('update',
|
||||
o_.bind(session.receivedUpdate, session));
|
||||
this.set(req.sessionID, session);
|
||||
fn(null, session);
|
||||
}, this));
|
||||
} else {
|
||||
fn();
|
||||
Hub.prototype.get = function(event, fn, socket) {
|
||||
this.auth.authenticate(this, event, o_.bind(function(event, user) {
|
||||
if (user) {
|
||||
if (socket) {
|
||||
user.socketio = socket;
|
||||
}
|
||||
}, this));
|
||||
}
|
||||
if (this.sessions[user.data('username')]) {
|
||||
fn(event, user);
|
||||
return;
|
||||
}
|
||||
this.set(user.data('username'), user);
|
||||
var friends = user.friends;
|
||||
var friends_copy = friends.slice();
|
||||
o_.values(this.sessions).filter(function(friend) {
|
||||
return ~friends.indexOf(friend.data('username'));
|
||||
}).forEach(function(friend) {
|
||||
var username = friend.data('username');
|
||||
friends_copy[friends_copy.indexOf(username)] = [username, friend.status()];
|
||||
}, this);
|
||||
user._friends(friends_copy);
|
||||
user.events.addListener('status', o_.bind(function(value, message) {
|
||||
var event = {type: 'status', from: user.data('username'), status: value, message: message};
|
||||
this.events.emit('update', event);
|
||||
}, this));
|
||||
this.events.addListener('update', o_.bind(user.receivedUpdate, user));
|
||||
fn(event, user);
|
||||
} else {
|
||||
fn(event);
|
||||
}
|
||||
}, this));
|
||||
};
|
||||
|
||||
Hub.prototype.set = function(sid, sess, fn) {
|
||||
@@ -96,11 +93,11 @@ Hub.prototype.set = function(sid, sess, fn) {
|
||||
fn && fn();
|
||||
};
|
||||
|
||||
Hub.prototype.find = function(username, fn) {
|
||||
Hub.prototype.find = function(key, value, fn) {
|
||||
for(var sid in this.sessions) {
|
||||
var session = this.sessions[sid],
|
||||
sess_username = session.data('username');
|
||||
if(sess_username == username) {
|
||||
var session = this.sessions[sid];
|
||||
var user_value = session.data(key);
|
||||
if (user_value == value) {
|
||||
fn(session);
|
||||
return;
|
||||
}
|
||||
@@ -108,19 +105,12 @@ Hub.prototype.find = function(username, fn) {
|
||||
fn(false);
|
||||
};
|
||||
|
||||
Hub.prototype.message = function(from, to, package) {
|
||||
try {
|
||||
package.user = from;
|
||||
to.send(package);
|
||||
from.respond(new packages.Success('sent'));
|
||||
} catch(e) {
|
||||
from.respond(new packages.Error(e.description));
|
||||
}
|
||||
};
|
||||
|
||||
Hub.prototype.signOff = function(sid) {
|
||||
if(sid in this.sessions)
|
||||
this.events.emit('update',
|
||||
new packages.Offline(
|
||||
this.sessions[sid].data('username')));
|
||||
Hub.prototype.dispatch = function(event) {
|
||||
this.find('username', event.from, function(from) {
|
||||
if (from) {
|
||||
from.dispatch(event);
|
||||
} else {
|
||||
event.reply({sent: false, e: 'not authenticated'});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -2,32 +2,50 @@ var events = require('events'),
|
||||
packages = require('../../libs/packages'),
|
||||
o_ = require('../../libs/utils');
|
||||
|
||||
var User = module.exports = function(id, data) {
|
||||
this.id = id;
|
||||
var User = module.exports = function(store, data, friends) {
|
||||
this.store = store;
|
||||
this.connection = null;
|
||||
this.listeners = [];
|
||||
this.message_queue = [];
|
||||
this.convos = {};
|
||||
this._data = data;
|
||||
this.friends = friends;
|
||||
|
||||
this.events = new events.EventEmitter();
|
||||
this.status(packages.STATUSES[0], '');
|
||||
this._status = packages.STATUSES[0];
|
||||
this._status_message = '';
|
||||
|
||||
setInterval(o_.bind(this._expireConns, this), 500);
|
||||
this.interval = setInterval(o_.bind(this._expireConns, this), 500);
|
||||
};
|
||||
|
||||
User.prototype.receivedUpdate = function(package) {
|
||||
if(this.friends.indexOf(package.username))
|
||||
this.send(package);
|
||||
User.prototype.close = function() {
|
||||
clearInterval(this.interval);
|
||||
var conn,
|
||||
noop = JSON.stringify({type: 'noop'}),
|
||||
noop_headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'Content-Length': noop.length
|
||||
};
|
||||
for(var i = this.listeners.length-1; i >= 0; i--) {
|
||||
conn = this.listeners[i].connection;
|
||||
this.listeners[i].writeHead(200, noop_headers);
|
||||
this.listeners[i].end(noop);
|
||||
}
|
||||
};
|
||||
|
||||
User.prototype.receivedUpdate = function(event) {
|
||||
event = o_.extend({}, event);
|
||||
event.to = this.data('username');
|
||||
if(this.friends.indexOf(event.from))
|
||||
this.send(event);
|
||||
};
|
||||
|
||||
User.prototype._friends = function(friends) {
|
||||
this.friends = friends;
|
||||
this.send(JSON.stringify({
|
||||
this.send({
|
||||
type: 'hello',
|
||||
username: this.data('username'),
|
||||
friends: friends
|
||||
}));
|
||||
});
|
||||
};
|
||||
|
||||
User.prototype._expireConns = function() {
|
||||
@@ -52,49 +70,37 @@ User.prototype.listener = function(conn) {
|
||||
this.listeners.push(conn);
|
||||
};
|
||||
|
||||
User.prototype.respond = function(code, message, callback) {
|
||||
this._send('connection', code, message, callback);
|
||||
User.prototype.send = function(event) {
|
||||
this._send('listener', event);
|
||||
};
|
||||
|
||||
User.prototype.send = function(code, message, callback) {
|
||||
this._send('listener', code, message, callback);
|
||||
};
|
||||
|
||||
User.prototype._send = function(type, code, message, callback) {
|
||||
if(!message && typeof code != 'number') {
|
||||
callback = message;
|
||||
message = code;
|
||||
code = 200;
|
||||
}
|
||||
|
||||
if(typeof message != 'string')
|
||||
message = JSON.stringify(message);
|
||||
|
||||
if(type == 'connection' && this.connection) {
|
||||
this.connection.writeHead(code || 200, {
|
||||
'Content-Type': 'application/json',
|
||||
'Content-Length': message.length
|
||||
});
|
||||
this.connection.end(message);
|
||||
User.prototype._send = function(type, event, res) {
|
||||
if (this.socketio) {
|
||||
var id = event.id;
|
||||
if (event.id) {
|
||||
delete event.id;
|
||||
}
|
||||
this.socketio.emit('client', event);
|
||||
if (id) {
|
||||
event.id = id;
|
||||
}
|
||||
} else if(type == 'connection') {
|
||||
// end a regular connection with a response
|
||||
res.jsonp(event);
|
||||
} else {
|
||||
// end a long-polling connection with an event
|
||||
if(!this.listeners.length)
|
||||
return this.message_queue.push(arguments);
|
||||
|
||||
var cx = this.listeners.slice(), conn;
|
||||
this.listeners = [];
|
||||
while(conn = cx.shift()) {
|
||||
conn.writeHead(code || 200, {
|
||||
'Content-Type': 'application/json',
|
||||
'Content-Length': message.length
|
||||
});
|
||||
conn.end(message);
|
||||
conn.jsonp(event);
|
||||
}
|
||||
if(callback) callback();
|
||||
}
|
||||
};
|
||||
|
||||
User.prototype.data = function(key, def) {
|
||||
if(key == 'id') return this.id;
|
||||
return this._data[key] || this['_' + key] ||
|
||||
(typeof this[key] != 'function' && this[key]) ||
|
||||
def || false;
|
||||
@@ -104,11 +110,49 @@ User.prototype.touch = function() {
|
||||
this.lastAccess = +new Date;
|
||||
};
|
||||
|
||||
User.prototype.status = function(value, message) {
|
||||
if(!value)
|
||||
return this._status;
|
||||
|
||||
this._status = value;
|
||||
this._status_message = message;
|
||||
this.events.emit('status', value, message);
|
||||
User.prototype.message = function(event) {
|
||||
var self = this;
|
||||
try {
|
||||
self.store.find('username', event.to, function(to) {
|
||||
if(to) {
|
||||
to.send(event);
|
||||
event.reply({sent: true});
|
||||
} else {
|
||||
event.reply({sent: false, e: 'not online'});
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
event.reply({sent: false, e: e.description});
|
||||
}
|
||||
};
|
||||
|
||||
User.prototype.status = function(event) {
|
||||
if (!event) {
|
||||
return this._status;
|
||||
}
|
||||
|
||||
this._status = event.status;
|
||||
this._status_message = event.message;
|
||||
this.events.emit('status', event.status, event.message);
|
||||
if (event.reply) {
|
||||
event.reply({sent: true});
|
||||
}
|
||||
};
|
||||
|
||||
User.prototype.signOff = function(event) {
|
||||
event.status = 'offline';
|
||||
this.store.events.emit('update', event);
|
||||
event.reply({sent: true});
|
||||
};
|
||||
|
||||
User.prototype.dispatch = function(event) {
|
||||
if (event.type == 'message') {
|
||||
this.message(event);
|
||||
} else if (event.type == 'status') {
|
||||
this.status(event);
|
||||
} else if (event.type == 'signoff') {
|
||||
this.signOff(event);
|
||||
} else {
|
||||
event.reply({sent: false, e: 'invalid event type'});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
// == Server Configuration ==
|
||||
//
|
||||
// This is the configuration file for the Node.js Ajax IM server. Here, you
|
||||
// can set which ports will be used for the public and internal servers,
|
||||
// as well as other settings such as the session cookie name and expiration.
|
||||
// can set which ports will be used for the public and internal servers.
|
||||
|
||||
// === Host and Port ===
|
||||
//
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário