Update sources to Jappix 1.1.0
11
source/.gitignore
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
mini/
|
||||
store/
|
||||
tmp/cache/
|
||||
tmp/jingle/
|
||||
tmp/avatar/
|
||||
tmp/archives/
|
||||
tmp/send/
|
||||
log/
|
||||
test/node_modules/
|
||||
.DS_Store
|
||||
*.esproj
|
|
@ -4,6 +4,57 @@ Jappix Changelog
|
|||
Here's the log of what has changed over the Jappix releases.
|
||||
|
||||
|
||||
Primo, v1.1.0 (Jun 2014)
|
||||
------------------------
|
||||
|
||||
* XEP-0272: Multiparty Jingle (Muji) @valeriansaliou
|
||||
* Prevent client crash on huge messages @valeriansaliou
|
||||
* Beautified client code (JavaScript) @valeriansaliou
|
||||
* Fix unavailable MUC rooms @emamirazavi
|
||||
|
||||
|
||||
One, v1.0.7 (May 2014)
|
||||
----------------------
|
||||
|
||||
* Fix BackLinks design @valeriansaliou
|
||||
* Sort Jappix Mobile contacts alphabetically @valeriansaliou
|
||||
* Display offline contacts in Jappix Mini @valeriansaliou
|
||||
|
||||
|
||||
One, v1.0.6 (May 2014)
|
||||
----------------------
|
||||
|
||||
* XEP-0308: Last Message Correction @valeriansaliou
|
||||
* XEP-0333: Chat Markers @valeriansaliou
|
||||
* XEP-0319: Last User Interaction into Presence @valeriansaliou
|
||||
* XEP-0224: Attention @valeriansaliou
|
||||
* XEP-0152: Reachability Addresses @valeriansaliou
|
||||
* XEP-0334: Message Processing Hints @valeriansaliou
|
||||
* Fix gateway contacts management @valeriansaliou
|
||||
* Fix sounds in Jappix Mini @aryo, @valeriansaliou
|
||||
|
||||
|
||||
One, v1.0.5 (May 2014)
|
||||
----------------------
|
||||
|
||||
* Fix MUC bookmark shortcut button @valeriansaliou
|
||||
* Fix HTML5 notifications in Firefox 22+ @valeriansaliou
|
||||
* Fix server commands tool @valeriansaliou
|
||||
* New translations added (Uzbek), and a few ones updated @nurkamol, @valeriansaliou
|
||||
|
||||
|
||||
One, v1.0.4 (May 2014)
|
||||
----------------------
|
||||
|
||||
* Fix update tool (on some environments) @valeriansaliou
|
||||
* Fix MUC room join @maranda, @valeriansaliou
|
||||
* Fix special chars in JIDs for Jappix Mini @dunger, @valeriansaliou
|
||||
* Fix WebSocket session termination in JSJaC @sstrigler
|
||||
* Enhance backend security (verify SSL certificates) @valeriansaliou
|
||||
* Add assets client cache option @valeriansaliou
|
||||
* Add SSO support to Jappix Mobile @valeriansaliou
|
||||
|
||||
|
||||
One, v1.0.3 (March 2014)
|
||||
------------------------
|
||||
|
||||
|
|
|
@ -11,56 +11,75 @@ Here are listed the XMPP Protocol Extensions that Jappix supports, as well as th
|
|||
* RFC-6122: Extensible Messaging and Presence Protocol (XMPP): Address Format
|
||||
|
||||
|
||||
# XMPP Extensions
|
||||
# XMPP Extensions (Standardized)
|
||||
|
||||
* XEP-0045: Multi-User Chat *v1.25*
|
||||
* XEP-0004: Data Forms *v2.9*
|
||||
* XEP-0012: Last Activity *v2.0*
|
||||
* XEP-0016: Privacy Lists *v1.6*
|
||||
* XEP-0030: Service Discovery *v2.4*
|
||||
* XEP-0045: Multi-User Chat *v1.25*
|
||||
* XEP-0049: Private XML Storage *v1.2*
|
||||
* XEP-0050: Ad-Hoc Commands *v1.2*
|
||||
* XEP-0054: vcard-temp *v1.2*
|
||||
* XEP-0055: Jabber Search *v1.3*
|
||||
* XEP-0060: Publish-Subscribe *v1.13*
|
||||
* XEP-0124: Bidirectional-streams Over Synchronous HTTP (BOSH) *v1.10*
|
||||
* XEP-0115: Entity Capabilities *v1.5*
|
||||
* XEP-0066: Out of Band Data *v1.5*
|
||||
* XEP-0071: XHTML-IM *v1.5*
|
||||
* XEP-0072: SOAP Over XMPP *v1.0*
|
||||
* XEP-0077: In-Band Registration *v2.4*
|
||||
* XEP-0080: User Location *v1.7*
|
||||
* XEP-0084: User Avatar *v1.1*
|
||||
* XEP-0085: Chat State Notifications *v2.1*
|
||||
* XEP-0092: Software Version *v1.1*
|
||||
* XEP-0107: User Mood *v1.2*
|
||||
* XEP-0108: User Activity *v1.3*
|
||||
* XEP-0115: Entity Capabilities *v1.5*
|
||||
* XEP-0118: User Tune *v1.2*
|
||||
* XEP-0080: User Location *v1.7*
|
||||
* XEP-0172: User Nickname *v1.1*
|
||||
* XEP-0084: User Avatar *v1.1*
|
||||
* XEP-0277: Microblogging over XMPP *v0.6*
|
||||
* XEP-xxxx: Notification Inbox *v0.1*
|
||||
* Alternate URL: http://xmpp.org/extensions/inbox/notification-inbox.html
|
||||
* XEP-0203: Delayed Delivery *v2.0*
|
||||
* XEP-0124: Bidirectional-streams Over Synchronous HTTP (BOSH) *v1.10*
|
||||
* XEP-0144: Roster Item Exchange *v1.0*
|
||||
* XEP-0072: SOAP Over XMPP *v1.0*
|
||||
* XEP-0085: Chat State Notifications *v2.1*
|
||||
* XEP-0071: XHTML-IM *v1.5*
|
||||
* XEP-0313: Message Archive Management *v0.3*
|
||||
* Alternate URL: https://demo.frenchtouch.pro/valerian.saliou/xmpp/extensions/xep-0313.html
|
||||
* XEP-0012: Last Activity *v2.0*
|
||||
* XEP-0049: Private XML Storage *v1.2*
|
||||
* XEP-0077: In-Band Registration *v2.4*
|
||||
* XEP-0055: Jabber Search *v1.3*
|
||||
* XEP-0050: Ad-Hoc Commands *v1.2*
|
||||
* XEP-0092: Software Version *v1.1*
|
||||
* XEP-0004: Data Forms *v2.9*
|
||||
* XEP-0054: vcard-temp *v1.2*
|
||||
* XEP-0202: Entity Time *v2.0*
|
||||
* XEP-0199: XMPP Ping *v2.0*
|
||||
* XEP-0184: Message Delivery Receipts *v1.2*
|
||||
* XEP-0016: Privacy Lists *v1.6*
|
||||
* XEP-0066: Out of Band Data *v1.5*
|
||||
* XEP-0280: Message Carbons *v0.9*
|
||||
* XEP-0292: vCard4 Over XMPP *v0.10*
|
||||
* XEP-0152: Reachability Addresses *v1.0*
|
||||
* XEP-0166: Jingle *v1.1*
|
||||
* XEP-0167: Jingle RTP Sessions *v1.1*
|
||||
* XEP-0172: User Nickname *v1.1*
|
||||
* XEP-0176: Jingle ICE-UDP Transport Method *v1.0*
|
||||
* XEP-0177: Jingle Raw UDP Transport Method *v1.1*
|
||||
* XEP-0184: Message Delivery Receipts *v1.2*
|
||||
* XEP-0199: XMPP Ping *v2.0*
|
||||
* XEP-0202: Entity Time *v2.0*
|
||||
* XEP-0203: Delayed Delivery *v2.0*
|
||||
* XEP-0224: Attention *v1.0*
|
||||
* XEP-0215: External Service Discovery *v0.5*
|
||||
* XEP-0249: Direct MUC Invitations *v1.2*
|
||||
* XEP-0262: Use of ZRTP in Jingle RTP Sessions *v1.0*
|
||||
* XEP-0266: Codecs for Jingle Audio *v1.0*
|
||||
* XEP-0269: Jingle Early Media *v0.1*
|
||||
* XEP-0277: Microblogging over XMPP *v0.6*
|
||||
* XEP-0278: Jingle Relay Nodes *v0.2*
|
||||
* XEP-0280: Message Carbons *v0.9*
|
||||
* XEP-0292: vCard4 Over XMPP *v0.10*
|
||||
* XEP-0293: Jingle RTP Feedback Negotiation *v0.1*
|
||||
* XEP-0294: Jingle RTP Header Extensions Negotiation *v0.1*
|
||||
* XEP-0299: Codecs for Jingle Video *v0.1*
|
||||
* XEP-0308: Last Message Correction *v1.0*
|
||||
* XEP-0319: Last User Interaction in Presence *v0.2*
|
||||
* XEP-0320: Use of DTLS-SRTP in Jingle Sessions *v0.2*
|
||||
* XEP-0333: Chat Markers *v0.2*
|
||||
* XEP-0334: Message Processing Hints *v0.1*
|
||||
* XEP-0338: Jingle Grouping Framework *v0.1*
|
||||
* XEP-0339: Source-Specific Media Attributes in Jingle *v0.1*
|
||||
|
||||
|
||||
# XMPP Extensions (Updated)
|
||||
|
||||
* XEP-0272: Multiparty Jingle (Muji) *v0.2*
|
||||
* Alternate URL: https://demo.frenchtouch.pro/valerian.saliou/xmpp/extensions/xep-0272.html
|
||||
* XEP-0313: Message Archive Management *v0.3*
|
||||
* Alternate URL: https://demo.frenchtouch.pro/valerian.saliou/xmpp/extensions/xep-0313.html
|
||||
|
||||
|
||||
# XMPP Extensions (Proposed)
|
||||
* XEP-xxxx: Notification Inbox *v0.1*
|
||||
* Alternate URL: http://xmpp.org/extensions/inbox/notification-inbox.html
|
||||
|
||||
|
||||
# Others
|
||||
|
|
|
@ -32,9 +32,9 @@ Start translating on https://www.transifex.com/projects/p/jappix/ (new translato
|
|||
Links
|
||||
-----
|
||||
|
||||
* Jappix project website: http://jappix.org/
|
||||
* Jappix project website: https://jappix.org/
|
||||
* Jappix project dev panel: https://github.com/jappix/jappix
|
||||
* Jappix nodes list: http://jappix.net/
|
||||
* Jappix nodes list: https://jappix.net/
|
||||
* Jappix main service: https://jappix.com/
|
||||
* Jappix commercial support: https://jappix.pro/
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
One [1.0.3]
|
||||
Primo [1.1.0]
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<jappix xmlns="jappix:file:get">
|
||||
<css>fonts.css~main.css~images.css~board.css~home.css~others.css~tools.css~roster.css~myinfos.css~pageengine.css~channel.css~pageswitch.css~smileys.css~popup.css~vcard.css~options.css~favorites.css~discovery.css~directory.css~adhoc.css~privacy.css~inbox.css~mucadmin.css~integratebox.css~userinfos.css~search.css~welcome.css~me.css~rosterx.css~jingle.css</css>
|
||||
<js>origin.js~jxhr.js~datejs.js~jquery.js~jquery.ui.js~jquery.json.js~jquery.form.js~jquery.timers.js~jquery.placeholder.js~jquery.textrange.js~base64.js~jsjac.js~jsjac.jingle.js~system.js~constants.js~datastore.js~browser-detect.js~home.js~talk.js~popup.js~audio.js~board.js~bubble.js~chat.js~groupchat.js~smileys.js~oob.js~avatar.js~mucadmin.js~connection.js~dataform.js~discovery.js~directory.js~adhoc.js~privacy.js~errors.js~name.js~favorites.js~features.js~interface.js~xmpplinks.js~iq.js~message.js~chatstate.js~receipts.js~tooltip.js~filter.js~links.js~inbox.js~microblog.js~music.js~notification.js~httpreply.js~options.js~integratebox.js~pubsub.js~pep.js~presence.js~roster.js~jingle.js~storage.js~console.js~common.js~utilities.js~date.js~caps.js~vcard.js~userinfos.js~search.js~autocompletion.js~welcome.js~me.js~rosterx.js~mam.js~carbons.js</js>
|
||||
<css>fonts.css~main.css~images.css~board.css~home.css~others.css~tools.css~roster.css~myinfos.css~pageengine.css~channel.css~pageswitch.css~smileys.css~popup.css~vcard.css~options.css~favorites.css~discovery.css~directory.css~adhoc.css~privacy.css~inbox.css~mucadmin.css~integratebox.css~userinfos.css~search.css~welcome.css~me.css~rosterx.css~call.css~jingle.css~muji.css</css>
|
||||
<js>origin.js~jxhr.js~datejs.js~jquery.js~jquery.ui.js~jquery.json.js~jquery.form.js~jquery.timers.js~jquery.placeholder.js~jquery.textrange.js~jquery.scrollto.js~base64.js~jsjac.js~jsjac.jingle.js~system.js~constants.js~datastore.js~browser-detect.js~home.js~talk.js~popup.js~audio.js~board.js~bubble.js~chat.js~groupchat.js~smileys.js~oob.js~avatar.js~mucadmin.js~connection.js~dataform.js~discovery.js~directory.js~adhoc.js~privacy.js~errors.js~name.js~favorites.js~features.js~interface.js~xmpplinks.js~iq.js~message.js~chatstate.js~receipts.js~tooltip.js~filter.js~links.js~inbox.js~microblog.js~music.js~notification.js~httpreply.js~options.js~integratebox.js~pubsub.js~pep.js~presence.js~roster.js~call.js~jingle.js~muji.js~storage.js~console.js~common.js~utilities.js~date.js~caps.js~vcard.js~userinfos.js~search.js~autocompletion.js~welcome.js~me.js~rosterx.js~mam.js~carbons.js~correction.js~markers.js~attention.js</js>
|
||||
</jappix>
|
||||
|
|
BIN
source/app/images/placeholders/jingle_audio_local.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
source/app/images/placeholders/jingle_audio_remote.png
Normal file
After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 1.1 KiB |
BIN
source/app/images/placeholders/jingle_video_remote.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
source/app/images/sprites/call.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 2 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.2 KiB |
|
@ -142,9 +142,7 @@ var AdHoc = (function () {
|
|||
|
||||
try {
|
||||
// Click event
|
||||
$('#adhoc .bottom .finish').click(
|
||||
self.close()
|
||||
);
|
||||
$('#adhoc .bottom .finish').click(self.close);
|
||||
} catch(e) {
|
||||
Console.error('AdHoc.launch', e);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,28 @@ var Anonymous = (function () {
|
|||
var self = {};
|
||||
|
||||
|
||||
/**
|
||||
* Registers connection handlers
|
||||
* @private
|
||||
* @param {object} con
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._registerHandlers = function(con) {
|
||||
|
||||
try {
|
||||
con.registerHandler('message', Message.handle);
|
||||
con.registerHandler('presence', Presence.handle);
|
||||
con.registerHandler('iq', IQ.handle);
|
||||
con.registerHandler('onconnect', self.connected);
|
||||
con.registerHandler('onerror', Errors.handle);
|
||||
con.registerHandler('ondisconnect', self.disconnected);
|
||||
} catch(e) {
|
||||
Console.error('Anonymous._registerHandlers', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Connected to an anonymous session
|
||||
* @public
|
||||
|
@ -115,12 +137,7 @@ var Anonymous = (function () {
|
|||
}
|
||||
|
||||
// And we handle everything that happen
|
||||
con.registerHandler('message', Message.handle);
|
||||
con.registerHandler('presence', Presence.handle);
|
||||
con.registerHandler('iq', IQ.handle);
|
||||
con.registerHandler('onconnect', self.connected);
|
||||
con.registerHandler('onerror', Errors.handle);
|
||||
con.registerHandler('ondisconnect', self.disconnected);
|
||||
self._registerHandlers(con);
|
||||
|
||||
// We set the anonymous connection parameters
|
||||
oArgs = {};
|
||||
|
@ -165,10 +182,13 @@ var Anonymous = (function () {
|
|||
Interface.showGeneralWait();
|
||||
|
||||
// Get the vars
|
||||
if(XMPPLinks.links_var.r)
|
||||
if(XMPPLinks.links_var.r) {
|
||||
ANONYMOUS_ROOM = XMPPLinks.links_var.r;
|
||||
if(XMPPLinks.links_var.n)
|
||||
}
|
||||
|
||||
if(XMPPLinks.links_var.n) {
|
||||
ANONYMOUS_NICK = XMPPLinks.links_var.n;
|
||||
}
|
||||
|
||||
// Fire the login action
|
||||
self.login(HOST_ANONYMOUS);
|
||||
|
|
216
source/app/javascripts/attention.js
Normal file
|
@ -0,0 +1,216 @@
|
|||
/*
|
||||
|
||||
Jappix - An open social platform
|
||||
Implementation of XEP-0224: Attention
|
||||
|
||||
-------------------------------------------------
|
||||
|
||||
License: AGPL
|
||||
Author: Valérian Saliou
|
||||
|
||||
*/
|
||||
|
||||
// Bundle
|
||||
var Attention = (function () {
|
||||
|
||||
/**
|
||||
* Alias of this
|
||||
* @private
|
||||
*/
|
||||
var self = {};
|
||||
|
||||
|
||||
/**
|
||||
* Displays attention message
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @param {string} body
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._display = function(xid, body, mode) {
|
||||
|
||||
try {
|
||||
var name = Name.getBuddy(xid).htmlEnc();
|
||||
var hash = hex_md5(xid);
|
||||
|
||||
// Compute some variables
|
||||
var message = Common._e(Common.printf("You requested %s's attention to the conversation", name));
|
||||
|
||||
if(mode == 'him') {
|
||||
message = Common._e(Common.printf("%s requested your attention to the conversation", name));
|
||||
}
|
||||
|
||||
if(body) {
|
||||
message += ' (' + body + ')';
|
||||
}
|
||||
|
||||
// Display notification
|
||||
Message.display(
|
||||
'chat',
|
||||
xid,
|
||||
hash,
|
||||
name,
|
||||
message,
|
||||
DateUtils.getCompleteTime(),
|
||||
DateUtils.getTimeStamp(),
|
||||
'system-message',
|
||||
true,
|
||||
undefined,
|
||||
mode
|
||||
);
|
||||
|
||||
// Add a marker to displayed message
|
||||
$('#' + hash + ' .content .one-line.system-message:last').addClass('attention-notice');
|
||||
} catch(e) {
|
||||
Console.error('Attention._display', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sends attention stanza
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @param {string} body
|
||||
* @return {object}
|
||||
*/
|
||||
self._stanza = function(xid, body) {
|
||||
|
||||
try {
|
||||
var message = new JSJaCMessage();
|
||||
message.setType('headline');
|
||||
message.setTo(xid);
|
||||
|
||||
if(body) {
|
||||
message.setBody(body);
|
||||
}
|
||||
|
||||
// Attention node
|
||||
message.appendNode('attention', {
|
||||
'xmlns': NS_URN_ATTENTION
|
||||
});
|
||||
|
||||
con.send(message);
|
||||
|
||||
return message;
|
||||
} catch(e) {
|
||||
Console.error('Attention._stanza', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether last attention message exists or not
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @return {boolean}
|
||||
*/
|
||||
self._lastExists = function(xid, mode) {
|
||||
|
||||
var last_exists = false;
|
||||
|
||||
try {
|
||||
var line_sel = $('#' + hex_md5(xid) + ' .content .one-line[data-mode="' + mode + '"]:last');
|
||||
last_exists = line_sel.is('.system-message.attention-notice') ? true : false;
|
||||
} catch(e) {
|
||||
Console.error('Attention._lastExists', e);
|
||||
} finally {
|
||||
return last_exists;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return whether entity supports attention notifications
|
||||
* @public
|
||||
* @param {string} xid
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.hasSupport = function(xid) {
|
||||
|
||||
var has_support = false;
|
||||
|
||||
try {
|
||||
has_support = true ? $('#' + hex_md5(xid)).attr('data-attention') == 'true' : false;
|
||||
} catch(e) {
|
||||
Console.error('Attention.hasSupport', e);
|
||||
} finally {
|
||||
return has_support;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Send an attention message
|
||||
* @public
|
||||
* @param {string} xid
|
||||
* @param {string} body
|
||||
* @return {undefined}
|
||||
*/
|
||||
self.send = function(xid, body) {
|
||||
|
||||
try {
|
||||
var mode = 'me';
|
||||
|
||||
// Don't send attention message twice
|
||||
if(self._lastExists(xid, mode) === false) {
|
||||
// Send message stanza
|
||||
self._stanza(xid, body);
|
||||
|
||||
// Display attention notification
|
||||
self._display(xid, body, mode);
|
||||
} else {
|
||||
Console.debug('Attention.send', 'Not sending attention message to: ' + xid + ' because already sent.');
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Attention.send', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Receive an attention notification
|
||||
* @public
|
||||
* @param {string} xid
|
||||
* @return {undefined}
|
||||
*/
|
||||
self.receive = function(xid, body) {
|
||||
|
||||
try {
|
||||
var mode = 'him';
|
||||
var hash = hex_md5(xid);
|
||||
|
||||
// Don't receive attention message twice
|
||||
if((self._lastExists(xid, mode) === false) && Common.exists('#' + hash)) {
|
||||
// Display attention notification
|
||||
self._display(xid, body, mode);
|
||||
|
||||
// Show a notification
|
||||
Interface.messageNotify(hash, 'personal');
|
||||
Audio.play('catch-attention');
|
||||
|
||||
Board.quick(
|
||||
xid,
|
||||
'chat',
|
||||
Common._e("Attention to conversation requested."),
|
||||
Name.getBuddy(xid)
|
||||
);
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Attention.receive', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return class scope
|
||||
*/
|
||||
return self;
|
||||
|
||||
})();
|
|
@ -29,7 +29,7 @@ var Audio = (function () {
|
|||
* @private
|
||||
* @return {boolean}
|
||||
*/
|
||||
self._is_supported = function() {
|
||||
self._isSupported = function() {
|
||||
|
||||
is_supported = true;
|
||||
|
||||
|
@ -38,7 +38,7 @@ var Audio = (function () {
|
|||
is_supported = false;
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Audio._is_supported', e);
|
||||
Console.error('Audio._isSupported', e);
|
||||
} finally {
|
||||
return is_supported;
|
||||
}
|
||||
|
@ -46,6 +46,57 @@ var Audio = (function () {
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* Append audio DOM code
|
||||
* @private
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._appendDOM = function() {
|
||||
|
||||
try {
|
||||
// If the audio elements aren't yet in the DOM
|
||||
if(!Common.exists('#audio')) {
|
||||
$('body').append(
|
||||
'<div id="audio">' +
|
||||
'<audio id="new-chat" preload="auto" data-duration="2">' +
|
||||
'<source src="' + './sounds/new-chat.mp3' + '" />' +
|
||||
'<source src="' + './sounds/new-chat.oga' + '" />' +
|
||||
'</audio>' +
|
||||
|
||||
'<audio id="receive-message" preload="auto" data-duration="2">' +
|
||||
'<source src="' + './sounds/receive-message.mp3' + '" />' +
|
||||
'<source src="' + './sounds/receive-message.oga' + '" />' +
|
||||
'</audio>' +
|
||||
|
||||
'<audio id="notification" preload="auto" data-duration="2">' +
|
||||
'<source src="' + './sounds/notification.mp3' + '" />' +
|
||||
'<source src="' + './sounds/notification.oga' + '" />' +
|
||||
'</audio>' +
|
||||
|
||||
'<audio id="catch-attention" preload="auto" data-duration="3">' +
|
||||
'<source src="' + './sounds/catch-attention.mp3' + '" />' +
|
||||
'<source src="' + './sounds/catch-attention.oga' + '" />' +
|
||||
'</audio>' +
|
||||
|
||||
'<audio id="incoming-call" preload="auto" data-duration="7">' +
|
||||
'<source src="' + './sounds/incoming-call.mp3' + '" />' +
|
||||
'<source src="' + './sounds/incoming-call.oga' + '" />' +
|
||||
'</audio>' +
|
||||
|
||||
'<audio id="outgoing-call" preload="auto" data-duration="30">' +
|
||||
'<source src="' + './sounds/outgoing-call.mp3' + '" />' +
|
||||
'<source src="' + './sounds/outgoing-call.oga' + '" />' +
|
||||
'</audio>' +
|
||||
'</div>'
|
||||
);
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Audio._appendDOM', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Plays the given sound ID
|
||||
* @public
|
||||
|
@ -58,43 +109,13 @@ var Audio = (function () {
|
|||
repeat = (typeof repeat === 'boolean') ? repeat : false;
|
||||
|
||||
// Not supported?
|
||||
if(!self._is_supported()) {
|
||||
if(!self._isSupported()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the sounds are enabled
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'sounds') === '1') {
|
||||
// If the audio elements aren't yet in the DOM
|
||||
if(!Common.exists('#audio')) {
|
||||
$('body').append(
|
||||
'<div id="audio">' +
|
||||
'<audio id="new-chat" preload="auto" data-duration="2">' +
|
||||
'<source src="' + './sounds/new-chat.mp3' + '" />' +
|
||||
'<source src="' + './sounds/new-chat.oga' + '" />' +
|
||||
'</audio>' +
|
||||
|
||||
'<audio id="receive-message" preload="auto" data-duration="2">' +
|
||||
'<source src="' + './sounds/receive-message.mp3' + '" />' +
|
||||
'<source src="' + './sounds/receive-message.oga' + '" />' +
|
||||
'</audio>' +
|
||||
|
||||
'<audio id="notification" preload="auto" data-duration="2">' +
|
||||
'<source src="' + './sounds/notification.mp3' + '" />' +
|
||||
'<source src="' + './sounds/notification.oga' + '" />' +
|
||||
'</audio>' +
|
||||
|
||||
'<audio id="incoming-call" preload="auto" data-duration="7">' +
|
||||
'<source src="' + './sounds/incoming-call.mp3' + '" />' +
|
||||
'<source src="' + './sounds/incoming-call.oga' + '" />' +
|
||||
'</audio>' +
|
||||
|
||||
'<audio id="outgoing-call" preload="auto" data-duration="30">' +
|
||||
'<source src="' + './sounds/outgoing-call.mp3' + '" />' +
|
||||
'<source src="' + './sounds/outgoing-call.oga' + '" />' +
|
||||
'</audio>' +
|
||||
'</div>'
|
||||
);
|
||||
}
|
||||
self._appendDOM();
|
||||
|
||||
// We play the target sound
|
||||
var audio_raw_sel = $('#audio audio').filter('#' + name);
|
||||
|
@ -146,7 +167,7 @@ var Audio = (function () {
|
|||
|
||||
try {
|
||||
// Not supported?
|
||||
if(!self._is_supported()) {
|
||||
if(!self._isSupported()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,14 +32,17 @@ var Autocompletion = (function () {
|
|||
|
||||
try {
|
||||
// Put the two strings into lower case
|
||||
var sA = a[0].toLowerCase();
|
||||
var sB = b[0].toLowerCase();
|
||||
var sort_a = a[0].toLowerCase();
|
||||
var sort_b = b[0].toLowerCase();
|
||||
|
||||
// Process the sort
|
||||
if(sA > sB)
|
||||
if(sort_a > sort_b) {
|
||||
return 1;
|
||||
if(sA < sB)
|
||||
}
|
||||
|
||||
if(sort_a < sort_b) {
|
||||
return -1;
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Autocompletion.caseInsensitiveSort', e);
|
||||
}
|
||||
|
@ -49,40 +52,51 @@ var Autocompletion = (function () {
|
|||
|
||||
/**
|
||||
* Split a query into its subqueries ready to be used in autocompletion
|
||||
* The function return an array containing two others : the first with subqueries
|
||||
* and the second with remaining parts
|
||||
* For example, if query is "A B C", the subqueries are ["C", "B C", "A B C"] and
|
||||
* the remaining parts are ["A B ", "A ", ""]
|
||||
* @public
|
||||
* @param {string} query
|
||||
* @return {Array}
|
||||
* @return {object}
|
||||
*/
|
||||
self.getSubQueries = function(query) {
|
||||
|
||||
var subqueries = [];
|
||||
var remnants = [];
|
||||
var result = [];
|
||||
|
||||
var queryLastCharPos = query.length - 1;
|
||||
var spaceCounter = 0;
|
||||
for (var i=queryLastCharPos; i>=0; i--) {
|
||||
// Search from the end of the query
|
||||
var iChar = query.charAt(i);
|
||||
if (spaceCounter === 0 && iChar.search(/\s/) === 0) {
|
||||
// the first "local" space was found
|
||||
// add the subquery and its remnant to results
|
||||
subqueries.push(query.slice(i+1));
|
||||
remnants.push(query.slice(0, i+1));
|
||||
spaceCounter++;
|
||||
} else {
|
||||
spaceCounter = 0;
|
||||
try {
|
||||
var subqueries = [];
|
||||
var remnants = [];
|
||||
|
||||
var query_last_char_pos = query.length - 1;
|
||||
var space_counter = 0;
|
||||
var cur_char;
|
||||
|
||||
for(var i = query_last_char_pos; i >= 0; i--) {
|
||||
// Search from the end of the query
|
||||
cur_char = query.charAt(i);
|
||||
|
||||
if(space_counter === 0 && cur_char.search(/\s/) === 0) {
|
||||
// The first "local" space was found
|
||||
// Add the subquery and its remnant to results
|
||||
subqueries.push(query.slice(i+1));
|
||||
remnants.push(query.slice(0, i+1));
|
||||
|
||||
space_counter++;
|
||||
} else {
|
||||
space_counter = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (spaceCounter === 0) {
|
||||
// If the first char of the query is not a space, add the full query to results
|
||||
subqueries.push(query);
|
||||
remnants.push("");
|
||||
|
||||
if(space_counter === 0) {
|
||||
// If the first char of the query is not a space, add the full query to results
|
||||
subqueries.push(query);
|
||||
remnants.push('');
|
||||
}
|
||||
|
||||
result = [subqueries, remnants];
|
||||
} catch(e) {
|
||||
Console.error('Autocompletion.getSubQueries', e);
|
||||
} finally {
|
||||
return result;
|
||||
}
|
||||
|
||||
return [subqueries, remnants];
|
||||
};
|
||||
|
||||
|
||||
|
@ -102,25 +116,37 @@ var Autocompletion = (function () {
|
|||
try {
|
||||
// Replace forbidden characters in regex
|
||||
query = Common.escapeRegex(query);
|
||||
|
||||
// Build an array of regex to use
|
||||
var queryRegExp = [];
|
||||
for (i = 0; i<query.length; i++) {
|
||||
if (query[i] !== null) {
|
||||
queryRegExp.push(new RegExp('(^)' + query[i], 'gi'));
|
||||
var query_reg_exp = [];
|
||||
|
||||
for(i = 0; i < query.length; i++) {
|
||||
if(query[i] !== null) {
|
||||
query_reg_exp.push(
|
||||
new RegExp('(^)' + query[i], 'gi')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Search in the roster
|
||||
var nick, regex;
|
||||
|
||||
$('#' + id + ' .user').each(function() {
|
||||
var nick = $(this).find('.name').text();
|
||||
for (i = 0; i<queryRegExp.length; i++) {
|
||||
var regex = queryRegExp[i];
|
||||
nick = $(this).find('.name').text();
|
||||
|
||||
for(i = 0; i < query_reg_exp.length; i++) {
|
||||
regex = query_reg_exp[i];
|
||||
|
||||
if(nick.match(regex)) {
|
||||
results.push([nick, i]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Sort the array
|
||||
results = results.sort(self.caseInsensitiveSort);
|
||||
results = results.sort(
|
||||
self.caseInsensitiveSort
|
||||
);
|
||||
} catch(e) {
|
||||
Console.error('Autocompletion.process', e);
|
||||
} finally {
|
||||
|
@ -139,7 +165,8 @@ var Autocompletion = (function () {
|
|||
self.reset = function(hash) {
|
||||
|
||||
try {
|
||||
$('#' + hash + ' .message-area').removeAttr('data-autocompletion-pointer').removeAttr('data-autocompletion-query');
|
||||
$('#' + hash + ' .message-area').removeAttr('data-autocompletion-pointer')
|
||||
.removeAttr('data-autocompletion-query');
|
||||
} catch(e) {
|
||||
Console.error('Autocompletion.reset', e);
|
||||
}
|
||||
|
@ -157,36 +184,34 @@ var Autocompletion = (function () {
|
|||
|
||||
try {
|
||||
// Initialize
|
||||
var vSelector = $('#' + hash + ' .message-area');
|
||||
var value = vSelector.val();
|
||||
var message_area_sel = $('#' + hash + ' .message-area');
|
||||
var value = message_area_sel.val();
|
||||
|
||||
if(!value) {
|
||||
self.reset(hash);
|
||||
}
|
||||
|
||||
var query = vSelector.attr('data-autocompletion-query');
|
||||
var query = message_area_sel.attr('data-autocompletion-query');
|
||||
|
||||
if(query === undefined) {
|
||||
// The autocompletion has not been yet launched
|
||||
query = self.getSubQueries(value);
|
||||
vSelector.attr('data-autocompletion-query', JSON.stringify(query));
|
||||
message_area_sel.attr('data-autocompletion-query', JSON.stringify(query));
|
||||
} else {
|
||||
// The autocompletion has already stored a query
|
||||
query = JSON.parse(query);
|
||||
}
|
||||
|
||||
// Get the pointer
|
||||
var pointer = vSelector.attr('data-autocompletion-pointer');
|
||||
var i = 0;
|
||||
|
||||
if(pointer)
|
||||
i = parseInt(pointer);
|
||||
var pointer = message_area_sel.attr('data-autocompletion-pointer');
|
||||
var i = pointer ? parseInt(pointer, 10) : 0;
|
||||
|
||||
// We get the nickname
|
||||
var nickResult = self.process(query[0], hash)[i];
|
||||
var nick_result = self.process(query[0], hash)[i];
|
||||
var nick;
|
||||
if (nickResult !== undefined) {
|
||||
nick = nickResult[0];
|
||||
|
||||
if(nick_result !== undefined) {
|
||||
nick = nick_result[0];
|
||||
}
|
||||
|
||||
// Shit, this is my nick!
|
||||
|
@ -195,21 +220,26 @@ var Autocompletion = (function () {
|
|||
i++;
|
||||
|
||||
// Get the next nick
|
||||
nickResult = self.process(query[0], hash)[i];
|
||||
if (nickResult !== undefined) {
|
||||
nick = nickResult[0];
|
||||
nick_result = self.process(query[0], hash)[i];
|
||||
|
||||
if (nick_result !== undefined) {
|
||||
nick = nick_result[0];
|
||||
}
|
||||
}
|
||||
|
||||
// We quote the nick
|
||||
if((nickResult !== undefined) && (nick !== undefined)) {
|
||||
if((nick_result !== undefined) && (nick !== undefined)) {
|
||||
// Increment
|
||||
i++;
|
||||
var message = query[1][nickResult[1]];
|
||||
Utils.quoteMyNick(hash, nick, message);
|
||||
|
||||
Utils.quoteMyNick(
|
||||
hash,
|
||||
nick,
|
||||
query[1][nick_result[1]]
|
||||
);
|
||||
|
||||
// Put a pointer
|
||||
vSelector.attr('data-autocompletion-pointer', i);
|
||||
message_area_sel.attr('data-autocompletion-pointer', i);
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Autocompletion.create', e);
|
||||
|
|
|
@ -39,8 +39,9 @@ var Avatar = (function () {
|
|||
|
||||
try {
|
||||
// No need to get the avatar, another process is yet running
|
||||
if(Utils.existArrayValue(self.pending, xid))
|
||||
if(Utils.existArrayValue(self.pending, xid)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize: XML data is in one SQL entry, because some browser are sloooow with SQL requests
|
||||
var xml = Common.XMLFromString(
|
||||
|
@ -49,8 +50,9 @@ var Avatar = (function () {
|
|||
var forced = false;
|
||||
|
||||
// Retrieving forced?
|
||||
if($(xml).find('forced').text() == 'true')
|
||||
if($(xml).find('forced').text() == 'true') {
|
||||
forced = true;
|
||||
}
|
||||
|
||||
// No avatar in presence
|
||||
if(!photo && !forced && enabled == 'true') {
|
||||
|
@ -72,8 +74,9 @@ var Avatar = (function () {
|
|||
var updated = false;
|
||||
|
||||
// Process the checksum of the avatar
|
||||
if(checksum == photo || photo == 'forget' || forced)
|
||||
if(checksum == photo || photo == 'forget' || forced) {
|
||||
updated = true;
|
||||
}
|
||||
|
||||
// If the avatar is yet stored and a new retrieving is not needed
|
||||
if(mode == 'cache' && type && binval && checksum && updated) {
|
||||
|
@ -141,8 +144,9 @@ var Avatar = (function () {
|
|||
oChecksum = DataStore.getDB(Connection.desktop_hash, 'checksum', 1);
|
||||
|
||||
// Avoid the "null" value
|
||||
if(!oChecksum)
|
||||
if(!oChecksum) {
|
||||
oChecksum = '';
|
||||
}
|
||||
}
|
||||
|
||||
// vCard not empty?
|
||||
|
@ -151,10 +155,12 @@ var Avatar = (function () {
|
|||
if(handleFrom == Common.getXID()) {
|
||||
// Get the names
|
||||
var names = Name.generateBuddy(iq);
|
||||
var phone_number = find.find('TEL:has(NUMBER):first NUMBER:first').text();
|
||||
|
||||
// Write the values to the database
|
||||
DataStore.setDB(Connection.desktop_hash, 'profile', 'name', names[0]);
|
||||
DataStore.setDB(Connection.desktop_hash, 'profile', 'nick', names[1]);
|
||||
DataStore.setDB(Connection.desktop_hash, 'profile', 'phone', phone_number);
|
||||
}
|
||||
|
||||
// We get the avatar
|
||||
|
@ -170,12 +176,11 @@ var Avatar = (function () {
|
|||
// Enough data
|
||||
else {
|
||||
// No type?
|
||||
if(!aType)
|
||||
if(!aType) {
|
||||
aType = 'image/png';
|
||||
|
||||
// Process the checksum
|
||||
else
|
||||
} else {
|
||||
aChecksum = hex_sha1(Base64.decode(aBinval));
|
||||
}
|
||||
}
|
||||
|
||||
// We display the user avatar
|
||||
|
@ -197,17 +202,19 @@ var Avatar = (function () {
|
|||
// Define a proper checksum
|
||||
var pChecksum = aChecksum;
|
||||
|
||||
if(pChecksum == 'none')
|
||||
if(pChecksum == 'none') {
|
||||
pChecksum = '';
|
||||
}
|
||||
|
||||
// Update our temp. checksum
|
||||
DataStore.setDB(Connection.desktop_hash, 'checksum', 1, pChecksum);
|
||||
|
||||
// Send the stanza
|
||||
if(!Presence.first_sent)
|
||||
if(!Presence.first_sent) {
|
||||
Storage.get(NS_OPTIONS);
|
||||
else if(DataStore.hasPersistent())
|
||||
} else if(DataStore.hasPersistent()) {
|
||||
Presence.sendActions(pChecksum);
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Avatar.handle', e);
|
||||
|
@ -255,10 +262,11 @@ var Avatar = (function () {
|
|||
var code = '<img class="avatar" src="';
|
||||
|
||||
// If the avatar exists
|
||||
if((type != 'none') && (binval != 'none'))
|
||||
if((type != 'none') && (binval != 'none')) {
|
||||
code += 'data:' + type + ';base64,' + binval;
|
||||
else
|
||||
} else {
|
||||
code += './images/others/default-avatar.png';
|
||||
}
|
||||
|
||||
code += '" alt="" />';
|
||||
|
||||
|
|
|
@ -20,6 +20,137 @@ var Board = (function () {
|
|||
var self = {};
|
||||
|
||||
|
||||
/* Contants */
|
||||
self.NOTIFICATION = (window.Notification || window.mozNotification || window.webkitNotification);
|
||||
|
||||
|
||||
/**
|
||||
* Generate board info message
|
||||
* @private
|
||||
* @param {string} id
|
||||
* @return {string}
|
||||
*/
|
||||
self._generateBoardInfo = function(id) {
|
||||
|
||||
var text = null;
|
||||
|
||||
try {
|
||||
switch(id) {
|
||||
// Password change
|
||||
case 1:
|
||||
text = Common._e("Your password has been changed, now you can connect to your account with your new login data.");
|
||||
|
||||
break;
|
||||
|
||||
// Account deletion
|
||||
case 2:
|
||||
text = Common._e("Your XMPP account has been removed, bye!");
|
||||
|
||||
break;
|
||||
|
||||
// Account logout
|
||||
case 3:
|
||||
text = Common._e("You have been logged out of your XMPP account, have a nice day!");
|
||||
|
||||
break;
|
||||
|
||||
// Groupchat join
|
||||
case 4:
|
||||
text = Common._e("The room you tried to join doesn't seem to exist.");
|
||||
|
||||
break;
|
||||
|
||||
// Groupchat removal
|
||||
case 5:
|
||||
text = Common._e("The groupchat has been removed.");
|
||||
|
||||
break;
|
||||
|
||||
// Non-existant groupchat user
|
||||
case 6:
|
||||
text = Common._e("The user that you want to reach is not present in the room.");
|
||||
|
||||
break;
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Board._generateBoardInfo', e);
|
||||
} finally {
|
||||
return text;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Generate board error message
|
||||
* @private
|
||||
* @param {string} id
|
||||
* @return {string}
|
||||
*/
|
||||
self._generateBoardError = function(id) {
|
||||
|
||||
var text = null;
|
||||
|
||||
try {
|
||||
switch(id) {
|
||||
// Custom error
|
||||
case 1:
|
||||
text = '<b>' + Common._e("Error") + '</b> » <span></span>';
|
||||
|
||||
break;
|
||||
|
||||
// Network error
|
||||
case 2:
|
||||
text = Common._e("Jappix has been interrupted by a network issue, a bug or bad login (check that you entered the right credentials), sorry for the inconvenience.");
|
||||
|
||||
break;
|
||||
|
||||
// List retrieving error
|
||||
case 3:
|
||||
text = Common._e("The element list on this server could not be obtained!");
|
||||
|
||||
break;
|
||||
|
||||
// Attaching error
|
||||
case 4:
|
||||
text = Common.printf(Common._e("An error occured while uploading your file: maybe it is too big (%s maximum) or forbidden!"), JAPPIX_MAX_UPLOAD);
|
||||
|
||||
break;
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Board._generateBoardError', e);
|
||||
} finally {
|
||||
return text;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Attaches board events
|
||||
* @private
|
||||
* @param {object} board_sel
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._attachEvents = function(board_sel) {
|
||||
|
||||
try {
|
||||
board_sel.click(function() {
|
||||
self.closeThis(this);
|
||||
});
|
||||
|
||||
board_sel.oneTime('5s', function() {
|
||||
self.closeThis(this);
|
||||
});
|
||||
|
||||
board_sel.slideDown();
|
||||
} catch(e) {
|
||||
Console.error('Board._attachEvents', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a board panel
|
||||
* @public
|
||||
|
@ -35,93 +166,25 @@ var Board = (function () {
|
|||
|
||||
// Info
|
||||
if(type == 'info') {
|
||||
switch(id) {
|
||||
// Password change
|
||||
case 1:
|
||||
text = Common._e("Your password has been changed, now you can connect to your account with your new login data.");
|
||||
|
||||
break;
|
||||
|
||||
// Account deletion
|
||||
case 2:
|
||||
text = Common._e("Your XMPP account has been removed, bye!");
|
||||
|
||||
break;
|
||||
|
||||
// Account logout
|
||||
case 3:
|
||||
text = Common._e("You have been logged out of your XMPP account, have a nice day!");
|
||||
|
||||
break;
|
||||
|
||||
// Groupchat join
|
||||
case 4:
|
||||
text = Common._e("The room you tried to join doesn't seem to exist.");
|
||||
|
||||
break;
|
||||
|
||||
// Groupchat removal
|
||||
case 5:
|
||||
text = Common._e("The groupchat has been removed.");
|
||||
|
||||
break;
|
||||
|
||||
// Non-existant groupchat user
|
||||
case 6:
|
||||
text = Common._e("The user that you want to reach is not present in the room.");
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Error
|
||||
else {
|
||||
switch(id) {
|
||||
// Custom error
|
||||
case 1:
|
||||
text = '<b>' + Common._e("Error") + '</b> » <span></span>';
|
||||
|
||||
break;
|
||||
|
||||
// Network error
|
||||
case 2:
|
||||
text = Common._e("Jappix has been interrupted by a network issue, a bug or bad login (check that you entered the right credentials), sorry for the inconvenience.");
|
||||
|
||||
break;
|
||||
|
||||
// List retrieving error
|
||||
case 3:
|
||||
text = Common._e("The element list on this server could not be obtained!");
|
||||
|
||||
break;
|
||||
|
||||
// Attaching error
|
||||
case 4:
|
||||
text = Common.printf(Common._e("An error occured while uploading your file: maybe it is too big (%s maximum) or forbidden!"), JAPPIX_MAX_UPLOAD);
|
||||
|
||||
break;
|
||||
}
|
||||
text = self._generateBoardInfo(id);
|
||||
} else {
|
||||
text = self._generateBoardError(id);
|
||||
}
|
||||
|
||||
// No text?
|
||||
if(!text)
|
||||
if(!text) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Append the content
|
||||
$('#board').append('<div class="one-board ' + type + '" data-id="' + id + '">' + text + '</div>');
|
||||
$('#board').append(
|
||||
'<div class="one-board ' + type + '" data-id="' + id + '">' + text + '</div>'
|
||||
);
|
||||
|
||||
// Events (click and auto-hide)
|
||||
$('#board .one-board.' + type + '[data-id="' + id + '"]')
|
||||
|
||||
.click(function() {
|
||||
self.closeThis(this);
|
||||
})
|
||||
|
||||
.oneTime('5s', function() {
|
||||
self.closeThis(this);
|
||||
})
|
||||
|
||||
.slideDown();
|
||||
self._attachEvents(
|
||||
$('#board .one-board.' + type + '[data-id="' + id + '"]')
|
||||
);
|
||||
|
||||
return true;
|
||||
} catch(e) {
|
||||
|
@ -235,7 +298,7 @@ var Board = (function () {
|
|||
|
||||
try {
|
||||
// Cannot process?
|
||||
if(Common.isFocused() || !content || !(window.webkitNotifications || window.Notification)) {
|
||||
if(Common.isFocused() || !content || !self.NOTIFICATION) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -248,11 +311,13 @@ var Board = (function () {
|
|||
var avatar_xml = Common.XMLFromString(
|
||||
DataStore.getPersistent('global', 'avatar', xid)
|
||||
);
|
||||
|
||||
var avatar_type = $(avatar_xml).find('type').text() || 'image/png';
|
||||
var avatar_binval = $(avatar_xml).find('binval').text();
|
||||
|
||||
if(avatar_binval && avatar_type)
|
||||
if(avatar_binval && avatar_type) {
|
||||
icon = 'data:' + avatar_type + ';base64,' + avatar_binval;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -261,8 +326,17 @@ var Board = (function () {
|
|||
title = Common._e("New event!");
|
||||
}
|
||||
|
||||
// Click callback
|
||||
var cb_click_fn = function() {
|
||||
// Create notification
|
||||
var notification = new self.NOTIFICATION(title, {
|
||||
dir: 'auto',
|
||||
lang: '',
|
||||
body: content,
|
||||
tag: type,
|
||||
icon: icon
|
||||
});
|
||||
|
||||
// Click event
|
||||
notification.onclick = function() {
|
||||
// Click action?
|
||||
switch(type) {
|
||||
case 'chat':
|
||||
|
@ -281,53 +355,17 @@ var Board = (function () {
|
|||
window.focus();
|
||||
|
||||
// Remove notification
|
||||
this.cancel();
|
||||
this.close();
|
||||
};
|
||||
|
||||
// Check for notification permission
|
||||
try {
|
||||
if(Notification.permission == 'granted' || Notification.permission === undefined) {
|
||||
var notification = new Notification(title, {
|
||||
dir: 'auto',
|
||||
lang: '',
|
||||
body: content,
|
||||
tag: type,
|
||||
icon: icon
|
||||
});
|
||||
|
||||
notification.onclick = cb_click_fn;
|
||||
// Show event
|
||||
notification.onshow = function() {
|
||||
setTimeout(function() {
|
||||
notification.close();
|
||||
}, 10000);
|
||||
};
|
||||
|
||||
setTimeout(function() {
|
||||
notification.close();
|
||||
}, 10000);
|
||||
|
||||
if(notification.permission == 'granted') {
|
||||
return notification;
|
||||
}
|
||||
}
|
||||
} catch(_e) {
|
||||
if(window.webkitNotifications.checkPermission() === 0) {
|
||||
// Create notification
|
||||
var notification = window.webkitNotifications.createNotification(icon, title, content);
|
||||
|
||||
// Auto-hide after a while
|
||||
notification.ondisplay = function(event) {
|
||||
setTimeout(function() {
|
||||
event.currentTarget.cancel();
|
||||
}, 10000);
|
||||
};
|
||||
|
||||
// Click event
|
||||
notification.onclick = cb_click_fn;
|
||||
|
||||
// Show notification
|
||||
notification.show();
|
||||
|
||||
return notification;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return notification;
|
||||
} catch(e) {
|
||||
Console.error('Board.quick', e);
|
||||
}
|
||||
|
@ -343,21 +381,7 @@ var Board = (function () {
|
|||
self.quickPermission = function() {
|
||||
|
||||
try {
|
||||
try {
|
||||
// W3C Notification API (still a draft!)
|
||||
if(Notification.permission !== 'granted') {
|
||||
// Ask for permission
|
||||
Notification.requestPermission();
|
||||
}
|
||||
} catch (_e) {
|
||||
// WebKit Notification API (fallback)
|
||||
if(!window.webkitNotifications || (window.webkitNotifications.checkPermission() === 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ask for permission
|
||||
window.webkitNotifications.requestPermission();
|
||||
}
|
||||
self.NOTIFICATION.requestPermission();
|
||||
} catch(e) {
|
||||
Console.error('Board.quickPermission', e);
|
||||
}
|
||||
|
@ -376,8 +400,9 @@ var Board = (function () {
|
|||
// Fires quickPermission() on document click
|
||||
$(document).click(function() {
|
||||
// Ask for permission to use quick boards
|
||||
if((typeof con != 'undefined') && con.connected())
|
||||
if((typeof con != 'undefined') && con.connected()) {
|
||||
self.quickPermission();
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Board.launch', e);
|
||||
|
|
|
@ -31,6 +31,7 @@ var Bubble = (function () {
|
|||
// Destroy all the elements
|
||||
$('.bubble.hidable:visible').hide();
|
||||
$('.bubble.removable').remove();
|
||||
|
||||
$('body').off('click');
|
||||
} catch(e) {
|
||||
Console.error('Bubble.close', e);
|
||||
|
@ -53,8 +54,9 @@ var Bubble = (function () {
|
|||
// Hidable bubbles special things
|
||||
if($(selector).is('.hidable')) {
|
||||
// This bubble is yet displayed? So abort!
|
||||
if($(selector).is(':visible'))
|
||||
if($(selector).is(':visible')) {
|
||||
return self.close();
|
||||
}
|
||||
|
||||
// Close all the bubbles
|
||||
self.close();
|
||||
|
@ -66,8 +68,9 @@ var Bubble = (function () {
|
|||
// Removable bubbles special things
|
||||
else {
|
||||
// This bubble is yet added? So abort!
|
||||
if(Common.exists(selector))
|
||||
if(Common.exists(selector)) {
|
||||
return self.close();
|
||||
}
|
||||
|
||||
// Close all the bubbles
|
||||
self.close();
|
||||
|
@ -78,8 +81,9 @@ var Bubble = (function () {
|
|||
var target = evt.target;
|
||||
|
||||
// If this is a click away from a bubble
|
||||
if(!$(target).parents('.ibubble').size())
|
||||
if(!$(target).parents('.ibubble').size()) {
|
||||
self.close();
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Bubble.show', e);
|
||||
|
|
972
source/app/javascripts/call.js
Normal file
|
@ -0,0 +1,972 @@
|
|||
/*
|
||||
|
||||
Jappix - An open social platform
|
||||
These are the call common management functions
|
||||
|
||||
-------------------------------------------------
|
||||
|
||||
License: AGPL
|
||||
Author: Valérian Saliou
|
||||
|
||||
*/
|
||||
|
||||
// Bundle
|
||||
var Call = (function() {
|
||||
|
||||
/**
|
||||
* Alias of this
|
||||
* @private
|
||||
*/
|
||||
var self = {};
|
||||
|
||||
|
||||
/* Variables */
|
||||
self._start_stamp = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Provides an adapter to the JSJaCJingle console implementation which is different
|
||||
* @private
|
||||
* @return {object}
|
||||
*/
|
||||
self._consoleAdapter = (function() {
|
||||
|
||||
/**
|
||||
* Alias of this
|
||||
* @private
|
||||
*/
|
||||
var _console = {};
|
||||
|
||||
|
||||
/**
|
||||
* Console logging interface (adapted)
|
||||
* @public
|
||||
* @param {string} message
|
||||
* @param {number} loglevel
|
||||
* @return {undefined}
|
||||
*/
|
||||
_console.log = function(message, loglevel) {
|
||||
|
||||
try {
|
||||
if(!message) {
|
||||
throw 'No message passed to console adapter!';
|
||||
}
|
||||
|
||||
switch(loglevel) {
|
||||
case 0:
|
||||
Console.warn(message); break;
|
||||
case 1:
|
||||
Console.error(message); break;
|
||||
case 2:
|
||||
Console.info(message); break;
|
||||
case 4:
|
||||
Console.debug(message); break;
|
||||
default:
|
||||
Console.log(message);
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Call._consoleAdapter.log', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return sub-class scope
|
||||
*/
|
||||
return _console;
|
||||
|
||||
})();
|
||||
|
||||
|
||||
/**
|
||||
* Initializes Jingle router
|
||||
* @public
|
||||
* @return {undefined}
|
||||
*/
|
||||
self.init = function() {
|
||||
|
||||
try {
|
||||
// Listen for incoming Jingle/Muji packet
|
||||
JSJaCJingle.listen({
|
||||
connection: con,
|
||||
debug: self._consoleAdapter,
|
||||
|
||||
// TODO: setting a fallback fucks up some calls...
|
||||
// fallback: './server/jingle.php',
|
||||
|
||||
single_initiate: function(stanza) {
|
||||
try {
|
||||
// Already in a call?
|
||||
if(self.is_ongoing()) {
|
||||
// Try to restore SID there
|
||||
var stanza_id = stanza.getID();
|
||||
var sid = null;
|
||||
|
||||
if(stanza_id) {
|
||||
var stanza_id_split = stanza_id.split('_');
|
||||
sid = stanza_id_split[1];
|
||||
}
|
||||
|
||||
// Build a temporary Jingle session
|
||||
var jingle_close = new JSJaCJingle.session(
|
||||
JSJAC_JINGLE_SESSION_SINGLE,
|
||||
{
|
||||
to: stanza.getFrom(),
|
||||
debug: JSJaCJingleStorage.get_debug()
|
||||
}
|
||||
);
|
||||
|
||||
if(sid) {
|
||||
jingle_close._set_sid(sid);
|
||||
}
|
||||
|
||||
jingle_close.terminate(JSJAC_JINGLE_REASON_BUSY);
|
||||
|
||||
Console.warn('session_initiate_success', 'Dropped incoming call because already in a call.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var xid = Common.fullXID(Common.getStanzaFrom(stanza));
|
||||
|
||||
Console.info('Incoming call from: ' + xid);
|
||||
|
||||
// Session values
|
||||
Jingle.receive(xid, stanza);
|
||||
} catch(e) {
|
||||
Console.error('Call.init[single_initiate]', e);
|
||||
}
|
||||
},
|
||||
|
||||
// Receive a multiparty (Muji) call
|
||||
muji_invite: function(stanza, args) {
|
||||
try {
|
||||
if(!self.is_ongoing()) {
|
||||
// Session values
|
||||
Muji.receive(args, stanza);
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Call.init[muji_invite]', e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Enable Jingle/Muji UI elements if plugin could start
|
||||
if(JSJAC_JINGLE_AVAILABLE) {
|
||||
$('.jingle-hidable, .muji-hidable').show();
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Call.init', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Opens the call interface
|
||||
* @public
|
||||
* @return {undefined}
|
||||
*/
|
||||
self.open = function() {
|
||||
|
||||
try {
|
||||
if(Jingle.in_call()) {
|
||||
Jingle.open();
|
||||
} else if(Muji.in_call()) {
|
||||
Muji.open();
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Call.open', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Stops current call
|
||||
* @public
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.stop = function() {
|
||||
|
||||
try {
|
||||
Jingle.stop();
|
||||
Muji.stop();
|
||||
} catch(e) {
|
||||
Console.error('Call.stop', e);
|
||||
} finally {
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Mutes current call
|
||||
* @public
|
||||
* @param {object} session
|
||||
* @param {object} controls
|
||||
* @return {undefined}
|
||||
*/
|
||||
self.mute = function(session, controls) {
|
||||
|
||||
try {
|
||||
if(session) {
|
||||
// Toggle interface buttons
|
||||
controls.filter('.mute').hide();
|
||||
controls.filter('.unmute').show();
|
||||
|
||||
// Actually mute audio stream
|
||||
if(session.get_mute(JSJAC_JINGLE_MEDIA_AUDIO) === false) {
|
||||
session.mute(JSJAC_JINGLE_MEDIA_AUDIO);
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Call.mute', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Unmutes current call
|
||||
* @public
|
||||
* @param {object} session
|
||||
* @param {object} controls
|
||||
* @return {undefined}
|
||||
*/
|
||||
self.unmute = function(session, controls) {
|
||||
|
||||
try {
|
||||
if(session) {
|
||||
controls.filter('.unmute').hide();
|
||||
controls.filter('.mute').show();
|
||||
|
||||
if(session.get_mute(JSJAC_JINGLE_MEDIA_AUDIO) === true) {
|
||||
session.unmute(JSJAC_JINGLE_MEDIA_AUDIO);
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Call.mute', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks whether user is in call or not
|
||||
* @public
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.is_ongoing = function() {
|
||||
|
||||
is_ongoing = false;
|
||||
|
||||
try {
|
||||
is_ongoing = (Jingle.in_call() === true || Muji.in_call() === true);
|
||||
} catch(e) {
|
||||
Console.error('Call.is_ongoing', e);
|
||||
} finally {
|
||||
return is_ongoing;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the given call SID is the same as the current call's one
|
||||
* @public
|
||||
* @param {object} session
|
||||
* @param {object} compare_session
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.is_same_sid = function(session, compare_session) {
|
||||
|
||||
is_same = false;
|
||||
|
||||
try {
|
||||
if(compare_session && session &&
|
||||
compare_session.get_sid() === session.get_sid()) {
|
||||
is_same = true;
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Call.is_same_sid', e);
|
||||
} finally {
|
||||
return is_same;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns if current call is audio
|
||||
* @public
|
||||
* @param {object} session
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.is_audio = function(session) {
|
||||
|
||||
audio = false;
|
||||
|
||||
try {
|
||||
if(session && session.get_media() === JSJAC_JINGLE_MEDIA_AUDIO) {
|
||||
audio = true;
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Call.is_audio', e);
|
||||
} finally {
|
||||
return audio;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns if current call is video
|
||||
* @public
|
||||
* @param {object} session
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.is_video = function(session) {
|
||||
|
||||
video = false;
|
||||
|
||||
try {
|
||||
if(session && session.get_media() === JSJAC_JINGLE_MEDIA_VIDEO) {
|
||||
video = true;
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Call.is_video', e);
|
||||
} finally {
|
||||
return video;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the Muji session as started
|
||||
* @public
|
||||
* @param {string} mode
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.start_session = function(mode) {
|
||||
|
||||
try {
|
||||
if(!(mode in JSJAC_JINGLE_MEDIAS)) {
|
||||
throw 'Unknown mode: ' + (mode || 'none');
|
||||
}
|
||||
|
||||
var call_tool_sel = $('#top-content .tools.call');
|
||||
|
||||
call_tool_sel.removeClass('audio video active');
|
||||
call_tool_sel.addClass('streaming').addClass(mode);
|
||||
|
||||
Console.info('Call session successfully started, mode: ' + (mode || 'none'));
|
||||
} catch(e) {
|
||||
Console.error('Call.start_session', e);
|
||||
} finally {
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Set the Jingle session as stopped
|
||||
* @public
|
||||
* @param {string} mode
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.stop_session = function() {
|
||||
|
||||
try {
|
||||
$('#top-content .tools.call').removeClass('audio video active streaming');
|
||||
|
||||
Console.info('Call session successfully stopped');
|
||||
} catch(e) {
|
||||
Console.error('Call.stop_session', e);
|
||||
} finally {
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Generates ICE servers configuration
|
||||
* @public
|
||||
* @return {object}
|
||||
*/
|
||||
self.generate_ice_servers = function() {
|
||||
|
||||
ice_servers = {
|
||||
stun: [],
|
||||
turn: []
|
||||
};
|
||||
|
||||
try {
|
||||
if(HOST_STUN) {
|
||||
ice_servers.stun.push({
|
||||
'host': HOST_STUN
|
||||
});
|
||||
}
|
||||
|
||||
if(HOST_TURN) {
|
||||
ice_servers.turn.push({
|
||||
'host': HOST_TURN,
|
||||
'username': HOST_TURN_USERNAME,
|
||||
'credential': HOST_TURN_PASSWORD
|
||||
});
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Call.generate_ice_servers', e);
|
||||
} finally {
|
||||
return is_ongoing;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the notification map (based on call type)
|
||||
* @private
|
||||
* @param {string} call_type
|
||||
* @return {object}
|
||||
*/
|
||||
self._get_notify_map = function(call_type) {
|
||||
|
||||
var map = {};
|
||||
|
||||
try {
|
||||
switch(call_type) {
|
||||
case JSJAC_JINGLE_SESSION_SINGLE:
|
||||
map = Jingle._notify_map(); break;
|
||||
case JSJAC_JINGLE_SESSION_MUJI:
|
||||
map = Muji._notify_map(); break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Call._get_notify_map', e);
|
||||
} finally {
|
||||
return map;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Notify for something related to calls
|
||||
* @public
|
||||
* @param {string} call_type
|
||||
* @param {string} xid
|
||||
* @param {string} type
|
||||
* @param {string} mode
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.notify = function(call_type, xid, type, mode, sender_xid) {
|
||||
|
||||
try {
|
||||
sender_xid = sender_xid || xid;
|
||||
|
||||
// Notification data map
|
||||
var map = self._get_notify_map(call_type);
|
||||
|
||||
if(!(type in map)) {
|
||||
throw 'Notification type not recognized!';
|
||||
}
|
||||
|
||||
// Selectors
|
||||
var call_tools_all_sel = $('#top-content .tools-all:has(.tools.call)');
|
||||
var call_tool_sel = call_tools_all_sel.find('.tools.call');
|
||||
var call_content_sel = call_tools_all_sel.find('.call-content');
|
||||
var call_subitem_sel = call_content_sel.find('.tools-content-subitem');
|
||||
|
||||
// Generate proper full name
|
||||
var fullname;
|
||||
|
||||
if(call_type === JSJAC_JINGLE_SESSION_MUJI && sender_xid === Common.getXID()) {
|
||||
fullname = Common._e("Conference call");
|
||||
} else {
|
||||
fullname = Name.getBuddy(sender_xid).htmlEnc();
|
||||
}
|
||||
|
||||
// Generate buttons code
|
||||
var buttons_html = '';
|
||||
var i = 0;
|
||||
|
||||
if(typeof map[type].buttons === 'object') {
|
||||
$.each(map[type].buttons, function(button, attrs) {
|
||||
buttons_html += '<a class="reply-button ' + button + ' ' + attrs.color + ' ' + (!(i++) ? 'first' : '') + '" data-action="' + button + '">' + attrs.text + '</a>';
|
||||
});
|
||||
}
|
||||
|
||||
// Append notification to DOM
|
||||
call_subitem_sel.html(
|
||||
'<div class="call-notify notify-' + type + ' ' + hex_md5(sender_xid) + '" data-type="' + type + '" data-xid="' + Common.encodeQuotes(xid) + '">' +
|
||||
'<div class="avatar-pane">' +
|
||||
'<div class="avatar-container">' +
|
||||
'<img class="avatar" src="' + './images/others/default-avatar.png' + '" alt="" />' +
|
||||
'</div>' +
|
||||
|
||||
'<span class="icon call-images"></span>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="notification-content">' +
|
||||
'<span class="fullname">' + fullname + '</span>' +
|
||||
'<span class="text">' + map[type].text + '</span>' +
|
||||
|
||||
'<div class="reply-buttons">' + buttons_html + '</div>' +
|
||||
'</div>' +
|
||||
'</div>'
|
||||
);
|
||||
|
||||
// Apply user avatar
|
||||
Avatar.get(sender_xid, 'cache', 'true', 'forget');
|
||||
|
||||
// Apply button events
|
||||
if(typeof map[type].buttons === 'object') {
|
||||
$.each(map[type].buttons, function(button, attrs) {
|
||||
call_tools_all_sel.find('a.reply-button[data-action="' + button + '"]').click(function() {
|
||||
try {
|
||||
// Remove notification
|
||||
self._unnotify(xid);
|
||||
|
||||
// Execute callback, if any
|
||||
if(typeof attrs.cb === 'function') {
|
||||
attrs.cb(xid, mode);
|
||||
}
|
||||
|
||||
Console.info('Closed call notification drawer');
|
||||
} catch(e) {
|
||||
Console.error('Call.notify[async]', e);
|
||||
} finally {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Enable notification box!
|
||||
call_tool_sel.addClass('active');
|
||||
|
||||
// Open notification box!
|
||||
call_content_sel.show();
|
||||
} catch(e) {
|
||||
Console.error('Call.notify', e);
|
||||
} finally {
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Remove notification
|
||||
* @private
|
||||
* @return {boolean}
|
||||
*/
|
||||
self._unnotify = function() {
|
||||
|
||||
try {
|
||||
// Selectors
|
||||
var call_tools_all_sel = $('#top-content .tools-all:has(.tools.call)');
|
||||
var call_tool_sel = call_tools_all_sel.find('.tools.call');
|
||||
var call_content_sel = call_tools_all_sel.find('.call-content');
|
||||
var call_subitem_sel = call_content_sel.find('.tools-content-subitem');
|
||||
|
||||
// Close & disable notification box
|
||||
call_content_sel.hide();
|
||||
call_subitem_sel.empty();
|
||||
call_tool_sel.removeClass('active');
|
||||
|
||||
// Stop all sounds
|
||||
Audio.stop('incoming-call');
|
||||
Audio.stop('outgoing-call');
|
||||
} catch(e) {
|
||||
Console.error('Call._unnotify', e);
|
||||
} finally {
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Processes the video elements size
|
||||
* @private
|
||||
* @param {object} screen
|
||||
* @param {object} video
|
||||
* @return {object}
|
||||
*/
|
||||
self._process_size = function(screen, video) {
|
||||
|
||||
try {
|
||||
if(!(typeof screen === 'object' && typeof video === 'object')) {
|
||||
throw 'Invalid object passed, aborting!';
|
||||
}
|
||||
|
||||
// Get the intrinsic size of the video
|
||||
var video_w = video[0].videoWidth || video.width();
|
||||
var video_h = video[0].videoHeight || video.height();
|
||||
|
||||
// Get the screen size of the video
|
||||
var screen_w = screen.width();
|
||||
var screen_h = screen.height();
|
||||
|
||||
// Process resize ratios (2 cases)
|
||||
var r_1 = screen_h / video_h;
|
||||
var r_2 = screen_w / video_w;
|
||||
|
||||
// Process resized video sizes
|
||||
var video_w_1 = video_w * r_1;
|
||||
var video_h_1 = video_h * r_1;
|
||||
|
||||
var video_w_2 = video_w * r_2;
|
||||
var video_h_2 = video_h * r_2;
|
||||
|
||||
// DOM view modifiers
|
||||
var dom_width = 'auto';
|
||||
var dom_height = 'auto';
|
||||
var dom_left = 0;
|
||||
var dom_top = 0;
|
||||
|
||||
// Landscape/Portrait/Equal container?
|
||||
if(video_w > video_h || (video_h == video_w && screen_w < screen_h)) {
|
||||
// Not sufficient?
|
||||
if(video_w_1 < screen_w) {
|
||||
dom_width = screen_w + 'px';
|
||||
dom_top = -1 * (video_h_2 - screen_h) / 2;
|
||||
} else {
|
||||
dom_height = screen_h + 'px';
|
||||
dom_left = -1 * (video_w_1 - screen_w) / 2;
|
||||
}
|
||||
} else if(video_h > video_w || (video_h == video_w && screen_w > screen_h)) {
|
||||
// Not sufficient?
|
||||
if(video_h_1 < screen_h) {
|
||||
dom_height = screen_h + 'px';
|
||||
dom_left = -1 * (video_w_1 - screen_w) / 2;
|
||||
} else {
|
||||
dom_width = screen_w + 'px';
|
||||
dom_top = -1 * (video_h_2 - screen_h) / 2;
|
||||
}
|
||||
} else if(screen_w == screen_h) {
|
||||
dom_width = screen_w + 'px';
|
||||
dom_height = screen_h + 'px';
|
||||
}
|
||||
|
||||
return {
|
||||
width : dom_width,
|
||||
height : dom_height,
|
||||
left : dom_left,
|
||||
top : dom_top
|
||||
};
|
||||
} catch(e) {
|
||||
Console.error('Call._process_size', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adapts the local video view
|
||||
* @public
|
||||
* @param {object} local_sel
|
||||
* @return {undefined}
|
||||
*/
|
||||
self.adapt_local = function(local_sel) {
|
||||
|
||||
try {
|
||||
var local_video_sel = local_sel.find('video');
|
||||
|
||||
// Process new sizes
|
||||
var sizes = Call._process_size(
|
||||
local_sel,
|
||||
local_video_sel
|
||||
);
|
||||
|
||||
// Apply new sizes
|
||||
local_video_sel.css({
|
||||
'height': sizes.height,
|
||||
'width': sizes.width,
|
||||
'margin-top': sizes.top,
|
||||
'margin-left': sizes.left
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Call.adapt_local', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adapts the remote video view
|
||||
* @public
|
||||
* @param {object} videobox_sel
|
||||
* @return {undefined}
|
||||
*/
|
||||
self.adapt_remote = function(videobox_sel) {
|
||||
|
||||
try {
|
||||
var remote_video_sel, sizes;
|
||||
|
||||
videobox_sel.find('.remote_video').each(function() {
|
||||
remote_video_sel = $(this).find('video');
|
||||
|
||||
if(remote_video_sel.size()) {
|
||||
// Process new sizes
|
||||
sizes = Call._process_size(
|
||||
$(this),
|
||||
remote_video_sel
|
||||
);
|
||||
|
||||
// Apply new sizes
|
||||
remote_video_sel.css({
|
||||
'height': sizes.height,
|
||||
'width': sizes.width,
|
||||
'margin-top': sizes.top,
|
||||
'margin-left': sizes.left
|
||||
});
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Call.adapt_remote', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Start call elpsed time counter
|
||||
* @public
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.start_counter = function() {
|
||||
|
||||
try {
|
||||
// Initialize counter
|
||||
self.stop_counter();
|
||||
self._start_stamp = DateUtils.getTimeStamp();
|
||||
self._fire_clock();
|
||||
|
||||
// Fire it every second
|
||||
$('#top-content .tools.call .counter').everyTime('1s', self._fire_clock);
|
||||
|
||||
Console.info('Call counter started');
|
||||
} catch(e) {
|
||||
Console.error('Call.start_counter', e);
|
||||
} finally {
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Stop call elpsed time counter
|
||||
* @public
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.stop_counter = function() {
|
||||
|
||||
try {
|
||||
// Reset stamp storage
|
||||
self._start_stamp = 0;
|
||||
|
||||
// Reset counter
|
||||
var counter_sel = $('#top-content .tools.call .counter');
|
||||
var default_count = counter_sel.attr('data-default');
|
||||
|
||||
counter_sel.stopTime();
|
||||
|
||||
$('#top-content .tools.call .counter').text(default_count);
|
||||
$('#jingle, #muji').find('.elapsed').text(default_count);
|
||||
|
||||
Console.info('Call counter stopped');
|
||||
} catch(e) {
|
||||
Console.error('Call.stop_counter', e);
|
||||
} finally {
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Fires the counter clock (once more)
|
||||
* @private
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._fire_clock = function() {
|
||||
|
||||
try {
|
||||
// Process updated time
|
||||
var count = DateUtils.difference(
|
||||
DateUtils.getTimeStamp(),
|
||||
self._start_stamp
|
||||
);
|
||||
|
||||
if(count.getHours()) {
|
||||
count = count.toString('H:mm:ss');
|
||||
} else {
|
||||
count = count.toString('mm:ss');
|
||||
}
|
||||
|
||||
// Display updated counter
|
||||
$('#top-content .tools.call .counter').text(count);
|
||||
$('#jingle, #muji').find('.elapsed').text(count);
|
||||
} catch(e) {
|
||||
Console.error('Call._fire_clock', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Destroy the call interface
|
||||
* @public
|
||||
* @return {undefined}
|
||||
*/
|
||||
self.destroy_interface = function(container_sel) {
|
||||
|
||||
try {
|
||||
container_sel.stopTime();
|
||||
container_sel.find('*').stopTime();
|
||||
|
||||
container_sel.remove();
|
||||
} catch(e) {
|
||||
Console.error('Call.destroy_interface', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Show the call interface
|
||||
* @public
|
||||
* @param {object} manager
|
||||
* @param {object} call_sel
|
||||
* @param {object} video_container_sel
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.show_interface = function(manager, call_sel, video_container_sel) {
|
||||
|
||||
try {
|
||||
if(manager.in_call()) {
|
||||
call_sel.filter(':hidden').show();
|
||||
|
||||
// Launch back some events
|
||||
video_container_sel.mousemove();
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Call.show_interface', e);
|
||||
} finally {
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Hide the call interface
|
||||
* @public
|
||||
* @param {object} call_sel
|
||||
* @param {object} video_container_sel
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.hide_interface = function(call_sel, video_container_sel) {
|
||||
|
||||
try {
|
||||
call_sel.filter(':visible').hide();
|
||||
|
||||
// Reset some events
|
||||
video_container_sel.find('.topbar').stopTime().hide();
|
||||
} catch(e) {
|
||||
Console.error('Call.hide_interface', e);
|
||||
} finally {
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Attaches interface events
|
||||
* @public
|
||||
* @param {object} manager
|
||||
* @param {object} call_sel
|
||||
* @param {object} video_container_sel
|
||||
* @return {undefined}
|
||||
*/
|
||||
self.events_interface = function(manager, call_sel, video_container_sel) {
|
||||
|
||||
try {
|
||||
call_sel.everyTime(50, function() {
|
||||
manager._adapt();
|
||||
});
|
||||
|
||||
// Close interface on click on semi-transparent background
|
||||
call_sel.click(function(evt) {
|
||||
try {
|
||||
// Click on lock background?
|
||||
if($(evt.target).is('.lock')) {
|
||||
return manager._hide_interface();
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Call.events_interface[async]', e);
|
||||
}
|
||||
});
|
||||
|
||||
// Click on a control or action button
|
||||
call_sel.find('.topbar').find('.controls a, .actions a').click(function() {
|
||||
try {
|
||||
switch($(this).data('type')) {
|
||||
case 'close':
|
||||
manager._hide_interface(); break;
|
||||
case 'stop':
|
||||
case 'leave':
|
||||
manager.stop(); break;
|
||||
case 'mute':
|
||||
manager.mute(); break;
|
||||
case 'unmute':
|
||||
manager.unmute(); break;
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Call.events_interface[async]', e);
|
||||
} finally {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// Auto Hide/Show interface topbar
|
||||
video_container_sel.mousemove(function() {
|
||||
try {
|
||||
var topbar_sel = $(this).find('.topbar');
|
||||
|
||||
if(topbar_sel.is(':hidden')) {
|
||||
topbar_sel.stop(true).fadeIn(250);
|
||||
}
|
||||
|
||||
topbar_sel.stopTime();
|
||||
topbar_sel.oneTime('5s', function() {
|
||||
topbar_sel.stop(true).fadeOut(250);
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Call.events_interface[async]', e);
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Call.events_interface', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return class scope
|
||||
*/
|
||||
return self;
|
||||
|
||||
})();
|
|
@ -20,6 +20,444 @@ var Caps = (function () {
|
|||
var self = {};
|
||||
|
||||
|
||||
/* Constants */
|
||||
self.disco_infos = {
|
||||
'identity': {
|
||||
'category': 'client',
|
||||
'type': 'web',
|
||||
'name': 'Jappix'
|
||||
},
|
||||
|
||||
'items': [
|
||||
NS_MUC,
|
||||
NS_MUC_USER,
|
||||
NS_MUC_ADMIN,
|
||||
NS_MUC_OWNER,
|
||||
NS_MUC_CONFIG,
|
||||
NS_DISCO_INFO,
|
||||
NS_DISCO_ITEMS,
|
||||
NS_PUBSUB_RI,
|
||||
NS_BOSH,
|
||||
NS_CAPS,
|
||||
NS_MOOD,
|
||||
NS_ACTIVITY,
|
||||
NS_TUNE,
|
||||
NS_GEOLOC,
|
||||
NS_NICK,
|
||||
NS_URN_MBLOG,
|
||||
NS_URN_INBOX,
|
||||
NS_MOOD + NS_NOTIFY,
|
||||
NS_ACTIVITY + NS_NOTIFY,
|
||||
NS_TUNE + NS_NOTIFY,
|
||||
NS_GEOLOC + NS_NOTIFY,
|
||||
NS_URN_MBLOG + NS_NOTIFY,
|
||||
NS_URN_INBOX + NS_NOTIFY,
|
||||
NS_URN_DELAY,
|
||||
NS_ROSTER,
|
||||
NS_ROSTERX,
|
||||
NS_HTTP_AUTH,
|
||||
NS_CHATSTATES,
|
||||
NS_XHTML_IM,
|
||||
NS_URN_MAM,
|
||||
NS_IPV6,
|
||||
NS_LAST,
|
||||
NS_PRIVATE,
|
||||
NS_REGISTER,
|
||||
NS_SEARCH,
|
||||
NS_COMMANDS,
|
||||
NS_VERSION,
|
||||
NS_XDATA,
|
||||
NS_VCARD,
|
||||
NS_IETF_VCARD4,
|
||||
NS_URN_ADATA,
|
||||
NS_URN_AMETA,
|
||||
NS_URN_TIME,
|
||||
NS_URN_PING,
|
||||
NS_URN_RECEIPTS,
|
||||
NS_PRIVACY,
|
||||
NS_IQOOB,
|
||||
NS_XOOB,
|
||||
NS_URN_CARBONS,
|
||||
NS_URN_CORRECT,
|
||||
NS_URN_MARKERS,
|
||||
NS_URN_IDLE,
|
||||
NS_URN_ATTENTION,
|
||||
NS_URN_REACH,
|
||||
NS_URN_HINTS
|
||||
]
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Parse identities from disco infos query response
|
||||
* @private
|
||||
* @param {object} query
|
||||
* @return {object}
|
||||
*/
|
||||
self._parseDiscoIdentities = function(query) {
|
||||
|
||||
var identities = [];
|
||||
|
||||
try {
|
||||
var cur_category, cur_type, cur_lang, cur_name;
|
||||
|
||||
$(query).find('identity').each(function() {
|
||||
cur_category = $(this).attr('category') || '';
|
||||
cur_type = $(this).attr('type') || '';
|
||||
cur_lang = $(this).attr('xml:lang') || '';
|
||||
cur_name = $(this).attr('name') || '';
|
||||
|
||||
identities.push(cur_category + '/' + cur_type + '/' + cur_lang + '/' + cur_name);
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Caps._parseDiscoIdentities', e);
|
||||
} finally {
|
||||
return identities;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Parse features from disco infos query response
|
||||
* @private
|
||||
* @param {object} query
|
||||
* @return {object}
|
||||
*/
|
||||
self._parseDiscoFeatures = function(query) {
|
||||
|
||||
var features = [];
|
||||
|
||||
try {
|
||||
var cur_var;
|
||||
|
||||
$(query).find('feature').each(function() {
|
||||
cur_var = $(this).attr('var');
|
||||
|
||||
// Add the current value to the array
|
||||
if(cur_var) {
|
||||
features.push(cur_var);
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Caps._parseDiscoFatures', e);
|
||||
} finally {
|
||||
return features;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Parse data form from disco infos query response
|
||||
* @private
|
||||
* @param {object} query
|
||||
* @return {object}
|
||||
*/
|
||||
self._parseDiscoDataForms = function(query) {
|
||||
|
||||
var data_forms = [];
|
||||
|
||||
try {
|
||||
var cur_string, cur_sort_var,
|
||||
cur_text, cur_var, cur_sort_val;
|
||||
|
||||
$(query).find('x[xmlns="' + NS_XDATA + '"]').each(function() {
|
||||
// Initialize some stuffs
|
||||
cur_string = '';
|
||||
cur_sort_var = [];
|
||||
|
||||
// Add the form type field
|
||||
$(this).find('field[var="FORM_TYPE"] value').each(function() {
|
||||
cur_text = $(this).text();
|
||||
|
||||
if(cur_text) {
|
||||
cur_string += cur_text + '<';
|
||||
}
|
||||
});
|
||||
|
||||
// Add the var attributes into an array
|
||||
$(this).find('field:not([var="FORM_TYPE"])').each(function() {
|
||||
cur_var = $(this).attr('var');
|
||||
|
||||
if(cur_var) {
|
||||
cur_sort_var.push(cur_var);
|
||||
}
|
||||
});
|
||||
|
||||
// Sort the var attributes
|
||||
cur_sort_var = cur_sort_var.sort();
|
||||
|
||||
// Loop this sorted var attributes
|
||||
$.each(cur_sort_var, function(i) {
|
||||
// Initialize the value sorting
|
||||
cur_sort_val = [];
|
||||
|
||||
// Append it to the string
|
||||
cur_string += cur_sort_var[i] + '<';
|
||||
|
||||
// Add each value to the array
|
||||
$(this).find('field[var=' + cur_sort_var[i] + '] value').each(function() {
|
||||
cur_sort_val.push($(this).text());
|
||||
});
|
||||
|
||||
// Sort the values
|
||||
cur_sort_val = cur_sort_val.sort();
|
||||
|
||||
// Append the values to the string
|
||||
for(var j in cur_sort_val) {
|
||||
cur_string += cur_sort_val[j] + '<';
|
||||
}
|
||||
});
|
||||
|
||||
// Any string?
|
||||
if(cur_string) {
|
||||
// Remove the undesired double '<' from the string
|
||||
if(cur_string.match(/(.+)(<)+$/)) {
|
||||
cur_string = cur_string.substring(0, cur_string.length - 1);
|
||||
}
|
||||
|
||||
// Add the current string to the array
|
||||
data_forms.push(cur_string);
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Caps._parseDiscoDataForms', e);
|
||||
} finally {
|
||||
return data_forms;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply XHTML-IM features from disco infos
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @param {object} features
|
||||
* @param {object} style_sel
|
||||
* @param {object} message_area_sel
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._applyDiscoXHTMLIM = function(xid, features, style_sel, message_area_sel) {
|
||||
|
||||
try {
|
||||
// Apply
|
||||
if(NS_XHTML_IM in features) {
|
||||
style_sel.show();
|
||||
} else {
|
||||
// Remove the tooltip elements
|
||||
style_sel.hide();
|
||||
style_sel.find('.bubble-style').remove();
|
||||
|
||||
// Reset the markers
|
||||
message_area_sel.removeAttr('style')
|
||||
.removeAttr('data-font')
|
||||
.removeAttr('data-fontsize')
|
||||
.removeAttr('data-color')
|
||||
.removeAttr('data-bold')
|
||||
.removeAttr('data-italic')
|
||||
.removeAttr('data-underline');
|
||||
}
|
||||
|
||||
} catch(e) {
|
||||
Console.error('Caps._applyDiscoXHTMLIM', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply Jingle features from disco infos
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @param {object} path_sel
|
||||
* @param {object} roster_sel
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._applyDiscoJingle = function(xid, path_sel, roster_sel) {
|
||||
|
||||
try {
|
||||
// Selectors
|
||||
var roster_jingle_sel = roster_sel.find('.buddy-infos .call-jingle');
|
||||
var jingle_audio = path_sel.find('.tools-jingle-audio');
|
||||
var roster_jingle_audio = roster_jingle_sel.find('a.audio');
|
||||
var jingle_video = path_sel.find('.tools-jingle-video');
|
||||
var roster_jingle_video = roster_jingle_sel.find('a.video');
|
||||
var roster_jingle_separator = roster_jingle_sel.find('span.separator');
|
||||
|
||||
// Apply
|
||||
var jingle_local_supported = JSJAC_JINGLE_AVAILABLE;
|
||||
var jingle_audio_xid = self.getFeatureResource(xid, NS_JINGLE_APPS_RTP_AUDIO);
|
||||
var jingle_video_xid = self.getFeatureResource(xid, NS_JINGLE_APPS_RTP_VIDEO);
|
||||
|
||||
if(jingle_audio_xid && jingle_local_supported) {
|
||||
jingle_audio.show();
|
||||
roster_jingle_audio.show();
|
||||
} else {
|
||||
jingle_audio.hide();
|
||||
roster_jingle_audio.hide();
|
||||
}
|
||||
|
||||
if(jingle_video_xid && jingle_local_supported) {
|
||||
jingle_video.show();
|
||||
roster_jingle_video.show();
|
||||
} else {
|
||||
jingle_video.hide();
|
||||
roster_jingle_video.hide();
|
||||
}
|
||||
|
||||
if(jingle_audio_xid && jingle_video_xid && jingle_local_supported) {
|
||||
roster_jingle_separator.show();
|
||||
} else {
|
||||
roster_jingle_separator.hide();
|
||||
}
|
||||
|
||||
if((jingle_audio_xid || jingle_video_xid) && jingle_local_supported) {
|
||||
roster_jingle_sel.show();
|
||||
} else {
|
||||
roster_jingle_sel.hide();
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Caps._applyDiscoJingle', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply Out of Band Data features from disco infos
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @param {object} features
|
||||
* @param {object} file_sel
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._applyDiscoOOB = function(xid, features, file_sel) {
|
||||
|
||||
try {
|
||||
// Apply
|
||||
var iq_oob_xid = self.getFeatureResource(xid, NS_IQOOB);
|
||||
|
||||
if(iq_oob_xid || NS_XOOB in features) {
|
||||
file_sel.show();
|
||||
|
||||
// Set a marker
|
||||
file_sel.attr(
|
||||
'data-oob',
|
||||
iq_oob_xid ? 'iq' : 'x'
|
||||
);
|
||||
} else {
|
||||
// Remove the tooltip elements
|
||||
file_sel.hide();
|
||||
file_sel.find('.bubble-style').remove();
|
||||
|
||||
// Reset the marker
|
||||
file_sel.removeAttr('data-oob');
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Caps._applyDiscoOOB', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply Receipts features from disco infos
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @param {object} features
|
||||
* @param {object} message_area_sel
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._applyDiscoReceipts = function(xid, features, message_area_sel) {
|
||||
|
||||
try {
|
||||
// Apply
|
||||
if(NS_URN_RECEIPTS in features) {
|
||||
message_area_sel.attr('data-receipts', 'true');
|
||||
} else {
|
||||
message_area_sel.removeAttr('data-receipts');
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Caps._applyDiscoReceipts', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply Last Message Correction features from disco infos
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @param {object} features
|
||||
* @param {object} path_sel
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._applyDiscoCorrection = function(xid, features, path_sel) {
|
||||
|
||||
try {
|
||||
// Apply
|
||||
if(NS_URN_CORRECT in features) {
|
||||
path_sel.attr('data-correction', 'true');
|
||||
} else {
|
||||
path_sel.removeAttr('data-correction');
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Caps._applyDiscoCorrection', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply Chat Markers features from disco infos
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @param {object} features
|
||||
* @param {object} path_sel
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._applyDiscoMarkers = function(xid, features, path_sel) {
|
||||
|
||||
try {
|
||||
// Apply
|
||||
if(NS_URN_MARKERS in features) {
|
||||
path_sel.attr('data-markers', 'true');
|
||||
} else {
|
||||
path_sel.removeAttr('data-markers');
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Caps._applyDiscoMarkers', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply Attention features from disco infos
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @param {object} features
|
||||
* @param {object} path_sel
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._applyDiscoAttention = function(xid, features, path_sel) {
|
||||
|
||||
try {
|
||||
// Apply
|
||||
if(NS_URN_ATTENTION in features) {
|
||||
path_sel.attr('data-attention', 'true');
|
||||
} else {
|
||||
path_sel.removeAttr('data-attention');
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Caps._applyDiscoAttention', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Reads a stored Caps
|
||||
* @public
|
||||
|
@ -47,62 +485,12 @@ var Caps = (function () {
|
|||
self.myDiscoInfos = function() {
|
||||
|
||||
try {
|
||||
var disco_base = [
|
||||
NS_MUC,
|
||||
NS_MUC_USER,
|
||||
NS_MUC_ADMIN,
|
||||
NS_MUC_OWNER,
|
||||
NS_MUC_CONFIG,
|
||||
NS_DISCO_INFO,
|
||||
NS_DISCO_ITEMS,
|
||||
NS_PUBSUB_RI,
|
||||
NS_BOSH,
|
||||
NS_CAPS,
|
||||
NS_MOOD,
|
||||
NS_ACTIVITY,
|
||||
NS_TUNE,
|
||||
NS_GEOLOC,
|
||||
NS_NICK,
|
||||
NS_URN_MBLOG,
|
||||
NS_URN_INBOX,
|
||||
NS_MOOD + NS_NOTIFY,
|
||||
NS_ACTIVITY + NS_NOTIFY,
|
||||
NS_TUNE + NS_NOTIFY,
|
||||
NS_GEOLOC + NS_NOTIFY,
|
||||
NS_URN_MBLOG + NS_NOTIFY,
|
||||
NS_URN_INBOX + NS_NOTIFY,
|
||||
NS_URN_DELAY,
|
||||
NS_ROSTER,
|
||||
NS_ROSTERX,
|
||||
NS_HTTP_AUTH,
|
||||
NS_CHATSTATES,
|
||||
NS_XHTML_IM,
|
||||
NS_URN_MAM,
|
||||
NS_IPV6,
|
||||
NS_LAST,
|
||||
NS_PRIVATE,
|
||||
NS_REGISTER,
|
||||
NS_SEARCH,
|
||||
NS_COMMANDS,
|
||||
NS_VERSION,
|
||||
NS_XDATA,
|
||||
NS_VCARD,
|
||||
NS_IETF_VCARD4,
|
||||
NS_URN_ADATA,
|
||||
NS_URN_AMETA,
|
||||
NS_URN_TIME,
|
||||
NS_URN_PING,
|
||||
NS_URN_RECEIPTS,
|
||||
NS_PRIVACY,
|
||||
NS_IQOOB,
|
||||
NS_XOOB,
|
||||
NS_URN_CARBONS
|
||||
];
|
||||
var disco_base = self.disco_infos.items;
|
||||
|
||||
var disco_jingle = JSJaCJingle_disco();
|
||||
var disco_jingle = JSJaCJingle.disco();
|
||||
var disco_all = disco_base.concat(disco_jingle);
|
||||
|
||||
return disco_all;
|
||||
return Utils.uniqueArrayValues(disco_all);
|
||||
} catch(e) {
|
||||
Console.error('Caps.myDiscoInfos', e);
|
||||
}
|
||||
|
@ -169,103 +557,17 @@ var Caps = (function () {
|
|||
self.handleDiscoInfos = function(iq) {
|
||||
|
||||
try {
|
||||
if(!iq || (iq.getType() == 'error'))
|
||||
if(!iq || (iq.getType() == 'error')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// IQ received, get some values
|
||||
var from = Common.fullXID(Common.getStanzaFrom(iq));
|
||||
var query = iq.getQuery();
|
||||
|
||||
// Generate the CAPS-processing values
|
||||
var identities = [];
|
||||
var features = [];
|
||||
var data_forms = [];
|
||||
|
||||
// Identity values
|
||||
$(query).find('identity').each(function() {
|
||||
var pCategory = $(this).attr('category');
|
||||
var pType = $(this).attr('type');
|
||||
var pLang = $(this).attr('xml:lang');
|
||||
var pName = $(this).attr('name');
|
||||
|
||||
if(!pCategory)
|
||||
pCategory = '';
|
||||
if(!pType)
|
||||
pType = '';
|
||||
if(!pLang)
|
||||
pLang = '';
|
||||
if(!pName)
|
||||
pName = '';
|
||||
|
||||
identities.push(pCategory + '/' + pType + '/' + pLang + '/' + pName);
|
||||
});
|
||||
|
||||
// Feature values
|
||||
$(query).find('feature').each(function() {
|
||||
var pVar = $(this).attr('var');
|
||||
|
||||
// Add the current value to the array
|
||||
if(pVar)
|
||||
features.push(pVar);
|
||||
});
|
||||
|
||||
// Data-form values
|
||||
$(query).find('x[xmlns="' + NS_XDATA + '"]').each(function() {
|
||||
// Initialize some stuffs
|
||||
var pString = '';
|
||||
var sortVar = [];
|
||||
|
||||
// Add the form type field
|
||||
$(this).find('field[var="FORM_TYPE"] value').each(function() {
|
||||
var cText = $(this).text();
|
||||
|
||||
if(cText)
|
||||
pString += cText + '<';
|
||||
});
|
||||
|
||||
// Add the var attributes into an array
|
||||
$(this).find('field:not([var="FORM_TYPE"])').each(function() {
|
||||
var cVar = $(this).attr('var');
|
||||
|
||||
if(cVar)
|
||||
sortVar.push(cVar);
|
||||
});
|
||||
|
||||
// Sort the var attributes
|
||||
sortVar = sortVar.sort();
|
||||
|
||||
// Loop this sorted var attributes
|
||||
$.each(sortVar, function(i) {
|
||||
// Initialize the value sorting
|
||||
var sortVal = [];
|
||||
|
||||
// Append it to the string
|
||||
pString += sortVar[i] + '<';
|
||||
|
||||
// Add each value to the array
|
||||
$(this).find('field[var=' + sortVar[i] + '] value').each(function() {
|
||||
sortVal.push($(this).text());
|
||||
});
|
||||
|
||||
// Sort the values
|
||||
sortVal = sortVal.sort();
|
||||
|
||||
// Append the values to the string
|
||||
for(var j in sortVal) {
|
||||
pString += sortVal[j] + '<';
|
||||
}
|
||||
});
|
||||
|
||||
// Any string?
|
||||
if(pString) {
|
||||
// Remove the undesired double '<' from the string
|
||||
if(pString.match(/(.+)(<)+$/))
|
||||
pString = pString.substring(0, pString.length - 1);
|
||||
|
||||
// Add the current string to the array
|
||||
data_forms.push(pString);
|
||||
}
|
||||
});
|
||||
// Parse values
|
||||
var identities = self._parseDiscoIdentities(query);
|
||||
var features = self._parseDiscoFeatures(query);
|
||||
var data_forms = self._parseDiscoDataForms(query);
|
||||
|
||||
// Process the CAPS
|
||||
var caps = self.process(identities, features, data_forms);
|
||||
|
@ -309,8 +611,9 @@ var Caps = (function () {
|
|||
var xid = Common.bareXID(from);
|
||||
|
||||
// This comes from a private groupchat chat?
|
||||
if(Utils.isPrivate(xid))
|
||||
if(Utils.isPrivate(xid)) {
|
||||
xid = from;
|
||||
}
|
||||
|
||||
hash = hex_md5(xid);
|
||||
|
||||
|
@ -326,96 +629,20 @@ var Caps = (function () {
|
|||
});
|
||||
|
||||
// Paths
|
||||
var path = $('#' + hash);
|
||||
var roster_path = $('#roster .buddy.' + hash);
|
||||
var roster_jingle_path = roster_path.find('.buddy-infos .call-jingle');
|
||||
|
||||
var message_area = path.find('.message-area');
|
||||
var style = path.find('.chat-tools-style');
|
||||
var jingle_audio = path.find('.tools-jingle-audio');
|
||||
var roster_jingle_audio = roster_jingle_path.find('a.audio');
|
||||
var jingle_video = path.find('.tools-jingle-video');
|
||||
var roster_jingle_video = roster_jingle_path.find('a.video');
|
||||
var roster_jingle_separator = roster_jingle_path.find('span.separator');
|
||||
var file = path.find('.chat-tools-file');
|
||||
var path_sel = $('#' + hash);
|
||||
var roster_sel = $('#roster .buddy.' + hash);
|
||||
var message_area_sel = path_sel.find('.message-area');
|
||||
var style_sel = path_sel.find('.chat-tools-style');
|
||||
var file_sel = path_sel.find('.chat-tools-file');
|
||||
|
||||
// Apply xHTML-IM
|
||||
if(NS_XHTML_IM in features) {
|
||||
style.show();
|
||||
} else {
|
||||
// Remove the tooltip elements
|
||||
style.hide();
|
||||
style.find('.bubble-style').remove();
|
||||
|
||||
// Reset the markers
|
||||
message_area.removeAttr('style')
|
||||
.removeAttr('data-font')
|
||||
.removeAttr('data-fontsize')
|
||||
.removeAttr('data-color')
|
||||
.removeAttr('data-bold')
|
||||
.removeAttr('data-italic')
|
||||
.removeAttr('data-underline');
|
||||
}
|
||||
|
||||
// Apply Jingle
|
||||
var jingle_local_supported = JSJAC_JINGLE_AVAILABLE;
|
||||
var jingle_audio_xid = self.getFeatureResource(xid, NS_JINGLE_APPS_RTP_AUDIO);
|
||||
var jingle_video_xid = self.getFeatureResource(xid, NS_JINGLE_APPS_RTP_VIDEO);
|
||||
|
||||
if(jingle_audio_xid && jingle_local_supported) {
|
||||
jingle_audio.show();
|
||||
roster_jingle_audio.show();
|
||||
} else {
|
||||
jingle_audio.hide();
|
||||
roster_jingle_audio.hide();
|
||||
}
|
||||
|
||||
if(jingle_video_xid && jingle_local_supported) {
|
||||
jingle_video.show();
|
||||
roster_jingle_video.show();
|
||||
} else {
|
||||
jingle_video.hide();
|
||||
roster_jingle_video.hide();
|
||||
}
|
||||
|
||||
if(jingle_audio_xid && jingle_video_xid && jingle_local_supported) {
|
||||
roster_jingle_separator.show();
|
||||
} else {
|
||||
roster_jingle_separator.hide();
|
||||
}
|
||||
|
||||
if((jingle_audio_xid || jingle_video_xid) && jingle_local_supported) {
|
||||
roster_jingle_path.show();
|
||||
} else {
|
||||
roster_jingle_path.hide();
|
||||
}
|
||||
|
||||
// Apply Out of Band Data
|
||||
var iq_oob_xid = self.getFeatureResource(xid, NS_IQOOB);
|
||||
|
||||
if(iq_oob_xid || NS_XOOB in features) {
|
||||
file.show();
|
||||
|
||||
// Set a marker
|
||||
file.attr(
|
||||
'data-oob',
|
||||
iq_oob_xid ? 'iq' : 'x'
|
||||
);
|
||||
} else {
|
||||
// Remove the tooltip elements
|
||||
file.hide();
|
||||
file.find('.bubble-style').remove();
|
||||
|
||||
// Reset the marker
|
||||
file.removeAttr('data-oob');
|
||||
}
|
||||
|
||||
// Apply receipts
|
||||
if(NS_URN_RECEIPTS in features) {
|
||||
message_area.attr('data-receipts', 'true');
|
||||
} else {
|
||||
message_area.removeAttr('data-receipts');
|
||||
}
|
||||
// Apply Features
|
||||
self._applyDiscoXHTMLIM(xid, features, style_sel, message_area_sel);
|
||||
self._applyDiscoJingle(xid, path_sel, roster_sel);
|
||||
self._applyDiscoOOB(xid, features, file_sel);
|
||||
self._applyDiscoReceipts(xid, features, message_area_sel);
|
||||
self._applyDiscoCorrection(xid, features, path_sel);
|
||||
self._applyDiscoMarkers(xid, features, path_sel);
|
||||
self._applyDiscoAttention(xid, features, path_sel);
|
||||
} catch(e) {
|
||||
Console.error('Caps.displayDiscoInfos', e);
|
||||
}
|
||||
|
@ -426,39 +653,39 @@ var Caps = (function () {
|
|||
/**
|
||||
* Generates the CAPS hash
|
||||
* @public
|
||||
* @param {object} cIdentities
|
||||
* @param {object} cFeatures
|
||||
* @param {object} cDataForms
|
||||
* @param {object} identities
|
||||
* @param {object} features
|
||||
* @param {object} dataforms
|
||||
* @return {string}
|
||||
*/
|
||||
self.process = function(cIdentities, cFeatures, cDataForms) {
|
||||
self.process = function(identities, features, dataforms) {
|
||||
|
||||
try {
|
||||
// Initialize
|
||||
var cString = '';
|
||||
var caps_str = '';
|
||||
|
||||
// Sort the arrays
|
||||
cIdentities = cIdentities.sort();
|
||||
cFeatures = cFeatures.sort();
|
||||
cDataForms = cDataForms.sort();
|
||||
identities = identities.sort();
|
||||
features = features.sort();
|
||||
dataforms = dataforms.sort();
|
||||
|
||||
// Process the sorted identity string
|
||||
for(var a in cIdentities) {
|
||||
cString += cIdentities[a] + '<';
|
||||
for(var a in identities) {
|
||||
caps_str += identities[a] + '<';
|
||||
}
|
||||
|
||||
// Process the sorted feature string
|
||||
for(var b in cFeatures) {
|
||||
cString += cFeatures[b] + '<';
|
||||
for(var b in features) {
|
||||
caps_str += features[b] + '<';
|
||||
}
|
||||
|
||||
// Process the sorted data-form string
|
||||
for(var c in cDataForms) {
|
||||
cString += cDataForms[c] + '<';
|
||||
for(var c in dataforms) {
|
||||
caps_str += dataforms[c] + '<';
|
||||
}
|
||||
|
||||
// Process the SHA-1 hash
|
||||
var cHash = b64_sha1(cString);
|
||||
var cHash = b64_sha1(caps_str);
|
||||
|
||||
return cHash;
|
||||
} catch(e) {
|
||||
|
@ -477,7 +704,12 @@ var Caps = (function () {
|
|||
|
||||
try {
|
||||
return self.process(
|
||||
['client/web//Jappix'],
|
||||
[
|
||||
self.disco_infos.identity.category + '/' +
|
||||
self.disco_infos.identity.type + '//' +
|
||||
self.disco_infos.identity.name
|
||||
],
|
||||
|
||||
self.myDiscoInfos(),
|
||||
[]
|
||||
);
|
||||
|
@ -507,8 +739,14 @@ var Caps = (function () {
|
|||
var max_priority = null;
|
||||
var cur_xid_full, cur_presence_sel, cur_caps, cur_features, cur_priority;
|
||||
|
||||
for(var cur_resource in Presence.resources(xid)) {
|
||||
cur_xid_full = xid + '/' + cur_resource;
|
||||
var resources_obj = Presence.resources(xid);
|
||||
var fn_parse_resource = function(cur_resource) {
|
||||
cur_xid_full = xid;
|
||||
|
||||
if(cur_resource) {
|
||||
cur_xid_full += '/' + cur_resource;
|
||||
}
|
||||
|
||||
cur_presence_sel = $(Presence.readStanza(cur_xid_full));
|
||||
|
||||
cur_priority = parseInt((cur_presence_sel.find('priority').text() || 0), 10);
|
||||
|
@ -523,6 +761,14 @@ var Caps = (function () {
|
|||
selected_xid = cur_xid_full;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if(resources_obj.bare === 1) {
|
||||
fn_parse_resource(null);
|
||||
}
|
||||
|
||||
for(var cur_resource in resources_obj.list) {
|
||||
fn_parse_resource(cur_resource);
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Caps.getFeatureResource', e);
|
||||
|
@ -538,4 +784,4 @@ var Caps = (function () {
|
|||
*/
|
||||
return self;
|
||||
|
||||
})();
|
||||
})();
|
||||
|
|
|
@ -22,7 +22,7 @@ var Carbons = (function () {
|
|||
|
||||
/**
|
||||
* Configures Message Carbons options
|
||||
* @public
|
||||
* @private
|
||||
* @param {string} type
|
||||
* @return {undefined}
|
||||
*/
|
||||
|
@ -50,7 +50,7 @@ var Carbons = (function () {
|
|||
|
||||
/**
|
||||
* Configures Message Carbons options
|
||||
* @public
|
||||
* @private
|
||||
* @param {object} iq
|
||||
* @param {string} type
|
||||
* @return {undefined}
|
||||
|
@ -193,6 +193,9 @@ var Carbons = (function () {
|
|||
} else {
|
||||
Console.debug('Got a sent message from another resource to: ' + (to || 'none') + ', was ignored because body empty');
|
||||
}
|
||||
|
||||
// Handle chat markers change
|
||||
Markers.handleCarbonChange(forwarded_message);
|
||||
} else {
|
||||
Console.debug('Got a sent message from another resource to: ' + (to || 'none') + ', was ignored because chat not open');
|
||||
}
|
||||
|
|
|
@ -20,6 +20,289 @@ var Chat = (function () {
|
|||
var self = {};
|
||||
|
||||
|
||||
/**
|
||||
* Apply generate events
|
||||
* @private
|
||||
* @param {string} path
|
||||
* @param {string} id
|
||||
* @param {string} xid
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._generateEvents = function(path, id, xid) {
|
||||
|
||||
try {
|
||||
// Click event: chat cleaner
|
||||
$(path + 'tools-clear').click(function() {
|
||||
self.clean(id);
|
||||
});
|
||||
|
||||
// Click event: call (audio)
|
||||
$(path + 'tools-jingle-audio').click(function() {
|
||||
Jingle.start(xid, 'audio');
|
||||
});
|
||||
|
||||
// Click event: call (video)
|
||||
$(path + 'tools-jingle-video').click(function() {
|
||||
Jingle.start(xid, 'video');
|
||||
});
|
||||
|
||||
// Click event: user-infos
|
||||
$(path + 'tools-infos').click(function() {
|
||||
UserInfos.open(xid);
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Chat._generateEvents', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply generate events
|
||||
* @private
|
||||
* @param {object} input_sel
|
||||
* @param {string} xid
|
||||
* @param {string} hash
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._createEvents = function(input_sel, xid, hash) {
|
||||
|
||||
try {
|
||||
self._createEventsInput(input_sel, hash);
|
||||
self._createEventsKey(input_sel, xid, hash);
|
||||
self._createEventsMouse(xid, hash);
|
||||
} catch(e) {
|
||||
Console.error('Chat._createEvents', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply generate events (input)
|
||||
* @private
|
||||
* @param {object} input_sel
|
||||
* @param {string} hash
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._createEventsInput = function(input_sel, hash) {
|
||||
|
||||
try {
|
||||
input_sel.focus(function() {
|
||||
// Clean notifications for this chat
|
||||
Interface.chanCleanNotify(hash);
|
||||
|
||||
// Store focus on this chat!
|
||||
Interface.chat_focus_hash = hash;
|
||||
});
|
||||
|
||||
input_sel.blur(function() {
|
||||
// Reset storage about focus on this chat!
|
||||
if(Interface.chat_focus_hash == hash) {
|
||||
Interface.chat_focus_hash = null;
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Chat._createEventsInput', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply generate events (key)
|
||||
* @private
|
||||
* @param {object} input_sel
|
||||
* @param {string} xid
|
||||
* @param {string} hash
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._createEventsKey = function(input_sel, xid, hash) {
|
||||
|
||||
try {
|
||||
input_sel.keydown(function(e) {
|
||||
if(e.keyCode == 13) {
|
||||
// Enter key
|
||||
if(e.shiftKey || e.ctrlKey) {
|
||||
// Add a new line
|
||||
input_sel.val(input_sel.val() + '\n');
|
||||
} else {
|
||||
if(Correction.isIn(xid) === true) {
|
||||
var corrected_value = input_sel.val().trim();
|
||||
|
||||
if(corrected_value) {
|
||||
// Send the corrected message
|
||||
Correction.send(xid, 'chat', corrected_value);
|
||||
}
|
||||
|
||||
Correction.leave(xid);
|
||||
} else {
|
||||
// Send the message
|
||||
Message.send(hash, 'chat');
|
||||
}
|
||||
|
||||
// Reset the composing database entry
|
||||
DataStore.setDB(Connection.desktop_hash, 'chatstate', xid, 'off');
|
||||
}
|
||||
|
||||
return false;
|
||||
} else if(e.keyCode == 8) {
|
||||
// Leave correction mode? (another way, by flushing input value progressively)
|
||||
if(Correction.isIn(xid) === true && !input_sel.val()) {
|
||||
Correction.leave(xid);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
input_sel.keyup(function(e) {
|
||||
if(e.keyCode == 27) {
|
||||
// Escape key
|
||||
input_sel.val('');
|
||||
|
||||
// Leave correction mode? (simple escape way)
|
||||
if(Correction.isIn(xid) === true) {
|
||||
Correction.leave(xid);
|
||||
}
|
||||
} else {
|
||||
Correction.detect(xid, input_sel);
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Chat._createEventsKey', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply generate events (mouse)
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @param {string} hash
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._createEventsMouse = function(xid, hash) {
|
||||
|
||||
try {
|
||||
// Scroll in chat content
|
||||
$('#page-engine #' + hash + ' .content').scroll(function() {
|
||||
var self = this;
|
||||
|
||||
if(Features.enabledMAM() && !(xid in MAM.map_pending)) {
|
||||
var has_state = xid in MAM.map_states;
|
||||
var rsm_count = has_state ? MAM.map_states[xid].rsm.count : 1;
|
||||
var rsm_before = has_state ? MAM.map_states[xid].rsm.first : '';
|
||||
|
||||
// Request more archives?
|
||||
if(rsm_count > 0 && $(this).scrollTop() < MAM.SCROLL_THRESHOLD) {
|
||||
var was_scroll_top = $(self).scrollTop() <= 32;
|
||||
var wait_mam = $('#' + hash).find('.wait-mam');
|
||||
wait_mam.show();
|
||||
|
||||
MAM.getArchives({
|
||||
'with': xid
|
||||
}, {
|
||||
'max': MAM.REQ_MAX,
|
||||
'before': rsm_before
|
||||
}, function() {
|
||||
var wait_mam_height = was_scroll_top ? 0 : wait_mam.height();
|
||||
wait_mam.hide();
|
||||
|
||||
// Restore scroll?
|
||||
if($(self).scrollTop() < MAM.SCROLL_THRESHOLD) {
|
||||
var sel_mam_chunk = $(self).find('.mam-chunk:first');
|
||||
|
||||
var cont_padding_top = parseInt($(self).css('padding-top').replace(/[^-\d\.]/g, ''));
|
||||
var cont_one_group_margin_bottom = parseInt(sel_mam_chunk.find('.one-group:last').css('margin-bottom').replace(/[^-\d\.]/g, ''));
|
||||
var cont_mam_chunk_height = sel_mam_chunk.height();
|
||||
|
||||
$(self).scrollTop(wait_mam_height + cont_padding_top + cont_one_group_margin_bottom + cont_mam_chunk_height);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Chat._createEventsMouse', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply generate events
|
||||
* @private
|
||||
* @param {string} type
|
||||
* @param {string} id
|
||||
* @return {object}
|
||||
*/
|
||||
self._generateChatCode = function(type, id) {
|
||||
|
||||
var code_args = {};
|
||||
|
||||
try {
|
||||
// Groupchat special code
|
||||
if(type == 'groupchat') {
|
||||
code_args.attributes = ' data-type="groupchat" data-correction="true"';
|
||||
code_args.avatar = '';
|
||||
code_args.name = '<p class="bc-infos"><b>' + Common._e("Subject") + '</b> <span class="muc-topic">' + Common._e("no subject defined for this room.") + '</span></p>';
|
||||
code_args.code = '<div class="content groupchat-content" id="chat-content-' + id + '"></div>' +
|
||||
'<div class="list"><div class="moderator role"><p class="title">' + Common._e("Moderators") + '</p></div>' +
|
||||
'<div class="participant role"><p class="title">' + Common._e("Participants") + '</p></div>' +
|
||||
'<div class="visitor role"><p class="title">' + Common._e("Visitors") + '</p></div>' +
|
||||
'<div class="none role"><p class="title">' + Common._e("Others") + '</p></div></div>';
|
||||
code_args.link = '<a href="#" class="tools-mucadmin tools-tooltip talk-images chat-tools-content" title="' + Common._e("Administration panel for this room") + '"></a>';
|
||||
code_args.style = '';
|
||||
|
||||
// Is this a gateway?
|
||||
if(xid.match(/%/)) {
|
||||
code_args.disabled = '';
|
||||
} else {
|
||||
code_args.disabled = ' disabled=""';
|
||||
}
|
||||
} else {
|
||||
code_args.mam = '<div class="wait-mam wait-small"></div>';
|
||||
code_args.attributes = ' data-type="chat"';
|
||||
code_args.avatar = '<div class="avatar-container"><img class="avatar" src="' + './images/others/default-avatar.png' + '" alt="" /></div>';
|
||||
code_args.name = '<div class="bc-pep"></div><p class="bc-infos"><span class="unavailable show talk-images"></span></p>';
|
||||
code_args.code = '<div class="content" id="chat-content-' + id + '">' + code_args.mam + '</div>';
|
||||
code_args.link = '<a href="#" class="tools-jingle-audio tools-tooltip talk-images chat-tools-content" title="' + Common._e("Call (audio only)") + '"></a>' +
|
||||
'<a href="#" class="tools-jingle-video tools-tooltip talk-images chat-tools-content" title="' + Common._e("Call (video)") + '"></a>' +
|
||||
'<a href="#" class="tools-infos tools-tooltip talk-images chat-tools-content" title="' + Common._e("Show user profile") + '"></a>';
|
||||
code_args.style = ' style="display: none;"';
|
||||
code_args.disabled = '';
|
||||
}
|
||||
|
||||
// Not a groupchat private chat, we can use the buddy add icon
|
||||
if((type == 'chat') || (type == 'groupchat')) {
|
||||
var title;
|
||||
|
||||
if(type == 'chat') {
|
||||
title = Common._e("Add this contact to your friends");
|
||||
} else {
|
||||
title = Common._e("Add this groupchat to your favorites");
|
||||
}
|
||||
|
||||
code_args.link += '<a href="#" class="tools-add tools-tooltip talk-images chat-tools-content" title="' + title + '"></a>';
|
||||
}
|
||||
|
||||
// IE DOM parsing bug fix
|
||||
code_args.style_picker = '<div class="chat-tools-content chat-tools-style"' + code_args.style + '>' +
|
||||
'<a href="#" class="tools-style tools-tooltip talk-images"></a>' +
|
||||
'</div>';
|
||||
|
||||
if((BrowserDetect.browser == 'Explorer') && (BrowserDetect.version < 9)) {
|
||||
code_args.style_picker = '';
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Chat._generateChatCode', e);
|
||||
} finally {
|
||||
return code_args;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Correctly opens a new chat
|
||||
* @public
|
||||
|
@ -34,38 +317,40 @@ var Chat = (function () {
|
|||
|
||||
try {
|
||||
// No XID?
|
||||
if(!xid)
|
||||
if(!xid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We generate some stuffs
|
||||
var hash = hex_md5(xid);
|
||||
var name;
|
||||
|
||||
// Gets the name of the user/title of the room
|
||||
if(title)
|
||||
if(title) {
|
||||
name = title;
|
||||
|
||||
else {
|
||||
} else {
|
||||
// Private groupchat chat
|
||||
if(type == 'private')
|
||||
if(type == 'private') {
|
||||
name = Common.thisResource(xid);
|
||||
}
|
||||
|
||||
// XMPP-ID
|
||||
else if(xid.indexOf('@') != -1)
|
||||
else if(xid.indexOf('@') != -1) {
|
||||
name = Name.getBuddy(xid);
|
||||
}
|
||||
|
||||
// Gateway
|
||||
else
|
||||
else {
|
||||
name = xid;
|
||||
}
|
||||
}
|
||||
|
||||
// If the target div does not exist
|
||||
if(!Common.exists('#' + hash)) {
|
||||
// We check the type of the chat to open
|
||||
if((type == 'chat') || (type == 'private'))
|
||||
if((type == 'chat') || (type == 'private')) {
|
||||
self.create(hash, xid, name, type);
|
||||
|
||||
else if(type == 'groupchat') {
|
||||
} else if(type == 'groupchat') {
|
||||
// Try to read the room stored configuration
|
||||
if(!Utils.isAnonymous() && (!nickname || !password || !title)) {
|
||||
// Catch the room data
|
||||
|
@ -115,71 +400,21 @@ var Chat = (function () {
|
|||
var escaped_xid = escape(xid);
|
||||
|
||||
// Special code
|
||||
var specialAttributes, specialAvatar, specialName, specialCode, specialLink, specialDisabled, specialStyle, specialMAM;
|
||||
|
||||
// Groupchat special code
|
||||
if(type == 'groupchat') {
|
||||
specialAttributes = ' data-type="groupchat"';
|
||||
specialAvatar = '';
|
||||
specialName = '<p class="bc-infos"><b>' + Common._e("Subject") + '</b> <span class="muc-topic">' + Common._e("no subject defined for this room.") + '</span></p>';
|
||||
specialCode = '<div class="content groupchat-content" id="chat-content-' + id + '"></div><div class="list"><div class="moderator role"><p class="title">' + Common._e("Moderators") + '</p></div><div class="participant role"><p class="title">' + Common._e("Participants") + '</p></div><div class="visitor role"><p class="title">' + Common._e("Visitors") + '</p></div><div class="none role"><p class="title">' + Common._e("Others") + '</p></div></div>';
|
||||
specialLink = '<a href="#" class="tools-mucadmin tools-tooltip talk-images chat-tools-content" title="' + Common._e("Administration panel for this room") + '"></a>';
|
||||
specialStyle = '';
|
||||
|
||||
// Is this a gateway?
|
||||
if(xid.match(/%/))
|
||||
specialDisabled = '';
|
||||
else
|
||||
specialDisabled = ' disabled=""';
|
||||
}
|
||||
|
||||
// Chat (or other things?!) special code
|
||||
else {
|
||||
specialMAM = '<div class="wait-mam wait-small"></div>';
|
||||
specialAttributes = ' data-type="chat"';
|
||||
specialAvatar = '<div class="avatar-container"><img class="avatar" src="' + './images/others/default-avatar.png' + '" alt="" /></div>';
|
||||
specialName = '<div class="bc-pep"></div><p class="bc-infos"><span class="unavailable show talk-images"></span></p>';
|
||||
specialCode = '<div class="content" id="chat-content-' + id + '">' + specialMAM + '</div>';
|
||||
specialLink = '<a href="#" class="tools-jingle-audio tools-tooltip talk-images chat-tools-content" title="' + Common._e("Call (audio only)") + '"></a>' +
|
||||
'<a href="#" class="tools-jingle-video tools-tooltip talk-images chat-tools-content" title="' + Common._e("Call (video)") + '"></a>' +
|
||||
'<a href="#" class="tools-infos tools-tooltip talk-images chat-tools-content" title="' + Common._e("Show user profile") + '"></a>';
|
||||
specialStyle = ' style="display: none;"';
|
||||
specialDisabled = '';
|
||||
}
|
||||
|
||||
// Not a groupchat private chat, we can use the buddy add icon
|
||||
if((type == 'chat') || (type == 'groupchat')) {
|
||||
var addTitle;
|
||||
|
||||
if(type == 'chat')
|
||||
addTitle = Common._e("Add this contact to your friends");
|
||||
else
|
||||
addTitle = Common._e("Add this groupchat to your favorites");
|
||||
|
||||
specialLink += '<a href="#" class="tools-add tools-tooltip talk-images chat-tools-content" title="' + addTitle + '"></a>';
|
||||
}
|
||||
|
||||
// IE DOM parsing bug fix
|
||||
var specialStylePicker = '<div class="chat-tools-content chat-tools-style"' + specialStyle + '>' +
|
||||
'<a href="#" class="tools-style tools-tooltip talk-images"></a>' +
|
||||
'</div>';
|
||||
|
||||
if((BrowserDetect.browser == 'Explorer') && (BrowserDetect.version < 9))
|
||||
specialStylePicker = '';
|
||||
|
||||
var chat_args = self._generateChatCode(type, id);
|
||||
|
||||
// Append the chat HTML code
|
||||
$('#page-engine').append(
|
||||
'<div id="' + id + '" class="page-engine-chan chat one-counter"' + specialAttributes + ' data-xid="' + escaped_xid + '">' +
|
||||
'<div id="' + id + '" class="page-engine-chan chat one-counter"' + chat_args.attributes + ' data-xid="' + escaped_xid + '">' +
|
||||
'<div class="top ' + id + '">' +
|
||||
specialAvatar +
|
||||
chat_args.avatar +
|
||||
|
||||
'<div class="name">' +
|
||||
'<p class="bc-name bc-name-nick">' + nick.htmlEnc() + '</p>' +
|
||||
specialName +
|
||||
chat_args.name +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
specialCode +
|
||||
chat_args.code +
|
||||
|
||||
'<div class="text">' +
|
||||
'<div class="footer">' +
|
||||
|
@ -187,7 +422,7 @@ var Chat = (function () {
|
|||
'<a href="#" class="tools-smileys tools-tooltip talk-images"></a>' +
|
||||
'</div>' +
|
||||
|
||||
specialStylePicker +
|
||||
chat_args.style_picker +
|
||||
|
||||
'<div class="chat-tools-content chat-tools-file">' +
|
||||
'<a href="#" class="tools-file tools-tooltip talk-images"></a>' +
|
||||
|
@ -199,35 +434,17 @@ var Chat = (function () {
|
|||
|
||||
'<a href="#" class="tools-clear tools-tooltip talk-images chat-tools-content" title="' + Common._e("Clean current chat") + '"></a>' +
|
||||
|
||||
specialLink +
|
||||
chat_args.link +
|
||||
'</div>' +
|
||||
|
||||
'<div class="compose">' +
|
||||
'<textarea class="message-area focusable" ' + specialDisabled + ' data-to="' + escaped_xid + '" /></textarea>' +
|
||||
'<textarea class="message-area focusable" ' + chat_args.disabled + ' data-to="' + escaped_xid + '" /></textarea>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>'
|
||||
);
|
||||
|
||||
// Click event: chat cleaner
|
||||
$(path + 'tools-clear').click(function() {
|
||||
self.clean(id);
|
||||
});
|
||||
|
||||
// Click event: call (audio)
|
||||
$(path + 'tools-jingle-audio').click(function() {
|
||||
Jingle.start(xid, 'audio');
|
||||
});
|
||||
|
||||
// Click event: call (video)
|
||||
$(path + 'tools-jingle-video').click(function() {
|
||||
Jingle.start(xid, 'video');
|
||||
});
|
||||
|
||||
// Click event: user-infos
|
||||
$(path + 'tools-infos').click(function() {
|
||||
UserInfos.open(xid);
|
||||
});
|
||||
self._generateEvents(path, id, xid);
|
||||
} catch(e) {
|
||||
Console.error('Chat.generate', e);
|
||||
}
|
||||
|
@ -251,26 +468,32 @@ var Chat = (function () {
|
|||
var chat_switch = '#page-switch .';
|
||||
|
||||
// Special code
|
||||
var specialClass = ' unavailable';
|
||||
var special_class = ' unavailable';
|
||||
var show_close = true;
|
||||
|
||||
// Groupchat
|
||||
if(type == 'groupchat') {
|
||||
specialClass = ' groupchat-default';
|
||||
special_class = ' groupchat-default';
|
||||
|
||||
if(Utils.isAnonymous() && (xid == Common.generateXID(ANONYMOUS_ROOM, 'groupchat')))
|
||||
if(Utils.isAnonymous() && (xid == Common.generateXID(ANONYMOUS_ROOM, 'groupchat'))) {
|
||||
show_close = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Generate the HTML code
|
||||
var html = '<div class="' + id + ' switcher chan" onclick="return Interface.switchChan(\'' + Utils.encodeOnclick(id) + '\')">' +
|
||||
'<div class="icon talk-images' + specialClass + '"></div>' +
|
||||
|
||||
'<div class="name">' + nick.htmlEnc() + '</div>';
|
||||
'<div class="icon talk-images' + special_class + '"></div>' +
|
||||
|
||||
'<div class="name">' + nick.htmlEnc() + '</div>';
|
||||
|
||||
// Show the close button if not MUC and not anonymous
|
||||
if(show_close)
|
||||
html += '<div class="exit" title="' + Common._e("Close this tab") + '" onclick="return Interface.quitThisChat(\'' + Utils.encodeOnclick(xid) + '\', \'' + Utils.encodeOnclick(id) + '\', \'' + Utils.encodeOnclick(type) + '\');">x</div>';
|
||||
if(show_close) {
|
||||
html += '<div class="exit" ' +
|
||||
'title="' + Common._e("Close this tab") + '" ' +
|
||||
'onclick="return Interface.quitThisChat(\'' + Utils.encodeOnclick(xid) + '\', \'' + Utils.encodeOnclick(id) + '\', \'' + Utils.encodeOnclick(type) + '\');">' +
|
||||
'x' +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
// Close the HTML
|
||||
html += '</div>';
|
||||
|
@ -353,7 +576,7 @@ var Chat = (function () {
|
|||
// Create the chat switcher
|
||||
self.generateSwitch(type, hash, xid, nick);
|
||||
|
||||
// If the user is not in our roster
|
||||
// Is this a chat?
|
||||
if(type == 'chat') {
|
||||
// MAM? Get archives from there!
|
||||
if(Features.enabledMAM()) {
|
||||
|
@ -373,32 +596,43 @@ var Chat = (function () {
|
|||
var friend_hash = hex_md5(xid);
|
||||
|
||||
// Add chat history HTML
|
||||
$('#' + hash + ' .content').append(chat_history);
|
||||
var path_sel = $('#' + hash);
|
||||
|
||||
path_sel.find('.content').append(chat_history);
|
||||
|
||||
// Filter old groups & messages
|
||||
$('#' + hash + ' .one-group[data-type="user-message"]').addClass('from-history').attr('data-type', 'old-message');
|
||||
$('#' + hash + ' .user-message').removeClass('user-message').addClass('old-message');
|
||||
var one_group_sel = path_sel.find('.one-group');
|
||||
one_group_sel.filter('[data-type="user-message"]').addClass('from-history').attr('data-type', 'old-message');
|
||||
path_sel.find('.user-message').removeClass('user-message').addClass('old-message');
|
||||
|
||||
// Regenerate user names
|
||||
$('#' + hash + ' .one-group.' + my_hash + ' b.name').text(Name.getBuddy(Common.getXID()));
|
||||
$('#' + hash + ' .one-group.' + friend_hash + ' b.name').text(Name.getBuddy(xid));
|
||||
one_group_sel.filter('.' + my_hash + ' b.name').text(
|
||||
Name.getBuddy(Common.getXID())
|
||||
);
|
||||
|
||||
one_group_sel.filter('.' + friend_hash + ' b.name').text(
|
||||
Name.getBuddy(xid)
|
||||
);
|
||||
|
||||
// Regenerate group dates
|
||||
$('#' + hash + ' .one-group').each(function() {
|
||||
var current_stamp = parseInt($(this).attr('data-stamp'));
|
||||
one_group_sel.each(function() {
|
||||
var current_stamp = parseInt($(this).attr('data-stamp'), 10);
|
||||
$(this).find('span.date').text(DateUtils.relative(current_stamp));
|
||||
});
|
||||
|
||||
// Regenerate avatars
|
||||
if(Common.exists('#' + hash + ' .one-group.' + my_hash + ' .avatar-container'))
|
||||
if(Common.exists('#' + hash + ' .one-group.' + my_hash + ' .avatar-container')) {
|
||||
Avatar.get(Common.getXID(), 'cache', 'true', 'forget');
|
||||
if(Common.exists('#' + hash + ' .one-group.' + friend_hash + ' .avatar-container'))
|
||||
}
|
||||
|
||||
if(Common.exists('#' + hash + ' .one-group.' + friend_hash + ' .avatar-container')) {
|
||||
Avatar.get(xid, 'cache', 'true', 'forget');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add button
|
||||
if(!Roster.isFriend(xid))
|
||||
if(!Roster.isFriend(xid)) {
|
||||
$('#' + hash + ' .tools-add').click(function() {
|
||||
// Hide the icon (to tell the user all is okay)
|
||||
$(this).hide();
|
||||
|
@ -406,6 +640,7 @@ var Chat = (function () {
|
|||
// Send the subscribe request
|
||||
Roster.addThisContact(xid, nick);
|
||||
}).show();
|
||||
}
|
||||
}
|
||||
|
||||
// We catch the user's informations (like this avatar, vcard, and so on...)
|
||||
|
@ -415,81 +650,12 @@ var Chat = (function () {
|
|||
Tooltip.icons(xid, hash);
|
||||
|
||||
// The event handlers
|
||||
var inputDetect = $('#page-engine #' + hash + ' .message-area');
|
||||
var input_sel = $('#page-engine #' + hash + ' .message-area');
|
||||
self._createEvents(input_sel, xid, hash);
|
||||
|
||||
inputDetect.focus(function() {
|
||||
// Clean notifications for this chat
|
||||
Interface.chanCleanNotify(hash);
|
||||
|
||||
// Store focus on this chat!
|
||||
Interface.chat_focus_hash = hash;
|
||||
});
|
||||
|
||||
inputDetect.blur(function() {
|
||||
// Reset storage about focus on this chat!
|
||||
if(Interface.chat_focus_hash == hash)
|
||||
Interface.chat_focus_hash = null;
|
||||
});
|
||||
|
||||
inputDetect.keypress(function(e) {
|
||||
// Enter key
|
||||
if(e.keyCode == 13) {
|
||||
// Add a new line
|
||||
if(e.shiftKey || e.ctrlKey) {
|
||||
inputDetect.val(inputDetect.val() + '\n');
|
||||
} else {
|
||||
// Send the message
|
||||
Message.send(hash, 'chat');
|
||||
|
||||
// Reset the composing database entry
|
||||
DataStore.setDB(Connection.desktop_hash, 'chatstate', xid, 'off');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// Scroll in chat content
|
||||
$('#page-engine #' + hash + ' .content').scroll(function() {
|
||||
var self = this;
|
||||
|
||||
if(Features.enabledMAM() && !(xid in MAM.map_pending)) {
|
||||
var has_state = xid in MAM.map_states;
|
||||
var rsm_count = has_state ? MAM.map_states[xid].rsm.count : 1;
|
||||
var rsm_before = has_state ? MAM.map_states[xid].rsm.first : '';
|
||||
|
||||
// Request more archives?
|
||||
if(rsm_count > 0 && $(this).scrollTop() < MAM.SCROLL_THRESHOLD) {
|
||||
var was_scroll_top = $(self).scrollTop() <= 32;
|
||||
var wait_mam = $('#' + hash).find('.wait-mam');
|
||||
wait_mam.show();
|
||||
|
||||
MAM.getArchives({
|
||||
'with': xid
|
||||
}, {
|
||||
'max': MAM.REQ_MAX,
|
||||
'before': rsm_before
|
||||
}, function() {
|
||||
var wait_mam_height = was_scroll_top ? 0 : wait_mam.height();
|
||||
wait_mam.hide();
|
||||
|
||||
// Restore scroll?
|
||||
if($(self).scrollTop() < MAM.SCROLL_THRESHOLD) {
|
||||
var sel_mam_chunk = $(self).find('.mam-chunk:first');
|
||||
|
||||
var cont_padding_top = parseInt($(self).css('padding-top').replace(/[^-\d\.]/g, ''));
|
||||
var cont_one_group_margin_bottom = parseInt(sel_mam_chunk.find('.one-group:last').css('margin-bottom').replace(/[^-\d\.]/g, ''));
|
||||
var cont_mam_chunk_height = sel_mam_chunk.height();
|
||||
|
||||
$(self).scrollTop(wait_mam_height + cont_padding_top + cont_one_group_margin_bottom + cont_mam_chunk_height);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Chatstate events
|
||||
ChatState.events(inputDetect, xid, hash, 'chat');
|
||||
// Input events
|
||||
ChatState.events(input_sel, xid, hash, 'chat');
|
||||
Markers.events(input_sel, xid, hash, 'chat');
|
||||
} catch(e) {
|
||||
Console.error('Chat.create', e);
|
||||
}
|
||||
|
|
|
@ -36,8 +36,9 @@ var ChatState = (function () {
|
|||
// If the friend client supports chatstates and is online
|
||||
if((user_type == 'groupchat') || ((user_type == 'chat') && $('#' + hash + ' .message-area').attr('data-chatstates') && !Common.exists('#page-switch .' + hash + ' .unavailable'))) {
|
||||
// Already sent?
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'currentchatstate', xid) == state)
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'currentchatstate', xid) == state) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Write the state
|
||||
DataStore.setDB(Connection.desktop_hash, 'currentchatstate', xid, state);
|
||||
|
@ -48,7 +49,9 @@ var ChatState = (function () {
|
|||
aMsg.setType(user_type);
|
||||
|
||||
// Append the chatstate node
|
||||
aMsg.appendNode(state, {'xmlns': NS_CHATSTATES});
|
||||
aMsg.appendNode(state, {
|
||||
'xmlns': NS_CHATSTATES
|
||||
});
|
||||
|
||||
// Send this!
|
||||
con.send(aMsg);
|
||||
|
@ -76,8 +79,9 @@ var ChatState = (function () {
|
|||
self.reset(hash, type);
|
||||
|
||||
// "gone" state not allowed
|
||||
if(state != 'gone')
|
||||
if(state != 'gone') {
|
||||
$('#page-engine .page-engine-chan .user.' + hash).addClass(state);
|
||||
}
|
||||
}
|
||||
|
||||
// Chat
|
||||
|
@ -125,7 +129,9 @@ var ChatState = (function () {
|
|||
$('#' + hash + ' .chatstate').remove();
|
||||
|
||||
// We create the chatstate
|
||||
$('#' + hash + ' .content').after('<div class="' + state + ' chatstate">' + text + '</div>');
|
||||
$('#' + hash + ' .content').after(
|
||||
'<div class="' + state + ' chatstate">' + text + '</div>'
|
||||
);
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('ChatState.display', e);
|
||||
|
@ -147,10 +153,11 @@ var ChatState = (function () {
|
|||
// Define the selector
|
||||
var selector;
|
||||
|
||||
if(type == 'groupchat')
|
||||
if(type == 'groupchat') {
|
||||
selector = $('#page-engine .page-engine-chan .user.' + hash);
|
||||
else
|
||||
} else {
|
||||
selector = $('#page-switch .' + hash + ' .name');
|
||||
}
|
||||
|
||||
// Reset!
|
||||
selector.removeClass('active composing paused inactive gone');
|
||||
|
@ -202,30 +209,33 @@ var ChatState = (function () {
|
|||
|
||||
target.focus(function() {
|
||||
// Not needed
|
||||
if(target.is(':disabled'))
|
||||
if(target.is(':disabled')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Something was written, user started writing again
|
||||
if($(this).val())
|
||||
if($(this).val()) {
|
||||
self.send('composing', xid, hash);
|
||||
}
|
||||
|
||||
// Chat only: Nothing in the input, user is active
|
||||
else if(type == 'chat')
|
||||
else if(type == 'chat') {
|
||||
self.send('active', xid, hash);
|
||||
}
|
||||
});
|
||||
|
||||
target.blur(function() {
|
||||
// Not needed
|
||||
if(target.is(':disabled'))
|
||||
if(target.is(':disabled')) {
|
||||
return;
|
||||
|
||||
// Something was written, user paused
|
||||
if($(this).val())
|
||||
self.send('paused', xid, hash);
|
||||
}
|
||||
|
||||
// Chat only: Nothing in the input, user is inactive
|
||||
else if(type == 'chat')
|
||||
// Something was written, user paused
|
||||
if($(this).val()) {
|
||||
self.send('paused', xid, hash);
|
||||
} else if(type == 'chat') {
|
||||
self.send('inactive', xid, hash);
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('ChatState.events', e);
|
||||
|
|
|
@ -20,6 +20,10 @@ var Common = (function () {
|
|||
var self = {};
|
||||
|
||||
|
||||
/* Constants */
|
||||
self.R_DOMAIN_NAME = /^(([a-zA-Z0-9-\.]+)\.)?[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9]\.[a-zA-Z]{2,}$/i;
|
||||
|
||||
|
||||
/**
|
||||
* Checks if an element exists in the DOM
|
||||
* @public
|
||||
|
@ -109,6 +113,29 @@ var Common = (function () {
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* Matches a domain name
|
||||
* @public
|
||||
* @param {string} xid
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.isDomain = function(xid) {
|
||||
|
||||
is_domain = false;
|
||||
|
||||
try {
|
||||
if(xid.match(self.R_DOMAIN_NAME)) {
|
||||
is_domain = true;
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Common.isDomain', e);
|
||||
} finally {
|
||||
return is_domain;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Generates the good XID
|
||||
* @public
|
||||
|
@ -120,20 +147,21 @@ var Common = (function () {
|
|||
|
||||
try {
|
||||
// XID needs to be transformed
|
||||
// .. and made lowercase (uncertain though this is the right place...)
|
||||
xid = xid.toLowerCase();
|
||||
|
||||
if(xid && (xid.indexOf('@') == -1)) {
|
||||
// Groupchat
|
||||
if(type == 'groupchat')
|
||||
if(xid && (xid.indexOf('@') === -1)) {
|
||||
// Groupchat XID
|
||||
if(type == 'groupchat') {
|
||||
return xid + '@' + HOST_MUC;
|
||||
}
|
||||
|
||||
// One-to-one chat
|
||||
if(xid.indexOf('.') == -1)
|
||||
return xid + '@' + HOST_MAIN;
|
||||
// Gateway XID
|
||||
if(self.isDomain(xid) === true) {
|
||||
return xid;
|
||||
}
|
||||
|
||||
// It might be a gateway?
|
||||
return xid;
|
||||
// User XID
|
||||
return xid + '@' + HOST_MAIN;
|
||||
}
|
||||
|
||||
// Nothing special (yet bare XID)
|
||||
|
@ -190,14 +218,16 @@ var Common = (function () {
|
|||
self.strAfterLast = function(given_char, str) {
|
||||
|
||||
try {
|
||||
if(!given_char || !str)
|
||||
if(!given_char || !str) {
|
||||
return '';
|
||||
}
|
||||
|
||||
var char_index = str.lastIndexOf(given_char);
|
||||
var str_return = str;
|
||||
|
||||
if(char_index >= 0)
|
||||
if(char_index >= 0) {
|
||||
str_return = str.substr(char_index + 1);
|
||||
}
|
||||
|
||||
return str_return;
|
||||
} catch(e) {
|
||||
|
@ -223,10 +253,11 @@ var Common = (function () {
|
|||
|
||||
// We split if necessary the string
|
||||
if(index !== -1) {
|
||||
if(i === 0)
|
||||
if(i === 0) {
|
||||
toStr = toStr.substr(0, index);
|
||||
else
|
||||
} else {
|
||||
toStr = toStr.substr(index + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// We return the value
|
||||
|
@ -309,8 +340,9 @@ var Common = (function () {
|
|||
// Spec: http://tools.ietf.org/html/rfc6122#appendix-A
|
||||
|
||||
try {
|
||||
if(!node)
|
||||
if(!node) {
|
||||
return node;
|
||||
}
|
||||
|
||||
// Remove prohibited chars
|
||||
var prohibited_chars = ['"', '&', '\'', '/', ':', '<', '>', '@'];
|
||||
|
@ -347,6 +379,40 @@ var Common = (function () {
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* Escapes quotes in a string
|
||||
* @public
|
||||
* @param {string} str
|
||||
* @return {string}
|
||||
*/
|
||||
self.escapeQuotes = function(str) {
|
||||
|
||||
try {
|
||||
return escape(self.encodeQuotes(str));
|
||||
} catch(e) {
|
||||
Console.error('Common.escapeQuotes', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Unescapes quotes in a string
|
||||
* @public
|
||||
* @param {string} str
|
||||
* @return {string}
|
||||
*/
|
||||
self.unescapeQuotes = function(str) {
|
||||
|
||||
try {
|
||||
return unescape(str);
|
||||
} catch(e) {
|
||||
Console.error('Common.unescapeQuotes', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the bare XID from a XID
|
||||
* @public
|
||||
|
@ -360,8 +426,8 @@ var Common = (function () {
|
|||
xid = self.cutResource(xid);
|
||||
|
||||
// Launch nodeprep
|
||||
if(xid.indexOf('@') != -1) {
|
||||
xid = self.nodeprep(self.getXIDNick(xid)) + '@' + self.getXIDHost(xid);
|
||||
if(xid.indexOf('@') !== -1) {
|
||||
xid = self.nodeprep(self.getXIDNick(xid, true)) + '@' + self.getXIDHost(xid);
|
||||
}
|
||||
|
||||
return xid;
|
||||
|
@ -386,8 +452,9 @@ var Common = (function () {
|
|||
var resource = self.thisResource(xid);
|
||||
|
||||
// Any resource?
|
||||
if(resource)
|
||||
if(resource) {
|
||||
full += '/' + resource;
|
||||
}
|
||||
|
||||
return full;
|
||||
} catch(e) {
|
||||
|
@ -401,14 +468,18 @@ var Common = (function () {
|
|||
* Gets the nick from a XID
|
||||
* @public
|
||||
* @param {string} aXID
|
||||
* @param {boolean} raw_explode
|
||||
* @return {string}
|
||||
*/
|
||||
self.getXIDNick = function(aXID) {
|
||||
self.getXIDNick = function(aXID, raw_explode) {
|
||||
|
||||
try {
|
||||
// Gateway nick?
|
||||
if(aXID.match(/\\40/))
|
||||
return self.explodeThis('\\40', aXID, 0);
|
||||
if(raw_explode !== true) {
|
||||
// Gateway nick?
|
||||
if(aXID.match(/\\40/)) {
|
||||
return self.explodeThis('\\40', aXID, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return self.explodeThis('@', aXID, 0);
|
||||
} catch(e) {
|
||||
|
@ -549,7 +620,7 @@ var Common = (function () {
|
|||
is_gateway = true;
|
||||
|
||||
try {
|
||||
if(xid.indexOf('@') != -1) {
|
||||
if(xid.indexOf('@') !== -1) {
|
||||
is_gateway = false;
|
||||
}
|
||||
} catch(e) {
|
||||
|
@ -618,12 +689,14 @@ var Common = (function () {
|
|||
|
||||
try {
|
||||
// Negative number (without first 0)
|
||||
if(i > -10 && i < 0)
|
||||
if(i > -10 && i < 0) {
|
||||
return '-0' + (i * -1);
|
||||
}
|
||||
|
||||
// Positive number (without first 0)
|
||||
if(i < 10 && i >= 0)
|
||||
if(i < 10 && i >= 0) {
|
||||
return '0' + i;
|
||||
}
|
||||
|
||||
// All is okay
|
||||
return i;
|
||||
|
@ -643,23 +716,31 @@ var Common = (function () {
|
|||
*/
|
||||
self.escapeRegex = function(query) {
|
||||
|
||||
if (query instanceof Array) {
|
||||
var result = new Array(query.length);
|
||||
for(i=0; i<query.length; i++) {
|
||||
var result = [];
|
||||
|
||||
try {
|
||||
if(query instanceof Array) {
|
||||
result = [query.length];
|
||||
|
||||
for(i = 0; i < query.length; i++) {
|
||||
try {
|
||||
result[i] = Common.escapeRegex(query[i]);
|
||||
} catch(e) {
|
||||
Console.error('Common.escapeRegex', e);
|
||||
result[i] = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
result[i] = Common.escapeRegex(query[i]);
|
||||
result = query.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
|
||||
} catch(e) {
|
||||
Console.error('Common.escapeRegex', e);
|
||||
result[i] = null;
|
||||
Console.error('Common.escapeRegex[inner]', e);
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Common.escapeRegex', e);
|
||||
} finally {
|
||||
return result;
|
||||
} else {
|
||||
try {
|
||||
return query.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
|
||||
} catch(e) {
|
||||
Console.error('Common.escapeRegex', e);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -29,6 +29,205 @@ var Connection = (function () {
|
|||
self.resume = false;
|
||||
|
||||
|
||||
/**
|
||||
* Do registration on Register API
|
||||
* @private
|
||||
* @param {string} username
|
||||
* @param {string} domain
|
||||
* @param {string} pass
|
||||
* @param {string} captcha
|
||||
* @return {boolean}
|
||||
*/
|
||||
self._doRegisterAPI = function(username, domain, pass, captcha) {
|
||||
|
||||
var is_success = false;
|
||||
|
||||
try {
|
||||
// Show the waiting image
|
||||
Interface.showGeneralWait();
|
||||
|
||||
// Change the page title
|
||||
Interface.title('wait');
|
||||
|
||||
// Send request
|
||||
$.post('./server/register.php', {username: username, domain: domain, password: pass, captcha: captcha}, function(data) {
|
||||
// Error registering
|
||||
Interface.removeGeneralWait();
|
||||
Interface.title('home');
|
||||
|
||||
// In all case, update CAPTCHA
|
||||
$('#home img.captcha_img').attr('src', './server/captcha.php?id=' + genID());
|
||||
$('#home input.captcha').val('');
|
||||
|
||||
// Registration okay
|
||||
if($(data).find('query status').text() == '1') {
|
||||
is_success = true;
|
||||
self.handleRegistered();
|
||||
} else {
|
||||
// Show error message
|
||||
var error_message = '';
|
||||
|
||||
switch($(data).find('query message').text()) {
|
||||
case 'CAPTCHA Not Matching':
|
||||
error_message = Common._e("The security code you entered is invalid. Please retry with another one.");
|
||||
|
||||
$('#home input.captcha').focus();
|
||||
|
||||
break;
|
||||
|
||||
case 'Username Unavailable':
|
||||
error_message = Common._e("The username you picked is not available. Please try another one.");
|
||||
|
||||
$('#home input.nick').focus();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
error_message = Common._e("There was an error registering your account. Please retry.");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(error_message) {
|
||||
Errors.show('', error_message, '');
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Connection._doRegisterAPI', e);
|
||||
} finally {
|
||||
return is_success;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Do registration throug in-band stream
|
||||
* @private
|
||||
* @param {string} username
|
||||
* @param {string} domain
|
||||
* @param {string} pass
|
||||
* @return {boolean}
|
||||
*/
|
||||
self._doRegisterInBand = function(username, domain, pass) {
|
||||
|
||||
var is_success = true;
|
||||
|
||||
try {
|
||||
if(Common.hasWebSocket()) {
|
||||
// WebSocket supported & configured
|
||||
con = new JSJaCWebSocketConnection({
|
||||
httpbase: HOST_WEBSOCKET
|
||||
});
|
||||
} else {
|
||||
var httpbase = (HOST_BOSH_MAIN || HOST_BOSH);
|
||||
|
||||
// Check BOSH origin
|
||||
BOSH_SAME_ORIGIN = Origin.isSame(httpbase);
|
||||
|
||||
// We create the new http-binding connection
|
||||
con = new JSJaCHttpBindingConnection({
|
||||
httpbase: httpbase
|
||||
});
|
||||
}
|
||||
|
||||
// We setup the connection !
|
||||
con.registerHandler('onconnect', self.handleRegistered);
|
||||
con.registerHandler('onerror', Errors.handle);
|
||||
|
||||
con.connect({
|
||||
'domain': $.trim(domain),
|
||||
'username': $.trim(username),
|
||||
'resource': JAPPIX_RESOURCE + ' Register (' + (new Date()).getTime() + ')',
|
||||
'pass': pass,
|
||||
'register': true,
|
||||
'secure': true,
|
||||
'xmllang': XML_LANG
|
||||
});
|
||||
|
||||
// Show the waiting image
|
||||
Interface.showGeneralWait();
|
||||
|
||||
// Change the page title
|
||||
Interface.title('wait');
|
||||
} catch(e) {
|
||||
Console.error('Connection._doRegisterInBand', e);
|
||||
is_success = false;
|
||||
} finally {
|
||||
return is_success;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Attaches reconnect events
|
||||
* @private
|
||||
* @param {string} mode
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._eventsReconnect = function(mode) {
|
||||
|
||||
try {
|
||||
// Click events
|
||||
if(mode == 'normal') {
|
||||
$('#reconnect a.finish.cancel').click(function() {
|
||||
return self.cancelReconnect();
|
||||
});
|
||||
}
|
||||
|
||||
$('#reconnect a.finish.reconnect').click(function() {
|
||||
return self.acceptReconnect(mode);
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Connection._eventsReconnect', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Schedules the next auto reconnect
|
||||
* @private
|
||||
* @param {string} mode
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._scheduleReconnect = function(mode) {
|
||||
|
||||
try {
|
||||
// Try to reconnect automatically after a while
|
||||
if(self.reconnect_try < 5) {
|
||||
self.reconnect_timer = 5 + (5 * self.reconnect_try);
|
||||
} else {
|
||||
self.reconnect_timer = 120;
|
||||
}
|
||||
|
||||
// Change the try number
|
||||
self.reconnect_try++;
|
||||
|
||||
// Fire the event!
|
||||
$('#reconnect a.finish.reconnect').everyTime('1s', function() {
|
||||
// We can reconnect!
|
||||
if(self.reconnect_timer === 0) {
|
||||
return self.acceptReconnect(mode);
|
||||
}
|
||||
|
||||
// Button text
|
||||
if(self.reconnect_timer <= 10) {
|
||||
$(this).text(Common._e("Reconnect") + ' (' + self.reconnect_timer + ')');
|
||||
}
|
||||
|
||||
// Remove 1 second
|
||||
self.reconnect_timer--;
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Connection._scheduleReconnect', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Does the user login
|
||||
* @public
|
||||
|
@ -45,7 +244,7 @@ var Connection = (function () {
|
|||
|
||||
try {
|
||||
// get optionnal conn handlers
|
||||
oExtend = loginOpts || {};
|
||||
extend_obj = loginOpts || {};
|
||||
|
||||
// We remove the not completed class to avoid problems
|
||||
$('#home .loginer input').removeClass('please-complete');
|
||||
|
@ -71,7 +270,7 @@ var Connection = (function () {
|
|||
}
|
||||
|
||||
// And we handle everything that happen
|
||||
self.setupCon(con, oExtend);
|
||||
self.setupCon(con, extend_obj);
|
||||
|
||||
// Generate a resource
|
||||
var random_resource = DataStore.getDB(self.desktop_hash, 'session', 'resource');
|
||||
|
@ -79,17 +278,17 @@ var Connection = (function () {
|
|||
if(!random_resource) {
|
||||
random_resource = lResource + ' (' + (new Date()).getTime() + ')';
|
||||
}
|
||||
|
||||
// We retrieve what the user typed in the login inputs
|
||||
oArgs = {};
|
||||
oArgs.domain = $.trim(lServer);
|
||||
oArgs.username = $.trim(lNick);
|
||||
oArgs.resource = random_resource;
|
||||
oArgs.pass = lPass;
|
||||
oArgs.secure = true;
|
||||
oArgs.xmllang = XML_LANG;
|
||||
|
||||
self.desktop_hash = 'jd.' + hex_md5(oArgs.username + '@' + oArgs.domain);
|
||||
var con_args = {
|
||||
'domain': lServer.trim(),
|
||||
'username': lNick.trim(),
|
||||
'resource': random_resource,
|
||||
'pass': lPass,
|
||||
'secure': true,
|
||||
'xmllang': XML_LANG
|
||||
};
|
||||
|
||||
self.desktop_hash = 'jd.' + hex_md5(con_args.username + '@' + con_args.domain);
|
||||
|
||||
// Store the resource (for reconnection)
|
||||
DataStore.setDB(self.desktop_hash, 'session', 'resource', random_resource);
|
||||
|
@ -101,7 +300,7 @@ var Connection = (function () {
|
|||
DataStore.setDB(self.desktop_hash, 'priority', 1, lPriority);
|
||||
|
||||
// We connect !
|
||||
con.connect(oArgs);
|
||||
con.connect(con_args);
|
||||
|
||||
// Change the page title
|
||||
Interface.title('wait');
|
||||
|
@ -169,7 +368,9 @@ var Connection = (function () {
|
|||
// We change the registered information text
|
||||
$('#home .homediv.registerer').append(
|
||||
'<div class="info success">' +
|
||||
Common._e("You have been registered, here is your XMPP address:") + ' <b>' + username.htmlEnc() + '@' + domain.htmlEnc() + '</b> - <a href="#">' + Common._e("Login") + '</a>' +
|
||||
Common._e("You have been registered, here is your XMPP address:") +
|
||||
' <b>' + username.htmlEnc() + '@' + domain.htmlEnc() + '</b> - ' +
|
||||
'<a href="#">' + Common._e("Login") + '</a>' +
|
||||
'</div>'
|
||||
);
|
||||
|
||||
|
@ -179,102 +380,9 @@ var Connection = (function () {
|
|||
});
|
||||
|
||||
if((REGISTER_API == 'on') && (domain == HOST_MAIN) && captcha) {
|
||||
// Show the waiting image
|
||||
Interface.showGeneralWait();
|
||||
|
||||
// Change the page title
|
||||
Interface.title('wait');
|
||||
|
||||
// Send request
|
||||
$.post('./server/register.php', {username: username, domain: domain, password: pass, captcha: captcha}, function(data) {
|
||||
// Error registering
|
||||
Interface.removeGeneralWait();
|
||||
Interface.title('home');
|
||||
|
||||
// In all case, update CAPTCHA
|
||||
$('#home img.captcha_img').attr('src', './server/captcha.php?id=' + genID());
|
||||
$('#home input.captcha').val('');
|
||||
|
||||
// Registration okay
|
||||
if($(data).find('query status').text() == '1') {
|
||||
self.handleRegistered();
|
||||
} else {
|
||||
// Show error message
|
||||
var error_message = '';
|
||||
|
||||
switch($(data).find('query message').text()) {
|
||||
case 'CAPTCHA Not Matching':
|
||||
error_message = Common._e("The security code you entered is invalid. Please retry with another one.");
|
||||
|
||||
$('#home input.captcha').focus();
|
||||
|
||||
break;
|
||||
|
||||
case 'Username Unavailable':
|
||||
error_message = Common._e("The username you picked is not available. Please try another one.");
|
||||
|
||||
$('#home input.nick').focus();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
error_message = Common._e("There was an error registering your account. Please retry.");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(error_message)
|
||||
Errors.show('', error_message, '');
|
||||
}
|
||||
});
|
||||
self._doRegisterAPI(username, domain, pass, captcha);
|
||||
} else {
|
||||
try {
|
||||
oArgs = {};
|
||||
|
||||
if(Common.hasWebSocket()) {
|
||||
// WebSocket supported & configured
|
||||
con = new JSJaCWebSocketConnection({
|
||||
httpbase: HOST_WEBSOCKET
|
||||
});
|
||||
} else {
|
||||
var httpbase = (HOST_BOSH_MAIN || HOST_BOSH);
|
||||
|
||||
// Check BOSH origin
|
||||
BOSH_SAME_ORIGIN = Origin.isSame(httpbase);
|
||||
|
||||
// We create the new http-binding connection
|
||||
con = new JSJaCHttpBindingConnection({
|
||||
httpbase: httpbase
|
||||
});
|
||||
}
|
||||
|
||||
// We setup the connection !
|
||||
con.registerHandler('onconnect', self.handleRegistered);
|
||||
con.registerHandler('onerror', Errors.handle);
|
||||
|
||||
// We retrieve what the user typed in the register inputs
|
||||
oArgs = {};
|
||||
oArgs.domain = $.trim(domain);
|
||||
oArgs.username = $.trim(username);
|
||||
oArgs.resource = JAPPIX_RESOURCE + ' Register (' + (new Date()).getTime() + ')';
|
||||
oArgs.pass = pass;
|
||||
oArgs.register = true;
|
||||
oArgs.secure = true;
|
||||
oArgs.xmllang = XML_LANG;
|
||||
|
||||
con.connect(oArgs);
|
||||
|
||||
// Show the waiting image
|
||||
Interface.showGeneralWait();
|
||||
|
||||
// Change the page title
|
||||
Interface.title('wait');
|
||||
}
|
||||
|
||||
catch(e) {
|
||||
// Logs errors
|
||||
Console.error('doRegister', e);
|
||||
}
|
||||
self._doRegisterInBand(username, domain, pass);
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Connection.doRegister', e);
|
||||
|
@ -295,30 +403,28 @@ var Connection = (function () {
|
|||
try {
|
||||
Console.info('Trying to login anonymously...');
|
||||
|
||||
var aPath = '#home .anonymouser ';
|
||||
var room = $(aPath + '.room').val();
|
||||
var nick = $(aPath + '.nick').val();
|
||||
var path_sel = $('#home .anonymouser');
|
||||
var room = path_sel.find('.room').val();
|
||||
var nick = path_sel.find('.nick').val();
|
||||
|
||||
// If the form is correctly completed
|
||||
// Form correctly completed?
|
||||
if(room && nick) {
|
||||
// We remove the not completed class to avoid problems
|
||||
$('#home .anonymouser input').removeClass('please-complete');
|
||||
|
||||
// Redirect the user to the anonymous room
|
||||
window.location.href = JAPPIX_LOCATION + '?r=' + room + '&n=' + nick;
|
||||
}
|
||||
|
||||
// We check if the form is entirely completed
|
||||
else {
|
||||
$(aPath + 'input[type="text"]').each(function() {
|
||||
var select = $(this);
|
||||
} else {
|
||||
path_sel.find('input[type="text"]').each(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
if(!select.val())
|
||||
if(!this_sel.val()) {
|
||||
$(document).oneTime(10, function() {
|
||||
select.addClass('please-complete').focus();
|
||||
this_sel.addClass('please-complete').focus();
|
||||
});
|
||||
else
|
||||
select.removeClass('please-complete');
|
||||
} else {
|
||||
this_sel.removeClass('please-complete');
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch(e) {
|
||||
|
@ -355,7 +461,7 @@ var Connection = (function () {
|
|||
Interface.removeGeneralWait();
|
||||
|
||||
// Init Jingle
|
||||
Jingle.init();
|
||||
Call.init();
|
||||
} catch(e) {
|
||||
Console.error('Connection.handleConnected', e);
|
||||
}
|
||||
|
@ -374,8 +480,9 @@ var Connection = (function () {
|
|||
// Not resumed?
|
||||
if(!self.resume) {
|
||||
// Remember the session?
|
||||
if(DataStore.getDB(self.desktop_hash, 'remember', 'session'))
|
||||
if(DataStore.getDB(self.desktop_hash, 'remember', 'session')) {
|
||||
DataStore.setPersistent('global', 'session', 1, self.current_session);
|
||||
}
|
||||
|
||||
// We show the chatting app.
|
||||
Talk.create();
|
||||
|
@ -431,24 +538,32 @@ var Connection = (function () {
|
|||
* Setups the normal connection
|
||||
* @public
|
||||
* @param {object} con
|
||||
* @param {object} oExtend
|
||||
* @param {object} extend_obj
|
||||
* @return {undefined}
|
||||
*/
|
||||
self.setupCon = function(con, oExtend) {
|
||||
self.setupCon = function(con, extend_obj) {
|
||||
|
||||
try {
|
||||
// Setup connection handlers
|
||||
con.registerHandler('message', Message.handle);
|
||||
con.registerHandler('presence', Presence.handle);
|
||||
con.registerHandler('iq', IQ.handle);
|
||||
con.registerHandler('onconnect', self.handleConnected);
|
||||
con.registerHandler('onerror', Errors.handle);
|
||||
con.registerHandler('ondisconnect', self.handleDisconnected);
|
||||
|
||||
var connection_handlers = {
|
||||
'message': Message.handle,
|
||||
'presence': Presence.handle,
|
||||
'iq': IQ.handle,
|
||||
'onconnect': self.handleConnected,
|
||||
'onerror': Errors.handle,
|
||||
'ondisconnect': self.handleDisconnected
|
||||
};
|
||||
|
||||
for(var cur_handler in connection_handlers) {
|
||||
con.registerHandler(
|
||||
cur_handler,
|
||||
connection_handlers[cur_handler]
|
||||
);
|
||||
}
|
||||
|
||||
// Extended handlers
|
||||
oExtend = oExtend || {};
|
||||
extend_obj = extend_obj || {};
|
||||
|
||||
jQuery.each(oExtend, function(keywd,funct) {
|
||||
jQuery.each(extend_obj, function(keywd,funct) {
|
||||
con.registerHandler(keywd, funct);
|
||||
});
|
||||
} catch(e) {
|
||||
|
@ -559,51 +674,25 @@ var Connection = (function () {
|
|||
|
||||
// Create the HTML code
|
||||
var html = '<div id="reconnect" class="lock">' +
|
||||
'<div class="pane">' +
|
||||
Common._e("Due to a network issue, you were disconnected. What do you want to do now?");
|
||||
'<div class="pane">' +
|
||||
Common._e("Due to a network issue, you were disconnected. What do you want to do now?");
|
||||
|
||||
// Can we cancel reconnection?
|
||||
if(mode == 'normal')
|
||||
if(mode == 'normal') {
|
||||
html += '<a href="#" class="finish cancel">' + Common._e("Cancel") + '</a>';
|
||||
}
|
||||
|
||||
html += '<a href="#" class="finish reconnect">' + Common._e("Reconnect") + '</a>' +
|
||||
'</div></div>';
|
||||
'</div></div>';
|
||||
|
||||
// Append the code
|
||||
$('body').append(html);
|
||||
|
||||
// Click events
|
||||
if(mode == 'normal')
|
||||
$('#reconnect a.finish.cancel').click(function() {
|
||||
return self.cancelReconnect();
|
||||
});
|
||||
// Attach events
|
||||
self._eventsReconnect(mode);
|
||||
|
||||
$('#reconnect a.finish.reconnect').click(function() {
|
||||
return self.acceptReconnect(mode);
|
||||
});
|
||||
|
||||
// Try to reconnect automatically after a while
|
||||
if(self.reconnect_try < 5)
|
||||
self.reconnect_timer = 5 + (5 * self.reconnect_try);
|
||||
else
|
||||
self.reconnect_timer = 120;
|
||||
|
||||
// Change the try number
|
||||
self.reconnect_try++;
|
||||
|
||||
// Fire the event!
|
||||
$('#reconnect a.finish.reconnect').everyTime('1s', function() {
|
||||
// We can reconnect!
|
||||
if(self.reconnect_timer === 0)
|
||||
return self.acceptReconnect(mode);
|
||||
|
||||
// Button text
|
||||
if(self.reconnect_timer <= 10)
|
||||
$(this).text(Common._e("Reconnect") + ' (' + self.reconnect_timer + ')');
|
||||
|
||||
// Remove 1 second
|
||||
self.reconnect_timer--;
|
||||
});
|
||||
// Schedule next reconnect
|
||||
self._scheduleReconnect(mode);
|
||||
|
||||
// Page title
|
||||
Interface.updateTitle();
|
||||
|
@ -634,9 +723,11 @@ var Connection = (function () {
|
|||
|
||||
// Reset some various stuffs
|
||||
var groupchats = '#page-engine .page-engine-chan[data-type="groupchat"]';
|
||||
$(groupchats + ' .list .role').hide();
|
||||
$(groupchats + ' .one-group, ' + groupchats + ' .list .user').remove();
|
||||
$(groupchats).attr('data-initial', 'false');
|
||||
var groupchats_sel = $(groupchats);
|
||||
|
||||
groupchats_sel.find('.list .role').hide();
|
||||
groupchats_sel.find('.one-group, ' + groupchats + ' .list .user').remove();
|
||||
groupchats_sel.attr('data-initial', 'false');
|
||||
|
||||
// Stop the timer
|
||||
$('#reconnect a.finish.reconnect').stopTime();
|
||||
|
@ -645,10 +736,11 @@ var Connection = (function () {
|
|||
$('#reconnect').remove();
|
||||
|
||||
// Try to login again
|
||||
if(mode == 'normal')
|
||||
if(mode == 'normal') {
|
||||
self.loginFromSession(Common.XMLFromString(self.current_session));
|
||||
else if(mode == 'anonymous')
|
||||
} else if(mode == 'anonymous') {
|
||||
Anonymous.login(HOST_ANONYMOUS);
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Connection.acceptReconnect', e);
|
||||
} finally {
|
||||
|
@ -817,7 +909,14 @@ var Connection = (function () {
|
|||
|
||||
try {
|
||||
// Generate a session XML to be stored
|
||||
session_xml = '<session><stored>true</stored><domain>' + lServer.htmlEnc() + '</domain><username>' + lNick.htmlEnc() + '</username><resource>' + lResource.htmlEnc() + '</resource><password>' + lPass.htmlEnc() + '</password><priority>' + lPriority.htmlEnc() + '</priority></session>';
|
||||
session_xml = '<session>' +
|
||||
'<stored>true</stored>' +
|
||||
'<domain>' + lServer.htmlEnc() + '</domain>' +
|
||||
'<username>' + lNick.htmlEnc() + '</username>' +
|
||||
'<resource>' + lResource.htmlEnc() + '</resource>' +
|
||||
'<password>' + lPass.htmlEnc() + '</password>' +
|
||||
'<priority>' + lPriority.htmlEnc() + '</priority>' +
|
||||
'</session>';
|
||||
|
||||
// Save the session parameters (for reconnect if network issue)
|
||||
self.current_session = session_xml;
|
||||
|
@ -848,8 +947,9 @@ var Connection = (function () {
|
|||
$(window).bind('beforeunload', Connection.terminate);
|
||||
|
||||
// Nothing to do when anonymous!
|
||||
if(Utils.isAnonymous())
|
||||
if(Utils.isAnonymous()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Connection params submitted in URL?
|
||||
if(XMPPLinks.links_var.u && XMPPLinks.links_var.q) {
|
||||
|
@ -865,7 +965,15 @@ var Connection = (function () {
|
|||
// Must store session?
|
||||
if(XMPPLinks.links_var.h && (XMPPLinks.links_var.h === '1')) {
|
||||
// Store session
|
||||
var session_xml = self.storeSession(login_nick, login_server, login_pwd, login_resource, login_priority, true);
|
||||
var session_xml = self.storeSession(
|
||||
login_nick,
|
||||
login_server,
|
||||
login_pwd,
|
||||
login_resource,
|
||||
login_priority,
|
||||
true
|
||||
);
|
||||
|
||||
DataStore.setPersistent('global', 'session', 1, session_xml);
|
||||
|
||||
// Redirect to a clean URL
|
||||
|
@ -900,10 +1008,7 @@ var Connection = (function () {
|
|||
self.loginFromSession(session);
|
||||
|
||||
Console.info('Saved session found, resuming it...');
|
||||
}
|
||||
|
||||
// Not connected, maybe a XMPP link is submitted?
|
||||
else if((parent.location.hash != '#OK') && XMPPLinks.links_var.x) {
|
||||
} else if((parent.location.hash != '#OK') && XMPPLinks.links_var.x) {
|
||||
Home.change('loginer');
|
||||
|
||||
Console.info('A XMPP link is set, switch to login page.');
|
||||
|
|
|
@ -11,103 +11,109 @@ Authors: Stefan Strigler, Valérian Saliou, Kloadut, Maranda
|
|||
*/
|
||||
|
||||
// XMPP XMLNS attributes
|
||||
var NS_PROTOCOL = 'http://jabber.org/protocol/';
|
||||
var NS_FEATURES = 'http://jabber.org/features/';
|
||||
var NS_CLIENT = 'jabber:client';
|
||||
var NS_IQ = 'jabber:iq:';
|
||||
var NS_X = 'jabber:x:';
|
||||
var NS_IETF = 'urn:ietf:params:xml:ns:';
|
||||
var NS_IETF_XMPP = NS_IETF + 'xmpp-';
|
||||
var NS_XMPP = 'urn:xmpp:';
|
||||
var NS_PROTOCOL = 'http://jabber.org/protocol/';
|
||||
var NS_FEATURES = 'http://jabber.org/features/';
|
||||
var NS_CLIENT = 'jabber:client';
|
||||
var NS_IQ = 'jabber:iq:';
|
||||
var NS_X = 'jabber:x:';
|
||||
var NS_IETF = 'urn:ietf:params:xml:ns:';
|
||||
var NS_IETF_XMPP = NS_IETF + 'xmpp-';
|
||||
var NS_XMPP = 'urn:xmpp:';
|
||||
|
||||
var NS_STORAGE = 'storage:';
|
||||
var NS_BOOKMARKS = NS_STORAGE + 'bookmarks';
|
||||
var NS_ROSTERNOTES = NS_STORAGE + 'rosternotes';
|
||||
var NS_STORAGE = 'storage:';
|
||||
var NS_BOOKMARKS = NS_STORAGE + 'bookmarks';
|
||||
var NS_ROSTERNOTES = NS_STORAGE + 'rosternotes';
|
||||
|
||||
var NS_JAPPIX = 'jappix:';
|
||||
var NS_INBOX = NS_JAPPIX + 'inbox';
|
||||
var NS_OPTIONS = NS_JAPPIX + 'options';
|
||||
var NS_JAPPIX = 'jappix:';
|
||||
var NS_INBOX = NS_JAPPIX + 'inbox';
|
||||
var NS_OPTIONS = NS_JAPPIX + 'options';
|
||||
|
||||
var NS_DISCO_ITEMS = NS_PROTOCOL + 'disco#items';
|
||||
var NS_DISCO_INFO = NS_PROTOCOL + 'disco#info';
|
||||
var NS_VCARD = 'vcard-temp';
|
||||
var NS_VCARD_P = NS_VCARD + ':x:update';
|
||||
var NS_IETF_VCARD4 = NS_IETF + 'vcard-4.0';
|
||||
var NS_XMPP_VCARD4 = NS_XMPP + 'vcard4';
|
||||
var NS_URN_ADATA = NS_XMPP + 'avatar:data';
|
||||
var NS_URN_AMETA = NS_XMPP + 'avatar:metadata';
|
||||
var NS_AUTH = NS_IQ + 'auth';
|
||||
var NS_AUTH_ERROR = NS_IQ + 'auth:error';
|
||||
var NS_REGISTER = NS_IQ + 'register';
|
||||
var NS_SEARCH = NS_IQ + 'search';
|
||||
var NS_ROSTER = NS_IQ + 'roster';
|
||||
var NS_PRIVACY = NS_IQ + 'privacy';
|
||||
var NS_PRIVATE = NS_IQ + 'private';
|
||||
var NS_VERSION = NS_IQ + 'version';
|
||||
var NS_TIME = NS_IQ + 'time';
|
||||
var NS_LAST = NS_IQ + 'last';
|
||||
var NS_IQDATA = NS_IQ + 'data';
|
||||
var NS_XDATA = NS_X + 'data';
|
||||
var NS_IQOOB = NS_IQ + 'oob';
|
||||
var NS_XOOB = NS_X + 'oob';
|
||||
var NS_DELAY = NS_X + 'delay';
|
||||
var NS_EXPIRE = NS_X + 'expire';
|
||||
var NS_EVENT = NS_X + 'event';
|
||||
var NS_XCONFERENCE = NS_X + 'conference';
|
||||
var NS_STATS = NS_PROTOCOL + 'stats';
|
||||
var NS_MUC = NS_PROTOCOL + 'muc';
|
||||
var NS_MUC_USER = NS_MUC + '#user';
|
||||
var NS_MUC_ADMIN = NS_MUC + '#admin';
|
||||
var NS_MUC_OWNER = NS_MUC + '#owner';
|
||||
var NS_MUC_CONFIG = NS_MUC + '#roomconfig';
|
||||
var NS_PUBSUB = NS_PROTOCOL + 'pubsub';
|
||||
var NS_PUBSUB_EVENT = NS_PUBSUB + '#event';
|
||||
var NS_PUBSUB_OWNER = NS_PUBSUB + '#owner';
|
||||
var NS_PUBSUB_NMI = NS_PUBSUB + '#node-meta-info';
|
||||
var NS_PUBSUB_NC = NS_PUBSUB + '#node_config';
|
||||
var NS_PUBSUB_CN = NS_PUBSUB + '#config-node';
|
||||
var NS_PUBSUB_RI = NS_PUBSUB + '#retrieve-items';
|
||||
var NS_COMMANDS = NS_PROTOCOL + 'commands';
|
||||
var NS_BOSH = NS_PROTOCOL + 'httpbind';
|
||||
var NS_DISCO_ITEMS = NS_PROTOCOL + 'disco#items';
|
||||
var NS_DISCO_INFO = NS_PROTOCOL + 'disco#info';
|
||||
var NS_VCARD = 'vcard-temp';
|
||||
var NS_VCARD_P = NS_VCARD + ':x:update';
|
||||
var NS_IETF_VCARD4 = NS_IETF + 'vcard-4.0';
|
||||
var NS_XMPP_VCARD4 = NS_XMPP + 'vcard4';
|
||||
var NS_URN_ADATA = NS_XMPP + 'avatar:data';
|
||||
var NS_URN_AMETA = NS_XMPP + 'avatar:metadata';
|
||||
var NS_AUTH = NS_IQ + 'auth';
|
||||
var NS_AUTH_ERROR = NS_IQ + 'auth:error';
|
||||
var NS_REGISTER = NS_IQ + 'register';
|
||||
var NS_SEARCH = NS_IQ + 'search';
|
||||
var NS_ROSTER = NS_IQ + 'roster';
|
||||
var NS_PRIVACY = NS_IQ + 'privacy';
|
||||
var NS_PRIVATE = NS_IQ + 'private';
|
||||
var NS_VERSION = NS_IQ + 'version';
|
||||
var NS_TIME = NS_IQ + 'time';
|
||||
var NS_LAST = NS_IQ + 'last';
|
||||
var NS_IQDATA = NS_IQ + 'data';
|
||||
var NS_XDATA = NS_X + 'data';
|
||||
var NS_IQOOB = NS_IQ + 'oob';
|
||||
var NS_XOOB = NS_X + 'oob';
|
||||
var NS_DELAY = NS_X + 'delay';
|
||||
var NS_EXPIRE = NS_X + 'expire';
|
||||
var NS_EVENT = NS_X + 'event';
|
||||
var NS_XCONFERENCE = NS_X + 'conference';
|
||||
var NS_STATS = NS_PROTOCOL + 'stats';
|
||||
var NS_MUC = NS_PROTOCOL + 'muc';
|
||||
var NS_MUC_USER = NS_MUC + '#user';
|
||||
var NS_MUC_ADMIN = NS_MUC + '#admin';
|
||||
var NS_MUC_OWNER = NS_MUC + '#owner';
|
||||
var NS_MUC_CONFIG = NS_MUC + '#roomconfig';
|
||||
var NS_PUBSUB = NS_PROTOCOL + 'pubsub';
|
||||
var NS_PUBSUB_EVENT = NS_PUBSUB + '#event';
|
||||
var NS_PUBSUB_OWNER = NS_PUBSUB + '#owner';
|
||||
var NS_PUBSUB_NMI = NS_PUBSUB + '#node-meta-info';
|
||||
var NS_PUBSUB_NC = NS_PUBSUB + '#node_config';
|
||||
var NS_PUBSUB_CN = NS_PUBSUB + '#config-node';
|
||||
var NS_PUBSUB_RI = NS_PUBSUB + '#retrieve-items';
|
||||
var NS_COMMANDS = NS_PROTOCOL + 'commands';
|
||||
var NS_BOSH = NS_PROTOCOL + 'httpbind';
|
||||
var NS_STREAM = 'http://etherx.jabber.org/streams';
|
||||
var NS_URN_TIME = NS_XMPP + 'time';
|
||||
var NS_URN_PING = NS_XMPP + 'ping';
|
||||
var NS_URN_MBLOG = NS_XMPP + 'microblog:0';
|
||||
var NS_URN_INBOX = NS_XMPP + 'inbox';
|
||||
var NS_URN_FORWARD = NS_XMPP + 'forward:0';
|
||||
var NS_URN_MAM = NS_XMPP + 'mam:tmp';
|
||||
var NS_URN_DELAY = NS_XMPP + 'delay';
|
||||
var NS_URN_RECEIPTS = NS_XMPP + 'receipts';
|
||||
var NS_URN_CARBONS = NS_XMPP + 'carbons:2';
|
||||
var NS_RSM = NS_PROTOCOL + 'rsm';
|
||||
var NS_IPV6 = 'ipv6';
|
||||
var NS_XHTML = 'http://www.w3.org/1999/xhtml';
|
||||
var NS_XHTML_IM = NS_PROTOCOL + 'xhtml-im';
|
||||
var NS_CHATSTATES = NS_PROTOCOL + 'chatstates';
|
||||
var NS_HTTP_AUTH = NS_PROTOCOL + 'http-auth';
|
||||
var NS_ROSTERX = NS_PROTOCOL + 'rosterx';
|
||||
var NS_MOOD = NS_PROTOCOL + 'mood';
|
||||
var NS_ACTIVITY = NS_PROTOCOL + 'activity';
|
||||
var NS_TUNE = NS_PROTOCOL + 'tune';
|
||||
var NS_GEOLOC = NS_PROTOCOL + 'geoloc';
|
||||
var NS_NICK = NS_PROTOCOL + 'nick';
|
||||
var NS_NOTIFY = '+notify';
|
||||
var NS_CAPS = NS_PROTOCOL + 'caps';
|
||||
var NS_ATOM = 'http://www.w3.org/2005/Atom';
|
||||
var NS_URN_TIME = NS_XMPP + 'time';
|
||||
var NS_URN_PING = NS_XMPP + 'ping';
|
||||
var NS_URN_MBLOG = NS_XMPP + 'microblog:0';
|
||||
var NS_URN_INBOX = NS_XMPP + 'inbox';
|
||||
var NS_URN_FORWARD = NS_XMPP + 'forward:0';
|
||||
var NS_URN_MAM = NS_XMPP + 'mam:tmp';
|
||||
var NS_URN_DELAY = NS_XMPP + 'delay';
|
||||
var NS_URN_RECEIPTS = NS_XMPP + 'receipts';
|
||||
var NS_URN_CARBONS = NS_XMPP + 'carbons:2';
|
||||
var NS_URN_CORRECT = NS_XMPP + 'message-correct:0';
|
||||
var NS_URN_IDLE = NS_XMPP + 'idle:1';
|
||||
var NS_URN_REACH = NS_XMPP + 'reach:0';
|
||||
var NS_URN_MARKERS = NS_XMPP + 'chat-markers:0';
|
||||
var NS_URN_ATTENTION = NS_XMPP + 'attention:0';
|
||||
var NS_URN_HINTS = NS_XMPP + 'hints';
|
||||
var NS_RSM = NS_PROTOCOL + 'rsm';
|
||||
var NS_IPV6 = 'ipv6';
|
||||
var NS_XHTML = 'http://www.w3.org/1999/xhtml';
|
||||
var NS_XHTML_IM = NS_PROTOCOL + 'xhtml-im';
|
||||
var NS_CHATSTATES = NS_PROTOCOL + 'chatstates';
|
||||
var NS_HTTP_AUTH = NS_PROTOCOL + 'http-auth';
|
||||
var NS_ROSTERX = NS_PROTOCOL + 'rosterx';
|
||||
var NS_MOOD = NS_PROTOCOL + 'mood';
|
||||
var NS_ACTIVITY = NS_PROTOCOL + 'activity';
|
||||
var NS_TUNE = NS_PROTOCOL + 'tune';
|
||||
var NS_GEOLOC = NS_PROTOCOL + 'geoloc';
|
||||
var NS_NICK = NS_PROTOCOL + 'nick';
|
||||
var NS_NOTIFY = '+notify';
|
||||
var NS_CAPS = NS_PROTOCOL + 'caps';
|
||||
var NS_ATOM = 'http://www.w3.org/2005/Atom';
|
||||
|
||||
var NS_STANZAS = NS_IETF_XMPP + 'stanzas';
|
||||
var NS_STREAMS = NS_IETF_XMPP + 'streams';
|
||||
var NS_STANZAS = NS_IETF_XMPP + 'stanzas';
|
||||
var NS_STREAMS = NS_IETF_XMPP + 'streams';
|
||||
|
||||
var NS_TLS = NS_IETF_XMPP + 'tls';
|
||||
var NS_SASL = NS_IETF_XMPP + 'sasl';
|
||||
var NS_SESSION = NS_IETF_XMPP + 'session';
|
||||
var NS_BIND = NS_IETF_XMPP + 'bind';
|
||||
var NS_TLS = NS_IETF_XMPP + 'tls';
|
||||
var NS_SASL = NS_IETF_XMPP + 'sasl';
|
||||
var NS_SESSION = NS_IETF_XMPP + 'session';
|
||||
var NS_BIND = NS_IETF_XMPP + 'bind';
|
||||
|
||||
var NS_FEATURE_IQAUTH = NS_FEATURES + 'iq-auth';
|
||||
var NS_FEATURE_IQAUTH = NS_FEATURES + 'iq-auth';
|
||||
var NS_FEATURE_IQREGISTER = NS_FEATURES + 'iq-register';
|
||||
var NS_FEATURE_COMPRESS = NS_FEATURES + 'compress';
|
||||
var NS_FEATURE_COMPRESS = NS_FEATURES + 'compress';
|
||||
|
||||
var NS_COMPRESS = NS_PROTOCOL + 'compress';
|
||||
var NS_COMPRESS = NS_PROTOCOL + 'compress';
|
||||
|
||||
var NS_METRONOME_MAM_PURGE = 'http://metronome.im/protocol/mam-purge';
|
||||
|
||||
|
|
509
source/app/javascripts/correction.js
Normal file
|
@ -0,0 +1,509 @@
|
|||
/*
|
||||
|
||||
Jappix - An open social platform
|
||||
Implementation of XEP-0308: Last Message Correction
|
||||
|
||||
-------------------------------------------------
|
||||
|
||||
License: AGPL
|
||||
Author: Valérian Saliou
|
||||
|
||||
*/
|
||||
|
||||
// Bundle
|
||||
var Correction = (function () {
|
||||
|
||||
/**
|
||||
* Alias of this
|
||||
* @private
|
||||
*/
|
||||
var self = {};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @return {boolean}
|
||||
*/
|
||||
self._hasSupport = function(xid) {
|
||||
|
||||
var support = false;
|
||||
|
||||
try {
|
||||
if($('#' + hex_md5(xid) + '[data-correction="true"]').size()) {
|
||||
support = true;
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Correction._hasSupport', e);
|
||||
} finally {
|
||||
return support;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @return {string}
|
||||
*/
|
||||
self._getLastID = function(xid) {
|
||||
|
||||
var last_id = null;
|
||||
|
||||
try {
|
||||
if(self._hasSupport(xid) === true) {
|
||||
// Check last message from ourselves
|
||||
last_id = $('#' + hex_md5(xid) + ' .content .one-line.user-message[data-mode="me"]:last').attr('data-id') || null;
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Correction._getLastID', e);
|
||||
} finally {
|
||||
return last_id;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @return {string}
|
||||
*/
|
||||
self._getCurrentID = function(xid) {
|
||||
|
||||
var current_id = null;
|
||||
|
||||
try {
|
||||
if(self._hasSupport(xid) === true) {
|
||||
// Check the ID of the message being edited (if any)
|
||||
current_id = $('#' + hex_md5(xid) + ' .message-area').attr('data-correction-current') || null;
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Correction._getCurrentID', e);
|
||||
} finally {
|
||||
return current_id;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @return {object}
|
||||
*/
|
||||
self._getLastMessage = function(xid) {
|
||||
|
||||
var last_message_val = null;
|
||||
var last_message_sel = null;
|
||||
|
||||
try {
|
||||
if(self._hasSupport(xid) === true) {
|
||||
// Check last message from ourselves
|
||||
last_message_sel = $('#' + hex_md5(xid) + ' .content .one-line.user-message[data-mode="me"]:last');
|
||||
last_message_val = last_message_sel.find('.message-content').text() || null;
|
||||
|
||||
if(last_message_val === null) {
|
||||
last_message_sel = null;
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Correction._getLastMessage', e);
|
||||
} finally {
|
||||
return {
|
||||
'value': last_message_val,
|
||||
'selector': last_message_sel
|
||||
};
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @param {object} message_sel
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._bindInterface = function(xid, message_sel) {
|
||||
|
||||
try {
|
||||
// Add message area elements
|
||||
var text_sel = $('#' + hex_md5(xid) + ' .text');
|
||||
|
||||
text_sel.addClass('correction-active');
|
||||
text_sel.prepend(
|
||||
'<div class="correction-toolbox">' +
|
||||
'<span class="correction-editing">' + Common._e("Editing") + '</span>' +
|
||||
'<a class="correction-cancel" href="#">' + Common._e("Cancel") + '</a>' +
|
||||
'</div>'
|
||||
);
|
||||
|
||||
// Add message correction marker
|
||||
message_sel.addClass('correction-active');
|
||||
message_sel.find('.correction-label').remove();
|
||||
message_sel.find('.correction-edit').hide();
|
||||
|
||||
message_sel.append(
|
||||
'<span class="correction-label">' +
|
||||
Common._e("Being edited") +
|
||||
'</span>'
|
||||
);
|
||||
|
||||
// Bind click events
|
||||
text_sel.find('.correction-cancel').click(function() {
|
||||
self.leave(xid);
|
||||
return false;
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Correction._bindInterface', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @param {object} message_sel
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._unbindInterface = function(xid, message_sel) {
|
||||
|
||||
try {
|
||||
// Remove message area elements
|
||||
var text_sel = $('#' + hex_md5(xid) + ' .text');
|
||||
text_sel.removeClass('correction-active');
|
||||
text_sel.find('.correction-toolbox, .correction-label').remove();
|
||||
|
||||
if(message_sel.size()) {
|
||||
message_sel.find('.correction-edit').css('display', '');
|
||||
|
||||
// Remove message correction marker
|
||||
message_sel.removeClass('correction-active');
|
||||
message_sel.find('.correction-label').remove();
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Correction._unbindInterface', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @param {string} full_xid
|
||||
* @param {string} type
|
||||
* @param {string} message_id
|
||||
* @param {string} message_body
|
||||
* @return {string}
|
||||
*/
|
||||
self._sendStanza = function(xid, full_xid, type, message_id, message_body) {
|
||||
|
||||
var args = {
|
||||
'id': null,
|
||||
'xhtml': false,
|
||||
'message': null
|
||||
};
|
||||
|
||||
try {
|
||||
var hash = hex_md5(xid);
|
||||
var id = genID();
|
||||
args.id = id;
|
||||
|
||||
// Initialize message stanza
|
||||
var message = new JSJaCMessage();
|
||||
args.message = message;
|
||||
|
||||
message.setType(type);
|
||||
message.setTo(full_xid);
|
||||
message.setID(id);
|
||||
|
||||
// Generates the correct message depending of the choosen style
|
||||
var generate_message = Message.generate(message, message_body, hash);
|
||||
args.xhtml = (generate_message === 'XHTML');
|
||||
|
||||
// Receipt request
|
||||
var receipt_request = Receipts.request(hash);
|
||||
|
||||
if(receipt_request) {
|
||||
message.appendNode('request', {'xmlns': NS_URN_RECEIPTS});
|
||||
}
|
||||
|
||||
// Chatstate
|
||||
message.appendNode('active', {'xmlns': NS_CHATSTATES});
|
||||
|
||||
if(message_id !== null) {
|
||||
message.appendNode('replace', {
|
||||
'xmlns': NS_URN_CORRECT,
|
||||
'id': message_id
|
||||
});
|
||||
}
|
||||
|
||||
con.send(message, Errors.handleReply);
|
||||
} catch(e) {
|
||||
Console.error('Correction._sendStanza', e);
|
||||
} finally {
|
||||
return args;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Detects correction mode request (in input)
|
||||
* @public
|
||||
* @param {string} xid
|
||||
* @param {object} input_sel
|
||||
* @return {undefined}
|
||||
*/
|
||||
self.detect = function(xid, input_sel) {
|
||||
|
||||
try {
|
||||
// Other keys
|
||||
if(input_sel.val().match(/^\/correct/) && self.isIn(xid) === false) {
|
||||
// Enter correction mode?
|
||||
self.enter(xid);
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Correction.detect', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Enter correction mode (for last message)
|
||||
* @public
|
||||
* @param {string} xid
|
||||
* @return {undefined}
|
||||
*/
|
||||
self.enter = function(xid) {
|
||||
|
||||
try {
|
||||
Console.debug('Correction.enter', 'Requested to enter the correction mode with: ' + xid);
|
||||
|
||||
if(self._hasSupport(xid) === true && self.isIn(xid) === false) {
|
||||
var last_message = self._getLastMessage(xid);
|
||||
|
||||
if(last_message.value && last_message.selector) {
|
||||
Console.info('Correction.enter', 'Valid last message found for correction mode with: ' + xid);
|
||||
|
||||
var message_area_sel = $('#' + hex_md5(xid) + ' .message-area');
|
||||
message_area_sel.val(last_message.value);
|
||||
|
||||
self._bindInterface(
|
||||
xid,
|
||||
last_message.selector
|
||||
);
|
||||
|
||||
// Focus hack (to get cursor at the end of textarea)
|
||||
message_area_sel.oneTime(10, function() {
|
||||
message_area_sel[0].select();
|
||||
message_area_sel[0].selectionStart = message_area_sel[0].selectionEnd;
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Correction.enter', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Leave correction mode
|
||||
* @public
|
||||
* @param {string} xid
|
||||
* @return {undefined}
|
||||
*/
|
||||
self.leave = function(xid) {
|
||||
|
||||
try {
|
||||
if(self.isIn(xid) === true) {
|
||||
var base_sel = $('#' + hex_md5(xid));
|
||||
var active_message_sel = base_sel.find('.content .one-line.user-message.correction-active');
|
||||
|
||||
self._unbindInterface(xid, active_message_sel);
|
||||
|
||||
var message_area_sel = base_sel.find('.message-area');
|
||||
message_area_sel.val('');
|
||||
message_area_sel.focus();
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Correction.leave', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Send corrected message
|
||||
* @public
|
||||
* @param {string} xid
|
||||
* @param {string} type
|
||||
* @param {string} replacement
|
||||
* @return {undefined}
|
||||
*/
|
||||
self.send = function(xid, type, replacement) {
|
||||
|
||||
try {
|
||||
if(self._hasSupport(xid) === true) {
|
||||
if(self._getLastMessage(xid).value != replacement) {
|
||||
var own_xid = Common.getXID();
|
||||
var hash = hex_md5(xid);
|
||||
var replace_id = self._getLastID(xid);
|
||||
|
||||
Console.info('Correction.send', 'Sending replacement message for: ' + xid + ' "' + replacement + '" with ID: ' + (replace_id || 'none'));
|
||||
|
||||
// Send the stanza itself
|
||||
var full_xid = Presence.highestPriority(xid) || xid;
|
||||
var stanza_args = self._sendStanza(
|
||||
xid,
|
||||
full_xid,
|
||||
type,
|
||||
replace_id,
|
||||
replacement
|
||||
);
|
||||
|
||||
// Update DOM (for chat only)
|
||||
if(type == 'chat') {
|
||||
// Filter the xHTML message (for us!)
|
||||
var replacement_formatted = replacement;
|
||||
|
||||
if(stanza_args.xhtml) {
|
||||
replacement_formatted = Filter.xhtml(stanza_args.message.getNode());
|
||||
}
|
||||
|
||||
// Remove old message
|
||||
old_message_sel = $('#' + hash + ' .content .one-line.user-message[data-mode="me"]').filter(function() {
|
||||
return ($(this).attr('data-id') + '') === (replace_id + '');
|
||||
}).filter(':last');
|
||||
|
||||
var edit_count = old_message_sel.attr('data-edit-count') || 0;
|
||||
edit_count = isNaN(edit_count) ? 0 : parseInt(edit_count, 10);
|
||||
|
||||
if(type == 'chat') {
|
||||
old_message_sel.remove();
|
||||
}
|
||||
|
||||
// Display edited message
|
||||
Message.display(
|
||||
'chat',
|
||||
own_xid,
|
||||
hash,
|
||||
Name.getBuddy(own_xid).htmlEnc(),
|
||||
replacement_formatted,
|
||||
DateUtils.getCompleteTime(),
|
||||
DateUtils.getTimeStamp(),
|
||||
'user-message',
|
||||
!stanza_args.xhtml,
|
||||
'',
|
||||
'me',
|
||||
stanza_args.id,
|
||||
undefined,
|
||||
undefined,
|
||||
true,
|
||||
(edit_count + 1)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Correction.send', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Catches a replace message
|
||||
* @public
|
||||
* @param {object} message
|
||||
* @param {string} hash
|
||||
* @param {string} type
|
||||
* @return {object}
|
||||
*/
|
||||
self.catch = function(message, hash, type) {
|
||||
|
||||
var edit_results = {
|
||||
'has_replace': false,
|
||||
'is_edited': false,
|
||||
'count': 0,
|
||||
'next_count': 0
|
||||
};
|
||||
|
||||
try {
|
||||
var replace_node = message.getChild('replace', NS_URN_CORRECT);
|
||||
|
||||
if(replace_node) {
|
||||
edit_results.has_replace = true;
|
||||
var message_edit_id = $(replace_node).attr('id');
|
||||
|
||||
if(typeof message_edit_id != 'undefined') {
|
||||
var message_edit_sel = $('#' + hash + ' .one-line.user-message').filter(function() {
|
||||
var this_sel = $(this);
|
||||
var is_valid_mode = true;
|
||||
|
||||
if(type == 'chat') {
|
||||
is_valid_mode = true ? this_sel.attr('data-mode') == 'him' : false;
|
||||
}
|
||||
|
||||
return is_valid_mode && ((this_sel.attr('data-id') + '') === (message_edit_id + ''));
|
||||
}).filter(':last');
|
||||
|
||||
if(message_edit_sel.size()) {
|
||||
edit_results.count = message_edit_sel.attr('data-edit-count') || 0;
|
||||
edit_results.count = isNaN(edit_results.count) ? 0 : parseInt(edit_results.count, 10);
|
||||
edit_results.next_count = edit_results.count + 1;
|
||||
edit_results.is_edited = true;
|
||||
|
||||
// Empty group?
|
||||
var message_edit_group_sel = message_edit_sel.parents('.one-group');
|
||||
|
||||
if(message_edit_group_sel.find('.one-line').size() <= 1) {
|
||||
message_edit_group_sel.remove();
|
||||
} else {
|
||||
message_edit_sel.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Correction.catch', e);
|
||||
} finally {
|
||||
return edit_results;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether we are in correction mode or not
|
||||
* @public
|
||||
* @param {string} xid
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.isIn = function(xid) {
|
||||
|
||||
var is_in = false;
|
||||
|
||||
try {
|
||||
is_in = $('#' + hex_md5(xid) + ' .text').hasClass('correction-active');
|
||||
} catch(e) {
|
||||
Console.error('Correction.isIn', e);
|
||||
} finally {
|
||||
return is_in;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return class scope
|
||||
*/
|
||||
return self;
|
||||
|
||||
})();
|
|
@ -39,8 +39,9 @@ var DataStore = (function () {
|
|||
|
||||
this.key = function(key) {
|
||||
if(legacy) {
|
||||
if(key >= this.length)
|
||||
if(key >= this.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var c = 0;
|
||||
|
||||
|
@ -56,8 +57,9 @@ var DataStore = (function () {
|
|||
|
||||
this.getItem = function(key) {
|
||||
if(legacy) {
|
||||
if(storage_emulated[key] !== undefined)
|
||||
if(storage_emulated[key] !== undefined) {
|
||||
return storage_emulated[key];
|
||||
}
|
||||
|
||||
return null;
|
||||
} else {
|
||||
|
@ -67,8 +69,9 @@ var DataStore = (function () {
|
|||
|
||||
this.setItem = function(key, data) {
|
||||
if(legacy) {
|
||||
if(!(key in storage_emulated))
|
||||
if(!(key in storage_emulated)) {
|
||||
this.length++;
|
||||
}
|
||||
|
||||
storage_emulated[key] = (data + '');
|
||||
} else {
|
||||
|
@ -472,8 +475,9 @@ var DataStore = (function () {
|
|||
self.resetPersistent();
|
||||
|
||||
// Restaure the stored session entry
|
||||
if(session)
|
||||
if(session) {
|
||||
self.setPersistent('global', 'session', 1, session);
|
||||
}
|
||||
|
||||
Console.info('Persistent database flushed.');
|
||||
|
||||
|
|
|
@ -84,8 +84,9 @@ var DateUtils = (function () {
|
|||
|
||||
try {
|
||||
// Last activity not yet initialized?
|
||||
if(self.last_activity === 0)
|
||||
if(self.last_activity === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return self.getTimeStamp() - self.last_activity;
|
||||
} catch(e) {
|
||||
|
@ -95,6 +96,27 @@ var DateUtils = (function () {
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the last user activity as a date
|
||||
* @public
|
||||
* @return {string}
|
||||
*/
|
||||
self.getLastActivityDate = function() {
|
||||
|
||||
try {
|
||||
var last_activity = self.last_activity || self.getTimeStamp();
|
||||
|
||||
var last_date = new Date();
|
||||
last_date.setTime(last_activity * 1000);
|
||||
|
||||
return self.getDatetime(last_date, 'utc');
|
||||
} catch(e) {
|
||||
Console.error('DateUtils.getLastActivityDate', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the last user available presence in seconds
|
||||
* @public
|
||||
|
@ -104,8 +126,9 @@ var DateUtils = (function () {
|
|||
|
||||
try {
|
||||
// Last presence stamp not yet initialized?
|
||||
if(self.presence_last_activity === 0)
|
||||
if(self.presence_last_activity === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return self.getTimeStamp() - self.presence_last_activity;
|
||||
} catch(e) {
|
||||
|
@ -115,6 +138,56 @@ var DateUtils = (function () {
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* Generates a normalized datetime
|
||||
* @public
|
||||
* @param {Date} date
|
||||
* @param {string} location
|
||||
* @return {string}
|
||||
*/
|
||||
self.getDatetime = function(date, location) {
|
||||
|
||||
/* FROM : http://trac.jwchat.org/jsjac/browser/branches/jsjac_1.0/jsextras.js?rev=221 */
|
||||
|
||||
var year, month, day, hours, minutes, seconds;
|
||||
var date_string = null;
|
||||
|
||||
try {
|
||||
if(location == 'utc') {
|
||||
// UTC date
|
||||
year = date.getUTCFullYear();
|
||||
month = date.getUTCMonth();
|
||||
day = date.getUTCDate();
|
||||
hours = date.getUTCHours();
|
||||
minutes = date.getUTCMinutes();
|
||||
seconds = date.getUTCSeconds();
|
||||
} else {
|
||||
// Local date
|
||||
year = date.getFullYear();
|
||||
month = date.getMonth();
|
||||
day = date.getDate();
|
||||
hours = date.getHours();
|
||||
minutes = date.getMinutes();
|
||||
seconds = date.getSeconds();
|
||||
}
|
||||
|
||||
// Generates the date string
|
||||
date_string = year + '-';
|
||||
date_string += Common.padZero(month + 1) + '-';
|
||||
date_string += Common.padZero(day) + 'T';
|
||||
date_string += Common.padZero(hours) + ':';
|
||||
date_string += Common.padZero(minutes) + ':';
|
||||
date_string += Common.padZero(seconds) + 'Z';
|
||||
|
||||
// Returns the date string
|
||||
return date_string;
|
||||
} catch(e) {
|
||||
Console.error('DateUtils.getDatetime', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Generates the time for XMPP
|
||||
* @public
|
||||
|
@ -123,43 +196,11 @@ var DateUtils = (function () {
|
|||
*/
|
||||
self.getXMPPTime = function(location) {
|
||||
|
||||
/* FROM : http://trac.jwchat.org/jsjac/browser/branches/jsjac_1.0/jsextras.js?rev=221 */
|
||||
|
||||
try {
|
||||
// Initialize
|
||||
var jInit = new Date();
|
||||
var year, month, day, hours, minutes, seconds;
|
||||
|
||||
// Gets the UTC date
|
||||
if(location == 'utc') {
|
||||
year = jInit.getUTCFullYear();
|
||||
month = jInit.getUTCMonth();
|
||||
day = jInit.getUTCDate();
|
||||
hours = jInit.getUTCHours();
|
||||
minutes = jInit.getUTCMinutes();
|
||||
seconds = jInit.getUTCSeconds();
|
||||
}
|
||||
|
||||
// Gets the local date
|
||||
else {
|
||||
year = jInit.getFullYear();
|
||||
month = jInit.getMonth();
|
||||
day = jInit.getDate();
|
||||
hours = jInit.getHours();
|
||||
minutes = jInit.getMinutes();
|
||||
seconds = jInit.getSeconds();
|
||||
}
|
||||
|
||||
// Generates the date string
|
||||
var jDate = year + '-';
|
||||
jDate += Common.padZero(month + 1) + '-';
|
||||
jDate += Common.padZero(day) + 'T';
|
||||
jDate += Common.padZero(hours) + ':';
|
||||
jDate += Common.padZero(minutes) + ':';
|
||||
jDate += Common.padZero(seconds) + 'Z';
|
||||
|
||||
// Returns the date string
|
||||
return jDate;
|
||||
return self.getDatetime(
|
||||
(new Date()),
|
||||
location
|
||||
);
|
||||
} catch(e) {
|
||||
Console.error('DateUtils.getXMPPTime', e);
|
||||
}
|
||||
|
@ -176,6 +217,7 @@ var DateUtils = (function () {
|
|||
|
||||
try {
|
||||
var init = new Date();
|
||||
|
||||
var time = Common.padZero(init.getHours()) + ':';
|
||||
time += Common.padZero(init.getMinutes()) + ':';
|
||||
time += Common.padZero(init.getSeconds());
|
||||
|
@ -332,20 +374,24 @@ var DateUtils = (function () {
|
|||
var days = Math.round((current_stamp - old_stamp) / 86400000);
|
||||
|
||||
// Invalid date?
|
||||
if(isNaN(old_stamp) || isNaN(days))
|
||||
if(isNaN(old_stamp) || isNaN(days)) {
|
||||
return self.getCompleteTime();
|
||||
}
|
||||
|
||||
// Is it today?
|
||||
if(current_day == old_day)
|
||||
if(current_day == old_day) {
|
||||
return old_time;
|
||||
}
|
||||
|
||||
// It is yesterday?
|
||||
if(days <= 1)
|
||||
if(days <= 1) {
|
||||
return Common._e("Yesterday") + ' - ' + old_time;
|
||||
}
|
||||
|
||||
// Is it less than a week ago?
|
||||
if(days <= 7)
|
||||
if(days <= 7) {
|
||||
return Common.printf(Common._e("%s days ago"), days) + ' - ' + old_time;
|
||||
}
|
||||
|
||||
// Another longer period
|
||||
return old_date.toLocaleDateString() + ' - ' + old_time;
|
||||
|
@ -371,13 +417,12 @@ var DateUtils = (function () {
|
|||
// Read the delay
|
||||
d_delay = jQuery(node).find('delay[xmlns="' + NS_URN_DELAY + '"]:first').attr('stamp');
|
||||
|
||||
// New delay (valid XEP)
|
||||
if(d_delay)
|
||||
// Get delay
|
||||
if(d_delay) {
|
||||
// New delay (valid XEP)
|
||||
delay = d_delay;
|
||||
|
||||
// Old delay (obsolete XEP!)
|
||||
else {
|
||||
// Try to read the old-school delay
|
||||
} else {
|
||||
// Old delay (obsolete XEP!)
|
||||
var x_delay = jQuery(node).find('x[xmlns="' + NS_DELAY + '"]:first').attr('stamp');
|
||||
|
||||
if(x_delay)
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/**
|
||||
* Version: 1.0 Alpha-1
|
||||
* Build Date: 13-Nov-2007
|
||||
* Copyright (c) 2006-2007, Coolite Inc. (http://www.coolite.com/). All rights reserved.
|
||||
* License: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/.
|
||||
* Website: http://www.datejs.com/ or http://www.coolite.com/datejs/
|
||||
*/
|
||||
/**
|
||||
* Version: 1.0 Alpha-1
|
||||
* Build Date: 13-Nov-2007
|
||||
* Copyright (c) 2006-2007, Coolite Inc. (http://www.coolite.com/). All rights reserved.
|
||||
* License: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/.
|
||||
* Website: http://www.datejs.com/ or http://www.coolite.com/datejs/
|
||||
*/
|
||||
Date.CultureInfo={name:"en-US",englishName:"English (United States)",nativeName:"English (United States)",dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],abbreviatedDayNames:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],shortestDayNames:["Su","Mo","Tu","We","Th","Fr","Sa"],firstLetterDayNames:["S","M","T","W","T","F","S"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],abbreviatedMonthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],amDesignator:"AM",pmDesignator:"PM",firstDayOfWeek:0,twoDigitYearMax:2029,dateElementOrder:"mdy",formatPatterns:{shortDate:"M/d/yyyy",longDate:"dddd, MMMM dd, yyyy",shortTime:"h:mm tt",longTime:"h:mm:ss tt",fullDateTime:"dddd, MMMM dd, yyyy h:mm:ss tt",sortableDateTime:"yyyy-MM-ddTHH:mm:ss",universalSortableDateTime:"yyyy-MM-dd HH:mm:ssZ",rfc1123:"ddd, dd MMM yyyy HH:mm:ss GMT",monthDay:"MMMM dd",yearMonth:"MMMM, yyyy"},regexPatterns:{jan:/^jan(uary)?/i,feb:/^feb(ruary)?/i,mar:/^mar(ch)?/i,apr:/^apr(il)?/i,may:/^may/i,jun:/^jun(e)?/i,jul:/^jul(y)?/i,aug:/^aug(ust)?/i,sep:/^sep(t(ember)?)?/i,oct:/^oct(ober)?/i,nov:/^nov(ember)?/i,dec:/^dec(ember)?/i,sun:/^su(n(day)?)?/i,mon:/^mo(n(day)?)?/i,tue:/^tu(e(s(day)?)?)?/i,wed:/^we(d(nesday)?)?/i,thu:/^th(u(r(s(day)?)?)?)?/i,fri:/^fr(i(day)?)?/i,sat:/^sa(t(urday)?)?/i,future:/^next/i,past:/^last|past|prev(ious)?/i,add:/^(\+|after|from)/i,subtract:/^(\-|before|ago)/i,yesterday:/^yesterday/i,today:/^t(oday)?/i,tomorrow:/^tomorrow/i,now:/^n(ow)?/i,millisecond:/^ms|milli(second)?s?/i,second:/^sec(ond)?s?/i,minute:/^min(ute)?s?/i,hour:/^h(ou)?rs?/i,week:/^w(ee)?k/i,month:/^m(o(nth)?s?)?/i,day:/^d(ays?)?/i,year:/^y((ea)?rs?)?/i,shortMeridian:/^(a|p)/i,longMeridian:/^(a\.?m?\.?|p\.?m?\.?)/i,timezone:/^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\s*(\+|\-)\s*\d\d\d\d?)|gmt)/i,ordinalSuffix:/^\s*(st|nd|rd|th)/i,timeContext:/^\s*(\:|a|p)/i},abbreviatedTimeZoneStandard:{GMT:"-000",EST:"-0400",CST:"-0500",MST:"-0600",PST:"-0700"},abbreviatedTimeZoneDST:{GMT:"-000",EDT:"-0500",CDT:"-0600",MDT:"-0700",PDT:"-0800"}};
|
||||
Date.getMonthNumberFromName=function(name){var n=Date.CultureInfo.monthNames,m=Date.CultureInfo.abbreviatedMonthNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
|
||||
return-1;};Date.getDayNumberFromName=function(name){var n=Date.CultureInfo.dayNames,m=Date.CultureInfo.abbreviatedDayNames,o=Date.CultureInfo.shortestDayNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
|
||||
|
@ -101,4 +101,4 @@ return _.any.apply(null,rx);}else{return _get(fx);}};g._formats=g.formats(["yyyy
|
|||
return g._start.call({},s);};}());Date._parse=Date.parse;Date.parse=function(s){var r=null;if(!s){return null;}
|
||||
try{r=Date.Grammar.start.call({},s);}catch(e){return null;}
|
||||
return((r[1].length===0)?r[0]:null);};Date.getParseFunction=function(fx){var fn=Date.Grammar.formats(fx);return function(s){var r=null;try{r=fn.call({},s);}catch(e){return null;}
|
||||
return((r[1].length===0)?r[0]:null);};};Date.parseExact=function(s,fx){return Date.getParseFunction(fx)(s);};
|
||||
return((r[1].length===0)?r[0]:null);};};Date.parseExact=function(s,fx){return Date.getParseFunction(fx)(s);};
|
||||
|
|
|
@ -123,8 +123,9 @@ var Directory = (function () {
|
|||
$('#directory .directory-server-input').keyup(function(e) {
|
||||
if(e.keyCode == 13) {
|
||||
// No value?
|
||||
if(!$(this).val())
|
||||
if(!$(this).val()) {
|
||||
$(this).val(HOST_VJUD);
|
||||
}
|
||||
|
||||
// Start the directory search
|
||||
self.start();
|
||||
|
|
|
@ -216,8 +216,9 @@ var Discovery = (function () {
|
|||
$('#discovery .disco-server-input').keyup(function(e) {
|
||||
if(e.keyCode == 13) {
|
||||
// No value?
|
||||
if(!$(this).val())
|
||||
if(!$(this).val()) {
|
||||
$(this).val(HOST_MAIN);
|
||||
}
|
||||
|
||||
// Start the discovery
|
||||
self.start();
|
||||
|
|
|
@ -37,17 +37,20 @@ var Errors = (function () {
|
|||
var eText = '';
|
||||
|
||||
// Any error condition
|
||||
if(condition)
|
||||
if(condition) {
|
||||
eText += condition;
|
||||
}
|
||||
|
||||
// Any error type
|
||||
if(type && eText)
|
||||
if(type && eText) {
|
||||
eText += ' (' + type + ')';
|
||||
}
|
||||
|
||||
// Any error reason
|
||||
if(reason) {
|
||||
if(eText)
|
||||
if(eText) {
|
||||
eText += ' - ';
|
||||
}
|
||||
|
||||
eText += reason;
|
||||
}
|
||||
|
@ -119,10 +122,11 @@ var Errors = (function () {
|
|||
// Show reconnect pane
|
||||
if(Connection.current_session && Connection.connected) {
|
||||
// Anonymous?
|
||||
if(Utils.isAnonymous())
|
||||
if(Utils.isAnonymous()) {
|
||||
Connection.createReconnect('anonymous');
|
||||
else
|
||||
} else {
|
||||
Connection.createReconnect('normal');
|
||||
}
|
||||
}
|
||||
|
||||
// Show the homepage (security)
|
||||
|
|
|
@ -143,16 +143,21 @@ var Favorites = (function () {
|
|||
self.reset = function() {
|
||||
|
||||
try {
|
||||
var path = '#favorites ';
|
||||
var path_sel = $('#favorites');
|
||||
|
||||
$(path + '.wait, ' + path + '.fedit-terminate').hide();
|
||||
$(path + '.fedit-add').show();
|
||||
$(path + '.fsearch-oneresult').remove();
|
||||
$(path + 'input').val('');
|
||||
$(path + '.please-complete').removeClass('please-complete');
|
||||
$(path + '.fedit-nick').val(Name.getNick());
|
||||
$(path + '.fsearch-head-server, ' + path + '.fedit-server').val(HOST_MUC);
|
||||
$(path + '.fedit-autojoin').removeAttr('checked');
|
||||
path_sel.find('.wait');
|
||||
path_sel.find('.fedit-terminate').hide();
|
||||
path_sel.find('.fedit-add').show();
|
||||
|
||||
path_sel.find('.fsearch-oneresult').remove();
|
||||
path_sel.find('input').val('');
|
||||
path_sel.find('.please-complete').removeClass('please-complete');
|
||||
|
||||
path_sel.find('.fedit-nick').val(Name.getNick());
|
||||
path_sel.find('.fsearch-head-server').val(HOST_MUC);
|
||||
path_sel.find('.fedit-server').val(HOST_MUC);
|
||||
|
||||
path_sel.find('.fedit-autojoin').removeAttr('checked');
|
||||
} catch(e) {
|
||||
Console.error('Favorites.reset', e);
|
||||
}
|
||||
|
@ -182,29 +187,34 @@ var Favorites = (function () {
|
|||
/**
|
||||
* Adds a room to the favorites
|
||||
* @public
|
||||
* @param {string} roomXID
|
||||
* @param {string} roomName
|
||||
* @param {string} room_xid
|
||||
* @param {string} room_name
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.addThis = function(roomXID, roomName) {
|
||||
self.addThis = function(room_xid, room_name) {
|
||||
|
||||
try {
|
||||
// Button path
|
||||
var button = '#favorites .fsearch-results div[data-xid="' + escape(roomXID) + '"] a.one-button';
|
||||
var button_sel = $('#favorites .fsearch-results div[data-xid="' + escape(room_xid) + '"] a.one-button');
|
||||
|
||||
// Add a remove button instead of the add one
|
||||
$(button + '.add').replaceWith('<a href="#" class="one-button remove talk-images">' + Common._e("Remove") + '</a>');
|
||||
button_sel.filter('.add').replaceWith(
|
||||
'<a href="#" class="one-button remove talk-images">' + Common._e("Remove") + '</a>'
|
||||
);
|
||||
|
||||
// Click event
|
||||
$(button + '.remove').click(function() {
|
||||
return self.removeThis(roomXID, roomName);
|
||||
button_sel.filter('.remove').click(function() {
|
||||
return self.removeThis(room_xid, room_name);
|
||||
});
|
||||
|
||||
// Hide the add button in the (opened?) groupchat
|
||||
$('#' + hex_md5(roomXID) + ' .tools-add').hide();
|
||||
$('#' + hex_md5(room_xid) + ' .tools-add').hide();
|
||||
|
||||
// Add the database entry
|
||||
self.display(roomXID, Common.explodeThis(' (', roomName, 0), Name.getNick(), '0', '');
|
||||
self.display(
|
||||
room_xid,
|
||||
Common.explodeThis(' (', room_name, 0), Name.getNick(), '0', ''
|
||||
);
|
||||
|
||||
// Publish the favorites
|
||||
self.publish();
|
||||
|
@ -220,29 +230,29 @@ var Favorites = (function () {
|
|||
/**
|
||||
* Removes a room from the favorites
|
||||
* @public
|
||||
* @param {string} roomXID
|
||||
* @param {string} roomName
|
||||
* @param {string} room_xid
|
||||
* @param {string} room_name
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.removeThis = function(roomXID, roomName) {
|
||||
self.removeThis = function(room_xid, room_name) {
|
||||
|
||||
try {
|
||||
// Button path
|
||||
var button = '#favorites .fsearch-results div[data-xid="' + escape(roomXID) + '"] a.one-button';
|
||||
var button_sel = $('#favorites .fsearch-results div[data-xid="' + escape(room_xid) + '"] a.one-button');
|
||||
|
||||
// Add a remove button instead of the add one
|
||||
$(button + '.remove').replaceWith('<a href="#" class="one-button add talk-images">' + Common._e("Add") + '</a>');
|
||||
button_sel.filter('.remove').replaceWith('<a href="#" class="one-button add talk-images">' + Common._e("Add") + '</a>');
|
||||
|
||||
// Click event
|
||||
$(button + '.add').click(function() {
|
||||
return self.addThis(roomXID, roomName);
|
||||
button_sel.filter('.add').click(function() {
|
||||
return self.addThis(room_xid, room_name);
|
||||
});
|
||||
|
||||
// Show the add button in the (opened?) groupchat
|
||||
$('#' + hex_md5(roomXID) + ' .tools-add').show();
|
||||
$('#' + hex_md5(room_xid) + ' .tools-add').show();
|
||||
|
||||
// Remove the favorite
|
||||
self.remove(roomXID, true);
|
||||
self.remove(room_xid, true);
|
||||
|
||||
// Publish the favorites
|
||||
self.publish();
|
||||
|
@ -264,31 +274,34 @@ var Favorites = (function () {
|
|||
|
||||
try {
|
||||
// Path to favorites
|
||||
var favorites = '#favorites .';
|
||||
var favorites_sel = $('#favorites');
|
||||
|
||||
// Reset the favorites
|
||||
self.reset();
|
||||
|
||||
// Show the edit/remove button, hide the others
|
||||
$(favorites + 'fedit-terminate').hide();
|
||||
$(favorites + 'fedit-edit').show();
|
||||
$(favorites + 'fedit-remove').show();
|
||||
favorites_sel.find('.fedit-terminate').hide();
|
||||
favorites_sel.find('.fedit-edit').show();
|
||||
favorites_sel.find('.fedit-remove').show();
|
||||
|
||||
// We retrieve the values
|
||||
var xid = $(favorites + 'fedit-head-select').val();
|
||||
var data = Common.XMLFromString(DataStore.getDB(Connection.desktop_hash, 'favorites', xid));
|
||||
var xid = favorites_sel.find('.fedit-head-select').val();
|
||||
var data_sel = $(Common.XMLFromString(
|
||||
DataStore.getDB(Connection.desktop_hash, 'favorites', xid)
|
||||
));
|
||||
|
||||
// If this is not the default room
|
||||
if(xid != 'none') {
|
||||
// We apply the values
|
||||
$(favorites + 'fedit-title').val($(data).find('name').text());
|
||||
$(favorites + 'fedit-nick').val($(data).find('nick').text());
|
||||
$(favorites + 'fedit-chan').val(Common.getXIDNick(xid));
|
||||
$(favorites + 'fedit-server').val(Common.getXIDHost(xid));
|
||||
$(favorites + 'fedit-password').val($(data).find('password').text());
|
||||
favorites_sel.find('.fedit-title').val(data_sel.find('name').text());
|
||||
favorites_sel.find('.fedit-nick').val(data_sel.find('nick').text());
|
||||
favorites_sel.find('.fedit-chan').val(Common.getXIDNick(xid));
|
||||
favorites_sel.find('.fedit-server').val(Common.getXIDHost(xid));
|
||||
favorites_sel.find('.fedit-password').val(data_sel.find('password').text());
|
||||
|
||||
if($(data).find('autojoin').text() == 'true')
|
||||
$(favorites + 'fedit-autojoin').attr('checked', true);
|
||||
if(data_sel.find('autojoin').text() == 'true') {
|
||||
favorites_sel.find('.fedit-autojoin').attr('checked', true);
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Favorites.edit', e);
|
||||
|
@ -307,52 +320,50 @@ var Favorites = (function () {
|
|||
|
||||
try {
|
||||
// Path to favorites
|
||||
var favorites = '#favorites ';
|
||||
var favorites_sel = $('#favorites');
|
||||
|
||||
// We get the values of the current edited groupchat
|
||||
var old_xid = $(favorites + '.fedit-head-select').val();
|
||||
var old_xid = favorites_sel.find('.fedit-head-select').val();
|
||||
|
||||
var title = $(favorites + '.fedit-title').val();
|
||||
var nick = $(favorites + '.fedit-nick').val();
|
||||
var room = $(favorites + '.fedit-chan').val();
|
||||
var server = $(favorites + '.fedit-server').val();
|
||||
var title = favorites_sel.find('.fedit-title').val();
|
||||
var nick = favorites_sel.find('.fedit-nick').val();
|
||||
var room = favorites_sel.find('.fedit-chan').val();
|
||||
var server = favorites_sel.find('.fedit-server').val();
|
||||
var xid = room + '@' + server;
|
||||
var password = $(favorites + '.fedit-password').val();
|
||||
var password = favorites_sel.find('.fedit-password').val();
|
||||
var autojoin = 'false';
|
||||
|
||||
if($(favorites + '.fedit-autojoin').filter(':checked').size())
|
||||
if(favorites_sel.find('.fedit-autojoin').filter(':checked').size()) {
|
||||
autojoin = 'true';
|
||||
}
|
||||
|
||||
// We check the missing values and send this if okay
|
||||
if((type == 'add') || (type == 'edit')) {
|
||||
if(title && nick && room && server) {
|
||||
// Remove the edited room
|
||||
if(type == 'edit')
|
||||
if(type == 'edit') {
|
||||
self.remove(old_xid, true);
|
||||
}
|
||||
|
||||
// Display the favorites
|
||||
self.display(xid, title, nick, autojoin, password);
|
||||
|
||||
// Reset the inputs
|
||||
self.reset();
|
||||
}
|
||||
|
||||
else {
|
||||
$(favorites + 'input[required]').each(function() {
|
||||
} else {
|
||||
favorites_sel.find('input[required]').each(function() {
|
||||
var select = $(this);
|
||||
|
||||
if(!select.val())
|
||||
if(!select.val()) {
|
||||
$(document).oneTime(10, function() {
|
||||
select.addClass('please-complete').focus();
|
||||
});
|
||||
else
|
||||
} else {
|
||||
select.removeClass('please-complete');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Must remove a favorite?
|
||||
else if(type == 'remove') {
|
||||
} else if(type == 'remove') {
|
||||
self.remove(old_xid, true);
|
||||
|
||||
// Reset the inputs
|
||||
|
@ -409,7 +420,9 @@ var Favorites = (function () {
|
|||
iq.setType('set');
|
||||
|
||||
var query = iq.setQuery(NS_PRIVATE);
|
||||
var storage = query.appendChild(iq.buildNode('storage', {'xmlns': NS_BOOKMARKS}));
|
||||
var storage = query.appendChild(iq.buildNode('storage', {
|
||||
'xmlns': NS_BOOKMARKS
|
||||
}));
|
||||
|
||||
// We generate the XML
|
||||
var db_regex = new RegExp(('^' + Connection.desktop_hash + '_') + 'favorites_(.+)');
|
||||
|
@ -420,19 +433,35 @@ var Favorites = (function () {
|
|||
|
||||
// If the pointer is on a stored favorite
|
||||
if(current.match(db_regex)) {
|
||||
var data = Common.XMLFromString(DataStore.storageDB.getItem(current));
|
||||
var xid = $(data).find('xid').text();
|
||||
var rName = $(data).find('name').text();
|
||||
var nick = $(data).find('nick').text();
|
||||
var password = $(data).find('password').text();
|
||||
var autojoin = $(data).find('autojoin').text();
|
||||
var data_sel = $(Common.XMLFromString(
|
||||
DataStore.storageDB.getItem(current)
|
||||
));
|
||||
|
||||
var xid = data_sel.find('xid').text();
|
||||
var rName = data_sel.find('name').text();
|
||||
var nick = data_sel.find('nick').text();
|
||||
var password = data_sel.find('password').text();
|
||||
var autojoin = data_sel.find('autojoin').text();
|
||||
|
||||
// We create the node for this groupchat
|
||||
var item = storage.appendChild(iq.buildNode('conference', {'name': rName, 'jid': xid, 'autojoin': autojoin, xmlns: NS_BOOKMARKS}));
|
||||
item.appendChild(iq.buildNode('nick', {xmlns: NS_BOOKMARKS}, nick));
|
||||
var item = storage.appendChild(
|
||||
iq.buildNode('conference', {
|
||||
'name': rName,
|
||||
'jid': xid,
|
||||
'autojoin': autojoin,
|
||||
xmlns: NS_BOOKMARKS
|
||||
})
|
||||
);
|
||||
|
||||
if(password)
|
||||
item.appendChild(iq.buildNode('password', {xmlns: NS_BOOKMARKS}, password));
|
||||
item.appendChild(iq.buildNode('nick', {
|
||||
xmlns: NS_BOOKMARKS
|
||||
}, nick));
|
||||
|
||||
if(password) {
|
||||
item.appendChild(iq.buildNode('password', {
|
||||
xmlns: NS_BOOKMARKS
|
||||
}, password));
|
||||
}
|
||||
|
||||
Console.info('Bookmark sent: ' + xid);
|
||||
}
|
||||
|
@ -454,17 +483,17 @@ var Favorites = (function () {
|
|||
self.getGCList = function() {
|
||||
|
||||
try {
|
||||
var path = '#favorites .';
|
||||
var gcServer = $('.fsearch-head-server').val();
|
||||
var path_sel = $('#favorites');
|
||||
var groupchat_server = $('.fsearch-head-server').val();
|
||||
|
||||
// We reset some things
|
||||
$(path + 'fsearch-oneresult').remove();
|
||||
$(path + 'fsearch-noresults').hide();
|
||||
$(path + 'wait').show();
|
||||
path_sel.find('.fsearch-oneresult').remove();
|
||||
path_sel.find('.fsearch-noresults').hide();
|
||||
path_sel.find('.wait').show();
|
||||
|
||||
var iq = new JSJaCIQ();
|
||||
iq.setType('get');
|
||||
iq.setTo(gcServer);
|
||||
iq.setTo(groupchat_server);
|
||||
|
||||
iq.setQuery(NS_DISCO_ITEMS);
|
||||
|
||||
|
@ -485,13 +514,13 @@ var Favorites = (function () {
|
|||
self.handleGCList = function(iq) {
|
||||
|
||||
try {
|
||||
var path = '#favorites .';
|
||||
var path_sel = $('#favorites');
|
||||
var from = Common.fullXID(Common.getStanzaFrom(iq));
|
||||
|
||||
if(!iq || (iq.getType() != 'result')) {
|
||||
Board.openThisError(3);
|
||||
|
||||
$(path + 'wait').hide();
|
||||
path_sel.find('.wait').hide();
|
||||
|
||||
Console.error('Error while retrieving the rooms: ' + from);
|
||||
}
|
||||
|
@ -504,24 +533,37 @@ var Favorites = (function () {
|
|||
var html = '';
|
||||
|
||||
$(handleXML).find('item').each(function() {
|
||||
var roomXID = $(this).attr('jid');
|
||||
var roomName = $(this).attr('name');
|
||||
var this_sel = $(this);
|
||||
|
||||
var room_xid = this_sel.attr('jid');
|
||||
var room_name = this_sel.attr('name');
|
||||
|
||||
if(roomXID && roomName) {
|
||||
if(room_xid && room_name) {
|
||||
// Escaped values
|
||||
var escaped_xid = Utils.encodeOnclick(roomXID);
|
||||
var escaped_name = Utils.encodeOnclick(roomName);
|
||||
var escaped_xid = Utils.encodeOnclick(room_xid);
|
||||
var escaped_name = Utils.encodeOnclick(room_name);
|
||||
|
||||
// Initialize the room HTML
|
||||
html += '<div class="oneresult fsearch-oneresult" data-xid="' + escape(roomXID) + '">' +
|
||||
'<div class="room-name">' + roomName.htmlEnc() + '</div>' +
|
||||
html += '<div class="oneresult fsearch-oneresult" data-xid="' + escape(room_xid) + '">' +
|
||||
'<div class="room-name">' + room_name.htmlEnc() + '</div>' +
|
||||
'<a href="#" class="one-button join talk-images" onclick="return Favorites.join(\'' + escaped_xid + '\');">' + Common._e("Join") + '</a>';
|
||||
|
||||
// This room is yet a favorite
|
||||
if(DataStore.existDB('favorites', roomXID))
|
||||
html += '<a href="#" class="one-button remove talk-images" onclick="return Favorites.removeThis(\'' + escaped_xid + '\', \'' + escaped_name + '\');">' + Common._e("Remove") + '</a>';
|
||||
else
|
||||
html += '<a href="#" class="one-button add talk-images" onclick="return Favorites.addThis(\'' + escaped_xid + '\', \'' + escaped_name + '\');">' + Common._e("Add") + '</a>';
|
||||
if(DataStore.existDB(Connection.desktop_hash, 'favorites', room_xid)) {
|
||||
html += '<a href="#" ' +
|
||||
'class="one-button remove talk-images" ' +
|
||||
'onclick="return Favorites.removeThis(\'' + escaped_xid + '\', \'' + escaped_name + '\');"' +
|
||||
'>' +
|
||||
Common._e("Remove") +
|
||||
'</a>';
|
||||
} else {
|
||||
html += '<a href="#" ' +
|
||||
'class="one-button add talk-images" ' +
|
||||
'onclick="return Favorites.addThis(\'' + escaped_xid + '\', \'' + escaped_name + '\');"' +
|
||||
'>' +
|
||||
Common._e("Add") +
|
||||
'</a>';
|
||||
}
|
||||
|
||||
// Close the room HTML
|
||||
html += '</div>';
|
||||
|
@ -529,16 +571,15 @@ var Favorites = (function () {
|
|||
});
|
||||
|
||||
// Append this code to the popup
|
||||
$(path + 'fsearch-results').append(html);
|
||||
path_sel.find('.fsearch-results').append(html);
|
||||
} else {
|
||||
path_sel.find('.fsearch-noresults').show();
|
||||
}
|
||||
|
||||
else
|
||||
$(path + 'fsearch-noresults').show();
|
||||
|
||||
Console.info('Rooms retrieved: ' + from);
|
||||
}
|
||||
|
||||
$(path + 'wait').hide();
|
||||
path_sel.find('.wait').hide();
|
||||
} catch(e) {
|
||||
Console.error('Favorites.handleGCList', e);
|
||||
}
|
||||
|
@ -556,7 +597,14 @@ var Favorites = (function () {
|
|||
|
||||
try {
|
||||
self.quit();
|
||||
Chat.checkCreate(room, 'groupchat', '', '', Common.getXIDNick(room));
|
||||
|
||||
Chat.checkCreate(
|
||||
room,
|
||||
'groupchat',
|
||||
'',
|
||||
'',
|
||||
Common.getXIDNick(room)
|
||||
);
|
||||
} catch(e) {
|
||||
Console.error('Favorites.join', e);
|
||||
} finally {
|
||||
|
@ -589,7 +637,14 @@ var Favorites = (function () {
|
|||
$('#roster .gc-join-first-option, #favorites .fedit-head-select-first-option').after(html);
|
||||
|
||||
// We store the informations
|
||||
var value = '<groupchat><xid>' + xid.htmlEnc() + '</xid><name>' + name.htmlEnc() + '</name><nick>' + nick.htmlEnc() + '</nick><autojoin>' + autojoin.htmlEnc() + '</autojoin><password>' + password.htmlEnc() + '</password></groupchat>';
|
||||
var value = '<groupchat>' +
|
||||
'<xid>' + xid.htmlEnc() + '</xid>' +
|
||||
'<name>' + name.htmlEnc() + '</name>' +
|
||||
'<nick>' + nick.htmlEnc() + '</nick>' +
|
||||
'<autojoin>' + autojoin.htmlEnc() + '</autojoin>' +
|
||||
'<password>' + password.htmlEnc() + '</password>' +
|
||||
'</groupchat>';
|
||||
|
||||
DataStore.setDB(Connection.desktop_hash, 'favorites', xid, value);
|
||||
} catch(e) {
|
||||
Console.error('Favorites.display', e);
|
||||
|
@ -621,13 +676,20 @@ var Favorites = (function () {
|
|||
var data = Common.XMLFromString(DataStore.storageDB.getItem(current));
|
||||
|
||||
// Add the current favorite to the HTML code
|
||||
html += '<option value="' + Common.encodeQuotes($(data).find('xid').text()) + '">' + $(data).find('name').text().htmlEnc() + '</option>';
|
||||
html += '<option value="' + Common.encodeQuotes($(data).find('xid').text()) + '">' +
|
||||
$(data).find('name').text().htmlEnc() +
|
||||
'</option>';
|
||||
}
|
||||
}
|
||||
|
||||
// Generate specific HTML code
|
||||
var favorites_bubble = '<option value="none" class="gc-join-first-option" selected="">' + Common._e("Select a favorite") + '</option>' + html;
|
||||
var favorites_popup = '<option value="none" class="fedit-head-select-first-option" selected="">' + Common._e("Select a favorite") + '</option>' + html;
|
||||
var favorites_bubble = '<option value="none" class="gc-join-first-option" selected="">' +
|
||||
Common._e("Select a favorite") +
|
||||
'</option>' + html;
|
||||
|
||||
var favorites_popup = '<option value="none" class="fedit-head-select-first-option" selected="">' +
|
||||
Common._e("Select a favorite") +
|
||||
'</option>' + html;
|
||||
|
||||
// Append the HTML code
|
||||
$('#roster .buddy-conf-groupchat-select').html(favorites_bubble);
|
||||
|
@ -647,29 +709,31 @@ var Favorites = (function () {
|
|||
self.instance = function() {
|
||||
|
||||
try {
|
||||
var path = '#favorites .';
|
||||
var favorites_sel = $('#favorites');
|
||||
|
||||
// Keyboard events
|
||||
$(path + 'fsearch-head-server').keyup(function(e) {
|
||||
favorites_sel.find('.fsearch-head-server').keyup(function(e) {
|
||||
if(e.keyCode == 13) {
|
||||
var this_sel = $(this);
|
||||
|
||||
// No value?
|
||||
if(!$(this).val())
|
||||
$(this).val(HOST_MUC);
|
||||
if(!this_sel.val()) {
|
||||
this_sel.val(HOST_MUC);
|
||||
}
|
||||
|
||||
// Get the list
|
||||
self.getGCList();
|
||||
}
|
||||
});
|
||||
|
||||
$(path + 'fedit-line input').keyup(function(e) {
|
||||
favorites_sel.find('.fedit-line input').keyup(function(e) {
|
||||
if(e.keyCode == 13) {
|
||||
// Edit a favorite
|
||||
if($(path + 'fedit-edit').is(':visible'))
|
||||
if(favorites_sel.find('.fedit-edit').is(':visible')) {
|
||||
self.terminateThis('edit');
|
||||
|
||||
// Add a favorite
|
||||
else
|
||||
} else {
|
||||
self.terminateThis('add');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -677,33 +741,33 @@ var Favorites = (function () {
|
|||
$('.fedit-head-select').change(self.edit);
|
||||
|
||||
// Click events
|
||||
$(path + 'room-switcher').click(function() {
|
||||
$(path + 'favorites-content').hide();
|
||||
favorites_sel.find('.room-switcher').click(function() {
|
||||
favorites_sel.find('.favorites-content').hide();
|
||||
self.reset();
|
||||
});
|
||||
|
||||
$(path + 'room-list').click(function() {
|
||||
$(path + 'favorites-edit').show();
|
||||
favorites_sel.find('.room-list').click(function() {
|
||||
favorites_sel.find('.favorites-edit').show();
|
||||
});
|
||||
|
||||
$(path + 'room-search').click(function() {
|
||||
$(path + 'favorites-search').show();
|
||||
favorites_sel.find('.room-search').click(function() {
|
||||
favorites_sel.find('.favorites-search').show();
|
||||
self.getGCList();
|
||||
});
|
||||
|
||||
$(path + 'fedit-add').click(function() {
|
||||
favorites_sel.find('.fedit-add').click(function() {
|
||||
return self.terminateThis('add');
|
||||
});
|
||||
|
||||
$(path + 'fedit-edit').click(function() {
|
||||
favorites_sel.find('.fedit-edit').click(function() {
|
||||
return self.terminateThis('edit');
|
||||
});
|
||||
|
||||
$(path + 'fedit-remove').click(function() {
|
||||
favorites_sel.find('.fedit-remove').click(function() {
|
||||
return self.terminateThis('remove');
|
||||
});
|
||||
|
||||
$(path + 'bottom .finish').click(function() {
|
||||
favorites_sel.find('.bottom .finish').click(function() {
|
||||
return self.quit();
|
||||
});
|
||||
} catch(e) {
|
||||
|
|
|
@ -103,7 +103,7 @@ var Features = (function () {
|
|||
};
|
||||
|
||||
// Markers
|
||||
var namespaces = [NS_PUBSUB, NS_PUBSUB_CN, NS_URN_MAM, NS_COMMANDS, NS_URN_CARBONS];
|
||||
var namespaces = [NS_PUBSUB, NS_PUBSUB_CN, NS_URN_MAM, NS_COMMANDS, NS_URN_CARBONS, NS_URN_CORRECT];
|
||||
|
||||
var identity = selector.find('identity');
|
||||
|
||||
|
@ -218,6 +218,11 @@ var Features = (function () {
|
|||
if(self.enabledMAMPurge()) {
|
||||
$(path + 'mam-purge-hidable').show();
|
||||
}
|
||||
|
||||
// Message correction features
|
||||
if(self.enabledCorrection()) {
|
||||
$(path + 'correction-hidable').show();
|
||||
}
|
||||
|
||||
// Commands features
|
||||
if(self.enabledCommands()) {
|
||||
|
@ -385,6 +390,22 @@ var Features = (function () {
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the XMPP server correction support
|
||||
* @public
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.enabledCorrection = function() {
|
||||
|
||||
try {
|
||||
return self.isEnabled(NS_URN_CORRECT);
|
||||
} catch(e) {
|
||||
Console.error('Features.enabledCorrection', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Normalizes the XMPP server name
|
||||
* @private
|
||||
|
|
|
@ -20,6 +20,300 @@ var Filter = (function () {
|
|||
var self = {};
|
||||
|
||||
|
||||
/* Constants */
|
||||
self.message_regex = {
|
||||
'commands': {
|
||||
'me': /((^)|((.+)(>)))(\/me )([^<]+)/
|
||||
},
|
||||
|
||||
'emotes': {
|
||||
'angry': [
|
||||
/(:-?@)($|\s|<)/gi,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'bat': [
|
||||
/(:-?\[)($|\s|<)/gi,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'beer': [
|
||||
/(\(B\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'biggrin': [
|
||||
/((:-?D)|(XD))($|\s|<)/gi,
|
||||
'$4'
|
||||
],
|
||||
|
||||
'blush': [
|
||||
/(:-?\$)($|\s|<)/gi,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'boy': [
|
||||
/(\(Z\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'brflower': [
|
||||
/(\(W\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'brheart': [
|
||||
/((<\/3)|(\(U\)))($|\s|<)/g,
|
||||
'$4'
|
||||
],
|
||||
|
||||
'coffee': [
|
||||
/(\(C\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'coolglasses': [
|
||||
/((8-\))|(\(H\)))($|\s|<)/g,
|
||||
'$4'
|
||||
],
|
||||
|
||||
'cry': [
|
||||
/(:'-?\()($|\s|<)/gi,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'cuffs': [
|
||||
/(\(%\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'devil': [
|
||||
/(\]:-?>)($|\s|<)/gi,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'drink': [
|
||||
/(\(D\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'flower': [
|
||||
/(@}->--)($|\s|<)/gi,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'frowning': [
|
||||
/((:-?\/)|(:-?S))($|\s|<)/gi,
|
||||
'$4'
|
||||
],
|
||||
|
||||
'girl': [
|
||||
/(\(X\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'heart': [
|
||||
/((<3)|(\(L\)))($|\s|<)/g,
|
||||
'$4'
|
||||
],
|
||||
|
||||
'hugleft': [
|
||||
/(\(}\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'hugright': [
|
||||
/(\({\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'kis': [
|
||||
/(:-?{})($|\s|<)/gi,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'lamp': [
|
||||
/(\(I\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'lion': [
|
||||
/(:-?3)($|\s|<)/gi,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'mail': [
|
||||
/(\(E\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'moon': [
|
||||
/(\(S\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'music': [
|
||||
/(\(8\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'oh': [
|
||||
/((=-?O)|(:-?O))($|\s|<)/gi,
|
||||
'$4'
|
||||
],
|
||||
|
||||
'phone': [
|
||||
/(\(T\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'photo': [
|
||||
/(\(P\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'puke': [
|
||||
/(:-?!)($|\s|<)/gi,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'pussy': [
|
||||
/(\(@\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'rainbow': [
|
||||
/(\(R\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'smile': [
|
||||
/(:-?\))($|\s|<)/gi,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'star': [
|
||||
/(\(\*\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'stare': [
|
||||
/(:-?\|)($|\s|<)/gi,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'thumbdown': [
|
||||
/(\(N\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'thumbup': [
|
||||
/(\(Y\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'tongue': [
|
||||
/(:-?P)($|\s|<)/gi,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'unhappy': [
|
||||
/(:-?\()($|\s|<)/gi,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'wink': [
|
||||
/(;-?\))($|\s|<)/gi,
|
||||
'$2'
|
||||
]
|
||||
|
||||
},
|
||||
|
||||
'formatting': {
|
||||
'bold': [
|
||||
/(^|\s|>|\()((\*)([^<>'"\*]+)(\*))($|\s|<|\))/gi,
|
||||
'$1<b>$2</b>$6'
|
||||
],
|
||||
|
||||
'italic': [
|
||||
/(^|\s|>|\()((\/)([^<>'"\/]+)(\/))($|\s|<|\))/gi,
|
||||
'$1<em>$2</em>$6'
|
||||
],
|
||||
|
||||
'underline': [
|
||||
/(^|\s|>|\()((_)([^<>'"_]+)(_))($|\s|<|\))/gi,
|
||||
'$1<span style="text-decoration: underline;">$2</span>$6'
|
||||
]
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
self.xhtml_allow = {
|
||||
'elements': [
|
||||
'a',
|
||||
'abbr',
|
||||
'acronym',
|
||||
'address',
|
||||
'blockquote',
|
||||
'body',
|
||||
'br',
|
||||
'cite',
|
||||
'code',
|
||||
'dd',
|
||||
'dfn',
|
||||
'div',
|
||||
'dt',
|
||||
'em',
|
||||
'h1',
|
||||
'h2',
|
||||
'h3',
|
||||
'h4',
|
||||
'h5',
|
||||
'h6',
|
||||
'head',
|
||||
'html',
|
||||
'kbd',
|
||||
'li',
|
||||
'ol',
|
||||
'p',
|
||||
'pre',
|
||||
'q',
|
||||
'samp',
|
||||
'span',
|
||||
'strong',
|
||||
'title',
|
||||
'ul',
|
||||
'var'
|
||||
],
|
||||
|
||||
'attributes': [
|
||||
'accesskey',
|
||||
'alt',
|
||||
'charset',
|
||||
'cite',
|
||||
'class',
|
||||
'height',
|
||||
'href',
|
||||
'hreflang',
|
||||
'id',
|
||||
'longdesc',
|
||||
'profile',
|
||||
'rel',
|
||||
'rev',
|
||||
'src',
|
||||
'style',
|
||||
'tabindex',
|
||||
'title',
|
||||
'type',
|
||||
'uri',
|
||||
'version',
|
||||
'width',
|
||||
'xml:lang',
|
||||
'xmlns'
|
||||
]
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Generates a given emoticon HTML code
|
||||
* @public
|
||||
|
@ -42,83 +336,64 @@ var Filter = (function () {
|
|||
/**
|
||||
* Filters a given message
|
||||
* @public
|
||||
* @param {string} neutralMessage
|
||||
* @param {string} message
|
||||
* @param {string} nick
|
||||
* @param {string} html_escape
|
||||
* @return {string}
|
||||
*/
|
||||
self.message = function(neutralMessage, nick, html_escape) {
|
||||
self.message = function(message, nick, html_escape) {
|
||||
|
||||
try {
|
||||
var filteredMessage = neutralMessage;
|
||||
var filtered = message;
|
||||
|
||||
// We encode the HTML special chars
|
||||
if(html_escape)
|
||||
filteredMessage = filteredMessage.htmlEnc();
|
||||
|
||||
// /me command
|
||||
filteredMessage = filteredMessage.replace(/((^)|((.+)(>)))(\/me )([^<]+)/, nick + ' $7')
|
||||
|
||||
// We replace the smilies text into images
|
||||
.replace(/(:-?@)($|\s|<)/gi, self.emoteImage('angry', '$1', '$2'))
|
||||
.replace(/(:-?\[)($|\s|<)/gi, self.emoteImage('bat', '$1', '$2'))
|
||||
.replace(/(\(B\))($|\s|<)/g, self.emoteImage('beer', '$1', '$2'))
|
||||
.replace(/((:-?D)|(XD))($|\s|<)/gi, self.emoteImage('biggrin', '$1', '$4'))
|
||||
.replace(/(:-?\$)($|\s|<)/gi, self.emoteImage('blush', '$1', '$2'))
|
||||
.replace(/(\(Z\))($|\s|<)/g, self.emoteImage('boy', '$1', '$2'))
|
||||
.replace(/(\(W\))($|\s|<)/g, self.emoteImage('brflower', '$1', '$2'))
|
||||
.replace(/((<\/3)|(\(U\)))($|\s|<)/g, self.emoteImage('brheart', '$1', '$4'))
|
||||
.replace(/(\(C\))($|\s|<)/g, self.emoteImage('coffee', '$1', '$2'))
|
||||
.replace(/((8-\))|(\(H\)))($|\s|<)/g, self.emoteImage('coolglasses', '$1', '$4'))
|
||||
.replace(/(:'-?\()($|\s|<)/gi, self.emoteImage('cry', '$1', '$2'))
|
||||
.replace(/(\(%\))($|\s|<)/g, self.emoteImage('cuffs', '$1', '$2'))
|
||||
.replace(/(\]:-?>)($|\s|<)/gi, self.emoteImage('devil', '$1', '$2'))
|
||||
.replace(/(\(D\))($|\s|<)/g, self.emoteImage('drink', '$1', '$2'))
|
||||
.replace(/(@}->--)($|\s|<)/gi, self.emoteImage('flower', '$1', '$2'))
|
||||
.replace(/((:-?\/)|(:-?S))($|\s|<)/gi, self.emoteImage('frowning', '$1', '$4'))
|
||||
.replace(/(\(X\))($|\s|<)/g, self.emoteImage('girl', '$1', '$2'))
|
||||
.replace(/((<3)|(\(L\)))($|\s|<)/g, self.emoteImage('heart', '$1', '$4'))
|
||||
.replace(/(\(}\))($|\s|<)/g, self.emoteImage('hugleft', '$1', '$2'))
|
||||
.replace(/(\({\))($|\s|<)/g, self.emoteImage('hugright', '$1', '$2'))
|
||||
.replace(/(:-?{})($|\s|<)/gi, self.emoteImage('kiss', '$1', '$2'))
|
||||
.replace(/(\(I\))($|\s|<)/g, self.emoteImage('lamp', '$1', '$2'))
|
||||
.replace(/(:-?3)($|\s|<)/gi, self.emoteImage('lion', '$1', '$2'))
|
||||
.replace(/(\(E\))($|\s|<)/g, self.emoteImage('mail', '$1', '$2'))
|
||||
.replace(/(\(S\))($|\s|<)/g, self.emoteImage('moon', '$1', '$2'))
|
||||
.replace(/(\(8\))($|\s|<)/g, self.emoteImage('music', '$1', '$2'))
|
||||
.replace(/((=-?O)|(:-?O))($|\s|<)/gi, self.emoteImage('oh', '$1', '$4'))
|
||||
.replace(/(\(T\))($|\s|<)/g, self.emoteImage('phone', '$1', '$2'))
|
||||
.replace(/(\(P\))($|\s|<)/g, self.emoteImage('photo', '$1', '$2'))
|
||||
.replace(/(:-?!)($|\s|<)/gi, self.emoteImage('puke', '$1', '$2'))
|
||||
.replace(/(\(@\))($|\s|<)/g, self.emoteImage('pussy', '$1', '$2'))
|
||||
.replace(/(\(R\))($|\s|<)/g, self.emoteImage('rainbow', '$1', '$2'))
|
||||
.replace(/(:-?\))($|\s|<)/gi, self.emoteImage('smile', '$1', '$2'))
|
||||
.replace(/(\(\*\))($|\s|<)/g, self.emoteImage('star', '$1', '$2'))
|
||||
.replace(/(:-?\|)($|\s|<)/gi, self.emoteImage('stare', '$1', '$2'))
|
||||
.replace(/(\(N\))($|\s|<)/g, self.emoteImage('thumbdown', '$1', '$2'))
|
||||
.replace(/(\(Y\))($|\s|<)/g, self.emoteImage('thumbup', '$1', '$2'))
|
||||
.replace(/(:-?P)($|\s|<)/gi, self.emoteImage('tongue', '$1', '$2'))
|
||||
.replace(/(:-?\()($|\s|<)/gi, self.emoteImage('unhappy', '$1', '$2'))
|
||||
.replace(/(;-?\))($|\s|<)/gi, self.emoteImage('wink', '$1', '$2'))
|
||||
|
||||
// Text in bold
|
||||
.replace(/(^|\s|>|\()((\*)([^<>'"\*]+)(\*))($|\s|<|\))/gi, '$1<b>$2</b>$6')
|
||||
|
||||
// Italic text
|
||||
.replace(/(^|\s|>|\()((\/)([^<>'"\/]+)(\/))($|\s|<|\))/gi, '$1<em>$2</em>$6')
|
||||
|
||||
// Underlined text
|
||||
.replace(/(^|\s|>|\()((_)([^<>'"_]+)(_))($|\s|<|\))/gi, '$1<span style="text-decoration: underline;">$2</span>$6');
|
||||
|
||||
// Add the links
|
||||
if(html_escape) {
|
||||
filteredMessage = Links.apply(filteredMessage, 'desktop');
|
||||
filtered = filtered.htmlEnc();
|
||||
}
|
||||
|
||||
// Filter integratebox links
|
||||
filteredMessage = IntegrateBox.filter(filteredMessage);
|
||||
// Security: don't filter huge messages (avoids crash attacks)
|
||||
if(filtered.length < 10000) {
|
||||
// /me command
|
||||
filtered = filtered.replace(self.message_regex.commands.me, nick + ' $7');
|
||||
|
||||
// We replace the smilies text into images
|
||||
var cur_emote;
|
||||
|
||||
for(var cur_emote_name in self.message_regex.emotes) {
|
||||
cur_emote = self.message_regex.emotes[cur_emote_name];
|
||||
|
||||
filtered = filtered.replace(
|
||||
cur_emote[0],
|
||||
self.emoteImage(
|
||||
cur_emote_name,
|
||||
'$1',
|
||||
cur_emote[1]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Text formatting
|
||||
var cur_formatting;
|
||||
|
||||
for(var cur_formatting_name in self.message_regex.formatting) {
|
||||
cur_formatting = self.message_regex.formatting[cur_formatting_name];
|
||||
|
||||
filtered = filtered.replace(
|
||||
cur_formatting[0],
|
||||
cur_formatting[1]
|
||||
);
|
||||
}
|
||||
|
||||
// Add the links
|
||||
if(html_escape) {
|
||||
filtered = Links.apply(filtered, 'desktop');
|
||||
}
|
||||
|
||||
// Filter integratebox links
|
||||
filtered = IntegrateBox.filter(filtered);
|
||||
}
|
||||
|
||||
return filteredMessage;
|
||||
return filtered;
|
||||
} catch(e) {
|
||||
Console.error('Filter.message', e);
|
||||
}
|
||||
|
@ -135,85 +410,23 @@ var Filter = (function () {
|
|||
self.xhtml = function(code) {
|
||||
|
||||
try {
|
||||
// Allowed elements array
|
||||
var elements = new Array(
|
||||
'a',
|
||||
'abbr',
|
||||
'acronym',
|
||||
'address',
|
||||
'blockquote',
|
||||
'body',
|
||||
'br',
|
||||
'cite',
|
||||
'code',
|
||||
'dd',
|
||||
'dfn',
|
||||
'div',
|
||||
'dt',
|
||||
'em',
|
||||
'h1',
|
||||
'h2',
|
||||
'h3',
|
||||
'h4',
|
||||
'h5',
|
||||
'h6',
|
||||
'head',
|
||||
'html',
|
||||
'kbd',
|
||||
'li',
|
||||
'ol',
|
||||
'p',
|
||||
'pre',
|
||||
'q',
|
||||
'samp',
|
||||
'span',
|
||||
'strong',
|
||||
'title',
|
||||
'ul',
|
||||
'var'
|
||||
);
|
||||
var code_sel = $(code);
|
||||
|
||||
// Allowed attributes array
|
||||
var attributes = new Array(
|
||||
'accesskey',
|
||||
'alt',
|
||||
'charset',
|
||||
'cite',
|
||||
'class',
|
||||
'height',
|
||||
'href',
|
||||
'hreflang',
|
||||
'id',
|
||||
'longdesc',
|
||||
'profile',
|
||||
'rel',
|
||||
'rev',
|
||||
'src',
|
||||
'style',
|
||||
'tabindex',
|
||||
'title',
|
||||
'type',
|
||||
'uri',
|
||||
'version',
|
||||
'width',
|
||||
'xml:lang',
|
||||
'xmlns'
|
||||
);
|
||||
|
||||
// Check if Filter for XHTML-IM images is enabled
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'no-xhtml-images') != '1') {
|
||||
elements.push("img");
|
||||
self.xhtml_allow.elements.push("img");
|
||||
}
|
||||
|
||||
// Remove forbidden elements
|
||||
$(code).find('html body *').each(function() {
|
||||
code_sel.find('html body *').each(function() {
|
||||
// This element is not authorized
|
||||
if(!Utils.existArrayValue(elements, (this).nodeName.toLowerCase()))
|
||||
if(!Utils.existArrayValue(self.xhtml_allow.elements, (this).nodeName.toLowerCase())) {
|
||||
$(this).remove();
|
||||
}
|
||||
});
|
||||
|
||||
// Remove forbidden attributes
|
||||
$(code).find('html body *').each(function() {
|
||||
code_sel.find('html body *').each(function() {
|
||||
// Put a pointer on this element (jQuery way & normal way)
|
||||
var cSelector = $(this);
|
||||
var cElement = (this);
|
||||
|
@ -226,15 +439,17 @@ var Filter = (function () {
|
|||
var cVal = cAttr.value;
|
||||
|
||||
// This attribute is not authorized, or contains JS code
|
||||
if(!Utils.existArrayValue(attributes, cName.toLowerCase()) || ((cVal.toLowerCase()).match(/(^|"|')javascript:/)))
|
||||
if(!Utils.existArrayValue(self.xhtml_allow.attributes, cName.toLowerCase()) ||
|
||||
((cVal.toLowerCase()).match(/(^|"|')javascript:/))) {
|
||||
cSelector.removeAttr(cName);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Filter some other elements
|
||||
$(code).find('a').attr('target', '_blank');
|
||||
code_sel.find('a').attr('target', '_blank');
|
||||
|
||||
return $(code).find('html body').html();
|
||||
return code_sel.find('html body').html();
|
||||
} catch(e) {
|
||||
Console.error('Filter.xhtml', e);
|
||||
}
|
||||
|
|
|
@ -24,6 +24,196 @@ var Groupchat = (function () {
|
|||
var JOIN_SUGGEST = [];
|
||||
|
||||
|
||||
/**
|
||||
* Apply generate events
|
||||
* @private
|
||||
* @param {object} input_sel
|
||||
* @param {string} hash
|
||||
* @param {string} room
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._createEvents = function(input_sel, hash, room) {
|
||||
|
||||
try {
|
||||
self._createEventsInput(input_sel, hash);
|
||||
self._createEventsKey(input_sel, hash, room);
|
||||
} catch(e) {
|
||||
Console.error('Groupchat._createEvents', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply generate events (input)
|
||||
* @private
|
||||
* @param {object} input_sel
|
||||
* @param {string} hash
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._createEventsInput = function(input_sel, hash) {
|
||||
|
||||
try {
|
||||
// Focus event
|
||||
input_sel.focus(function() {
|
||||
// Clean notifications for this chat
|
||||
Interface.chanCleanNotify(hash);
|
||||
|
||||
// Store focus on this chat!
|
||||
Interface.chat_focus_hash = hash;
|
||||
});
|
||||
|
||||
// Blur event
|
||||
input_sel.blur(function() {
|
||||
// Reset storage about focus on this chat!
|
||||
if(Interface.chat_focus_hash == hash) {
|
||||
Interface.chat_focus_hash = null;
|
||||
}
|
||||
|
||||
// Reset autocompletion
|
||||
Autocompletion.reset(hash);
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Groupchat._createEventsInput', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply generate events (key)
|
||||
* @private
|
||||
* @param {object} input_sel
|
||||
* @param {string} hash
|
||||
* @param {string} room
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._createEventsKey = function(input_sel, hash, room) {
|
||||
|
||||
try {
|
||||
// Lock to the input
|
||||
input_sel.keydown(function(e) {
|
||||
// Enter key
|
||||
if(e.keyCode == 13) {
|
||||
// If shift key (without any others modifiers) was pressed, add a new line
|
||||
if(e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey) {
|
||||
input_sel.val(input_sel.val() + '\n');
|
||||
} else {
|
||||
if(Correction.isIn(room) === true) {
|
||||
var corrected_value = input_sel.val().trim();
|
||||
|
||||
if(corrected_value) {
|
||||
// Send the corrected message
|
||||
Correction.send(room, 'groupchat', corrected_value);
|
||||
}
|
||||
|
||||
Correction.leave(room);
|
||||
} else {
|
||||
// Send the message
|
||||
Message.send(hash, 'groupchat');
|
||||
|
||||
// Reset the composing database entry
|
||||
DataStore.setDB(Connection.desktop_hash, 'chatstate', room, 'off');
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove chars (leave correction)
|
||||
else if(e.keyCode == 8) {
|
||||
// Leave correction mode? (another way, by flushing input value progressively)
|
||||
if(Correction.isIn(room) === true && !input_sel.val()) {
|
||||
Correction.leave(room);
|
||||
}
|
||||
}
|
||||
|
||||
// Tabulation key (without any modifiers)
|
||||
else if(!e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey && e.keyCode == 9) {
|
||||
Autocompletion.create(hash);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Reset the autocompleter
|
||||
else {
|
||||
Autocompletion.reset(hash);
|
||||
}
|
||||
});
|
||||
|
||||
input_sel.keyup(function(e) {
|
||||
if(e.keyCode == 27) {
|
||||
// Escape key
|
||||
input_sel.val('');
|
||||
|
||||
// Leave correction mode? (simple escape way)
|
||||
if(Correction.isIn(room) === true) {
|
||||
Correction.leave(room);
|
||||
}
|
||||
} else {
|
||||
Correction.detect(room, input_sel);
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Groupchat._createEventsKey', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply suggest check events
|
||||
* @private
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._suggestCheckEvents = function() {
|
||||
|
||||
try {
|
||||
// Click events
|
||||
$('#suggest .content a.one').click(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// Add/remove the active class
|
||||
this_sel.toggleClass('active');
|
||||
|
||||
// We require at least one room to be chosen
|
||||
if(Common.exists('#suggest .content a.one.active')) {
|
||||
$('#suggest a.next').removeClass('disabled');
|
||||
} else {
|
||||
$('#suggest a.next').addClass('disabled');
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#suggest a.next').click(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// Disabled?
|
||||
if(this_sel.hasClass('disabled')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Store groupchats to join?
|
||||
if(this_sel.is('.continue')) {
|
||||
$('#suggest .content a.one.active').each(function() {
|
||||
JOIN_SUGGEST.push(this_sel.attr('data-xid'));
|
||||
});
|
||||
}
|
||||
|
||||
// Switch to talk UI
|
||||
$('#suggest').remove();
|
||||
Connection.triggerConnected();
|
||||
|
||||
return false;
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Groupchat._suggestCheckEvents', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Displays the MUC admin elements
|
||||
* @public
|
||||
|
@ -37,16 +227,19 @@ var Groupchat = (function () {
|
|||
|
||||
try {
|
||||
// We must be in the "login" mode
|
||||
if(Utils.isAnonymous())
|
||||
if(Utils.isAnonymous()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We check if the user is a room owner or administrator to give him privileges
|
||||
if(affiliation == 'owner' || affiliation == 'admin')
|
||||
if(affiliation == 'owner' || affiliation == 'admin') {
|
||||
$('#' + id + ' .tools-mucadmin').show();
|
||||
}
|
||||
|
||||
// We check if the room hasn't been yet created
|
||||
if(statuscode == 201)
|
||||
if(statuscode == 201) {
|
||||
Board.openThisInfo(4);
|
||||
}
|
||||
|
||||
// We add the click event
|
||||
$('#' + id + ' .tools-mucadmin').click(function() {
|
||||
|
@ -80,14 +273,16 @@ var Groupchat = (function () {
|
|||
// No nickname?
|
||||
if(!nickname) {
|
||||
// Get some values
|
||||
if(!Utils.isAnonymous())
|
||||
if(!Utils.isAnonymous()) {
|
||||
nickname = Name.getNick();
|
||||
else
|
||||
} else {
|
||||
nickname = ANONYMOUS_NICK;
|
||||
}
|
||||
|
||||
// If the nickname could not be retrieved, ask it
|
||||
if(!nickname)
|
||||
if(!nickname) {
|
||||
self.generateMUCAsk('nickname', room, hash, nickname, password);
|
||||
}
|
||||
}
|
||||
|
||||
// Got our nickname?
|
||||
|
@ -126,10 +321,12 @@ var Groupchat = (function () {
|
|||
var room = Common.bareXID(from);
|
||||
var nickname = Common.thisResource(from);
|
||||
var hash = hex_md5(room);
|
||||
var id = presence.getID();
|
||||
|
||||
// No ID: must fix M-Link bug
|
||||
if(presence.getID() === null) {
|
||||
presence.setID(1);
|
||||
if(id === null) {
|
||||
id = 1;
|
||||
presence.setID(id);
|
||||
}
|
||||
|
||||
Console.info('First MUC presence: ' + from);
|
||||
|
@ -139,11 +336,17 @@ var Groupchat = (function () {
|
|||
// Define some stuffs
|
||||
var muc_user = $(xml).find('x[xmlns="' + NS_MUC_USER + '"]');
|
||||
var affiliation = muc_user.find('item').attr('affiliation');
|
||||
var statuscode = parseInt(muc_user.find('status').attr('code'));
|
||||
var statuscode = parseInt(muc_user.find('status').attr('code'));
|
||||
|
||||
// Handle my presence
|
||||
Presence.handle(presence);
|
||||
|
||||
// Configure the new room
|
||||
if(affiliation == 'owner' || affiliation == 'admin') {
|
||||
console.debug('presence', presence.xml());
|
||||
self._initialConfiguration(id, room);
|
||||
}
|
||||
|
||||
// Check if I am a room owner
|
||||
self.openAdmin(affiliation, hash, room, statuscode);
|
||||
|
||||
|
@ -279,65 +482,16 @@ var Groupchat = (function () {
|
|||
});
|
||||
|
||||
// Must show the add button?
|
||||
if(!DataStore.existDB('favorites', room))
|
||||
if(!DataStore.existDB(Connection.desktop_hash, 'favorites', room)) {
|
||||
$('#' + hash + ' .tools-add').show();
|
||||
}
|
||||
|
||||
// The event handlers
|
||||
var inputDetect = $('#' + hash + ' .message-area');
|
||||
|
||||
// Focus event
|
||||
inputDetect.focus(function() {
|
||||
// Clean notifications for this chat
|
||||
Interface.chanCleanNotify(hash);
|
||||
|
||||
// Store focus on this chat!
|
||||
Interface.chat_focus_hash = hash;
|
||||
});
|
||||
|
||||
// Blur event
|
||||
inputDetect.blur(function() {
|
||||
// Reset storage about focus on this chat!
|
||||
if(Interface.chat_focus_hash == hash)
|
||||
Interface.chat_focus_hash = null;
|
||||
|
||||
// Reset autocompletion
|
||||
Autocompletion.reset(hash);
|
||||
});
|
||||
|
||||
// Lock to the input
|
||||
inputDetect.keydown(function(e) {
|
||||
// Enter key
|
||||
if(e.keyCode == 13) {
|
||||
// If shift key (without any others modifiers) was pressed, add a new line
|
||||
if(e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey)
|
||||
inputDetect.val(inputDetect.val() + '\n');
|
||||
|
||||
// Send the message
|
||||
else {
|
||||
Message.send(hash, 'groupchat');
|
||||
|
||||
// Reset the composing database entry
|
||||
DataStore.setDB(Connection.desktop_hash, 'chatstate', room, 'off');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Tabulation key (without any modifiers)
|
||||
else if(!e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey && e.keyCode == 9) {
|
||||
Autocompletion.create(hash);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Reset the autocompleter
|
||||
else {
|
||||
Autocompletion.reset(hash);
|
||||
}
|
||||
});
|
||||
var input_sel = $('#' + hash + ' .message-area');
|
||||
self._createEvents(input_sel, hash, room);
|
||||
|
||||
// Chatstate events
|
||||
ChatState.events(inputDetect, room, hash, 'groupchat');
|
||||
ChatState.events(input_sel, room, hash, 'groupchat');
|
||||
|
||||
// Get the current muc informations and content
|
||||
self.getMUC(room, nickname, password);
|
||||
|
@ -361,23 +515,26 @@ var Groupchat = (function () {
|
|||
var new_arr = [];
|
||||
|
||||
// Try to split it
|
||||
if(GROUPCHATS_JOIN.indexOf(',') != -1)
|
||||
if(GROUPCHATS_JOIN.indexOf(',') != -1) {
|
||||
muc_arr = GROUPCHATS_JOIN.split(',');
|
||||
}
|
||||
|
||||
for(var i in muc_arr) {
|
||||
// Get the current value
|
||||
var muc_current = $.trim(muc_arr[i]);
|
||||
|
||||
// No current value?
|
||||
if(!muc_current)
|
||||
if(!muc_current) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Filter the current value
|
||||
muc_current = Common.generateXID(muc_current, 'groupchat');
|
||||
|
||||
// Add the current value
|
||||
if(!Utils.existArrayValue(new_arr, muc_current))
|
||||
if(!Utils.existArrayValue(new_arr, muc_current)) {
|
||||
new_arr.push(muc_current);
|
||||
}
|
||||
}
|
||||
|
||||
return new_arr;
|
||||
|
@ -397,8 +554,9 @@ var Groupchat = (function () {
|
|||
|
||||
try {
|
||||
// Nothing to join?
|
||||
if(!JOIN_SUGGEST)
|
||||
if(!JOIN_SUGGEST) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Join the chats
|
||||
if(JOIN_SUGGEST.length) {
|
||||
|
@ -425,8 +583,9 @@ var Groupchat = (function () {
|
|||
|
||||
// Must suggest the user?
|
||||
if((GROUPCHATS_SUGGEST == 'on') && groupchat_arr.length) {
|
||||
if(Common.exists('#suggest'))
|
||||
if(Common.exists('#suggest')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create HTML code
|
||||
var html = '<div id="suggest" class="removable">';
|
||||
|
@ -452,39 +611,8 @@ var Groupchat = (function () {
|
|||
// Append HTML code
|
||||
$('body').append(html);
|
||||
|
||||
// Click events
|
||||
$('#suggest .content a.one').click(function() {
|
||||
// Add/remove the active class
|
||||
$(this).toggleClass('active');
|
||||
|
||||
// We require at least one room to be chosen
|
||||
if(Common.exists('#suggest .content a.one.active'))
|
||||
$('#suggest a.next').removeClass('disabled');
|
||||
else
|
||||
$('#suggest a.next').addClass('disabled');
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#suggest a.next').click(function() {
|
||||
// Disabled?
|
||||
if($(this).hasClass('disabled')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Store groupchats to join?
|
||||
if($(this).is('.continue')) {
|
||||
$('#suggest .content a.one.active').each(function() {
|
||||
JOIN_SUGGEST.push($(this).attr('data-xid'));
|
||||
});
|
||||
}
|
||||
|
||||
// Switch to talk UI
|
||||
$('#suggest').remove();
|
||||
Connection.triggerConnected();
|
||||
|
||||
return false;
|
||||
});
|
||||
// Attach events
|
||||
self._suggestCheckEvents();
|
||||
} else {
|
||||
JOIN_SUGGEST = groupchat_arr;
|
||||
|
||||
|
@ -512,7 +640,7 @@ var Groupchat = (function () {
|
|||
if(!ban_xid) {
|
||||
Board.openThisInfo(6);
|
||||
|
||||
Console.warning('Could not ban user with XID: ' + ban_xid + ' from room: ' + room_xid);
|
||||
Console.warn('Could not ban user with XID: ' + ban_xid + ' from room: ' + room_xid);
|
||||
} else {
|
||||
// We generate the ban IQ
|
||||
var iq = new JSJaCIQ();
|
||||
|
@ -520,10 +648,16 @@ var Groupchat = (function () {
|
|||
iq.setType('set');
|
||||
|
||||
var iqQuery = iq.setQuery(NS_MUC_ADMIN);
|
||||
var item = iqQuery.appendChild(iq.buildNode('item', {'affiliation': 'outcast', 'jid': ban_xid, 'xmlns': NS_MUC_ADMIN}));
|
||||
var item = iqQuery.appendChild(iq.buildNode('item', {
|
||||
'affiliation': 'outcast',
|
||||
'jid': ban_xid,
|
||||
'xmlns': NS_MUC_ADMIN
|
||||
}));
|
||||
|
||||
if(reason) {
|
||||
item.appendChild(iq.buildNode('reason', {'xmlns': NS_MUC_ADMIN}, reason));
|
||||
item.appendChild(iq.buildNode('reason', {
|
||||
'xmlns': NS_MUC_ADMIN
|
||||
}, reason));
|
||||
}
|
||||
|
||||
con.send(iq, Errors.handleReply);
|
||||
|
@ -561,10 +695,16 @@ var Groupchat = (function () {
|
|||
iq.setType('set');
|
||||
|
||||
var iqQuery = iq.setQuery(NS_MUC_ADMIN);
|
||||
var item = iqQuery.appendChild(iq.buildNode('item', {'nick': nick, 'role': 'none', 'xmlns': NS_MUC_ADMIN}));
|
||||
var item = iqQuery.appendChild(iq.buildNode('item', {
|
||||
'nick': nick,
|
||||
'role': 'none',
|
||||
'xmlns': NS_MUC_ADMIN
|
||||
}));
|
||||
|
||||
if(reason) {
|
||||
item.appendChild(iq.buildNode('reason', {'xmlns': NS_MUC_ADMIN}, reason));
|
||||
item.appendChild(iq.buildNode('reason', {
|
||||
'xmlns': NS_MUC_ADMIN
|
||||
}, reason));
|
||||
}
|
||||
|
||||
con.send(iq, Errors.handleReply);
|
||||
|
@ -670,6 +810,50 @@ var Groupchat = (function () {
|
|||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Sends initial configuration of the room
|
||||
* @private
|
||||
* @param {string} pid
|
||||
* @param {string} xid
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._initialConfiguration = function(pid, xid) {
|
||||
|
||||
try {
|
||||
var iq = new JSJaCIQ();
|
||||
|
||||
iq.setTo(xid);
|
||||
iq.setType('set');
|
||||
iq.setID('first-muc-config-' + pid);
|
||||
|
||||
var iqQuery = iq.setQuery(NS_MUC_OWNER);
|
||||
|
||||
// Configure room with nil(null) fields
|
||||
var iqX = iqQuery.appendChild(iq.buildNode('x', {
|
||||
'xmlns': NS_XDATA,
|
||||
'type': 'submit'
|
||||
}));
|
||||
|
||||
// Build a new field node
|
||||
var iqField = iqX.appendChild(iq.buildNode('field', {
|
||||
'var': 'FORM_TYPE',
|
||||
'type': 'hidden',
|
||||
'xmlns': NS_XDATA
|
||||
}));
|
||||
|
||||
iqField.appendChild(iq.buildNode('value', {
|
||||
'xmlns': NS_XDATA
|
||||
}, NS_MUC_CONFIG));
|
||||
|
||||
con.send(iq);
|
||||
|
||||
Console.info('Groupchat._initialConfiguration', 'Sent initial room configuration: ' + xid);
|
||||
} catch(e) {
|
||||
Console.error('Groupchat._initialConfiguration', e);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
@ -677,4 +861,4 @@ var Groupchat = (function () {
|
|||
*/
|
||||
return self;
|
||||
|
||||
})();
|
||||
})();
|
||||
|
|
|
@ -20,6 +20,119 @@ var Home = (function () {
|
|||
var self = {};
|
||||
|
||||
|
||||
/**
|
||||
* Apply change events
|
||||
* @private
|
||||
* @param {object} current_sel
|
||||
* @param {string} div
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._eventsChange = function(current_sel, div) {
|
||||
|
||||
try {
|
||||
// Create the attached events
|
||||
switch(div) {
|
||||
// Login tool
|
||||
case 'loginer':
|
||||
current_sel.find('a.to-anonymous').click(function() {
|
||||
return self.change('anonymouser');
|
||||
});
|
||||
|
||||
current_sel.find('a.advanced').click(self.showAdvanced);
|
||||
current_sel.find('form').submit(self.loginForm);
|
||||
|
||||
break;
|
||||
|
||||
// Anonymous login tool
|
||||
case 'anonymouser':
|
||||
current_sel.find('a.to-home').click(function() {
|
||||
return self.change('loginer');
|
||||
});
|
||||
|
||||
current_sel.find('form').submit(Connection.doAnonymous);
|
||||
|
||||
// Keyup event on anonymous join's room input
|
||||
current_sel.find('input.room').keyup(function() {
|
||||
var value = $(this).val();
|
||||
var report_sel = current_sel.find('.report');
|
||||
var span_sel = current_sel.find('span');
|
||||
|
||||
if(!value) {
|
||||
report_sel.hide();
|
||||
span_sel.text('');
|
||||
} else {
|
||||
report_sel.show();
|
||||
span_sel.text(JAPPIX_LOCATION + '?r=' + value);
|
||||
}
|
||||
});
|
||||
|
||||
break;
|
||||
|
||||
// Register tool
|
||||
case 'registerer':
|
||||
// Server input change
|
||||
$('#home input.server').keyup(function(e) {
|
||||
if($.trim($(this).val()) == HOST_MAIN) {
|
||||
$('#home .captcha_grp').show();
|
||||
$('#home input.captcha').removeAttr('disabled');
|
||||
} else {
|
||||
$('#home .captcha_grp').hide();
|
||||
$('#home input.captcha').attr('disabled', true);
|
||||
}
|
||||
});
|
||||
|
||||
// Register input placeholder
|
||||
// FIXME: breaks IE compatibility
|
||||
//$('#home input[placeholder]').placeholder();
|
||||
|
||||
// Register form submit
|
||||
current_sel.find('form').submit(self.registerForm);
|
||||
|
||||
break;
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Home._eventsChange', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create obsolete form
|
||||
* @private
|
||||
* @param {string} home
|
||||
* @param {string} locale
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._obsolete = function(home, locale) {
|
||||
|
||||
try {
|
||||
// Add the code
|
||||
$(locale).after(
|
||||
'<div class="obsolete">' +
|
||||
'<p>' + Common._e("Your browser is out of date!") + '</p>' +
|
||||
|
||||
'<a class="firefox browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Mozilla Firefox') + '" href="http://www.mozilla.com/firefox/"></a>' +
|
||||
'<a class="chrome browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Google Chrome') + '" href="http://www.google.com/chrome"></a>' +
|
||||
'<a class="safari browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Safari') + '" href="http://www.apple.com/safari/"></a>' +
|
||||
'<a class="opera browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Opera') + '" href="http://www.opera.com/"></a>' +
|
||||
'<a class="ie browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Internet Explorer') + '" href="http://www.microsoft.com/hk/windows/internet-explorer/"></a>' +
|
||||
'</div>'
|
||||
);
|
||||
|
||||
// Display it later
|
||||
$(home + '.obsolete').oneTime('1s', function() {
|
||||
$(this).slideDown();
|
||||
});
|
||||
|
||||
Console.warn('Jappix does not support this browser!');
|
||||
} catch(e) {
|
||||
Console.error('Home._obsolete', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Allows the user to switch the difference home page elements
|
||||
* @public
|
||||
|
@ -76,7 +189,7 @@ var Home = (function () {
|
|||
'<legend>' + Common._e("Required") + '</legend>' +
|
||||
|
||||
'<label for="lnick">' + Common._e("Address") + '</label>' +
|
||||
'<input type="text" class="nick" id="lnick" pattern="[^@/]+" required="" /><span class="jid">@</span><input type="text" class="server" id="lserver" value="' + HOST_MAIN + '" ' + lock_host + ' pattern="[^@/]+" required="" />' +
|
||||
'<input type="text" class="nick" id="lnick" pattern="[^@/]+" required="" /><span class="jid">@</span><input type="text" class="server" id="lserver" value="' + HOST_MAIN + '" ' + lock_host + ' pattern="[^@/]+" required="" list="server" />' +
|
||||
'<label for="lpassword">' + Common._e("Password") + '</label>' +
|
||||
'<input type="password" class="password" id="lpassword" required="" />' +
|
||||
'<label for="lremember">' + Common._e("Remember me") + '</label>' +
|
||||
|
@ -112,8 +225,9 @@ var Home = (function () {
|
|||
disable_form = Utils.disableInput(ANONYMOUS, 'off');
|
||||
code = '<p>' + Common.printf(Common._e("Enter the groupchat you want to join and the nick you want to have. You can also go back to the %s."), '<a href="#" class="to-home">' + Common._e("login page") + '</a>') + '</p>';
|
||||
|
||||
if(LEGAL)
|
||||
if(LEGAL) {
|
||||
code += '<p>' + Common.printf(Common._e("By using our service, you accept %s."), '<b><a href="' + Common.encodeQuotes(LEGAL) + '" target="_blank">' + Common._e("our terms of use") + '</a></b>') + '</p>';
|
||||
}
|
||||
|
||||
code += '<form action="#" method="post">' +
|
||||
'<fieldset>' +
|
||||
|
@ -139,27 +253,30 @@ var Home = (function () {
|
|||
case 'registerer':
|
||||
disable_form = Utils.disableInput(REGISTRATION, 'off');
|
||||
|
||||
if(!disable_form)
|
||||
if(!disable_form) {
|
||||
lock_host = Utils.disableInput(LOCK_HOST, 'on');
|
||||
}
|
||||
|
||||
code = '<p>' + Common._e("Register a new XMPP account to join your friends on your own social cloud. That's simple!") + '</p>';
|
||||
|
||||
if(LEGAL)
|
||||
if(LEGAL) {
|
||||
code += '<p>' + Common.printf(Common._e("By using our service, you accept %s."), '<b><a href="' + Common.encodeQuotes(LEGAL) + '" target="_blank">' + Common._e("our terms of use") + '</a></b>') + '</p>';
|
||||
}
|
||||
|
||||
code += '<form action="#" method="post">' +
|
||||
'<fieldset>' +
|
||||
'<legend>' + Common._e("Required") + '</legend>' +
|
||||
|
||||
'<label for="rnick">' + Common._e("Address") + '</label>' +
|
||||
'<input type="text" class="nick" id="rnick" ' + disable_form + ' pattern="[^@/]+" required="" placeholder="' + Common._e("Username") + '" /><span class="jid">@</span><input type="text" class="server" id="rserver" value="' + HOST_MAIN + '" ' + disable_form + lock_host + ' pattern="[^@/]+" required="" placeholder="' + Common._e("Server") + '" />' +
|
||||
'<input type="text" class="nick" id="rnick" ' + disable_form + ' pattern="[^@/]+" required="" placeholder="' + Common._e("Username") + '" /><span class="jid">@</span><input type="text" class="server" id="rserver" value="' + HOST_MAIN + '" ' + disable_form + lock_host + ' pattern="[^@/]+" required="" list="server" placeholder="' + Common._e("Server") + '" />' +
|
||||
'<label for="rpassword">' + Common._e("Password") + '</label>' +
|
||||
'<input type="password" class="password" id="rpassword" ' + disable_form + ' required="" placeholder="' + Common._e("Enter password") + '" /><input type="password" class="spassword" id="spassword" ' + disable_form + ' required="" placeholder="' + Common._e("Once again...") + '" />';
|
||||
|
||||
if(REGISTER_API == 'on')
|
||||
if(REGISTER_API == 'on') {
|
||||
code += '<div class="captcha_grp">' +
|
||||
'<label for="captcha">' + Common._e("Code") + '</label><input type="text" class="captcha" id="captcha" ' + disable_form + ' maxlength="6" pattern="[a-zA-Z0-9]{6}" required="" placeholder="' + Common._e("Security code") + '" /><img class="captcha_img" src="./server/captcha.php?id=' + genID() + '" alt="" />' +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
code += '</fieldset>' +
|
||||
|
||||
|
@ -170,78 +287,22 @@ var Home = (function () {
|
|||
}
|
||||
|
||||
// Form disabled?
|
||||
if(disable_form)
|
||||
if(disable_form) {
|
||||
code += '<div class="info fail">' +
|
||||
Common._e("This tool has been disabled!") +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
// Create this HTML code
|
||||
if(code && !Common.exists(current)) {
|
||||
// Append it!
|
||||
$(right + '.homediv.default').after('<div class="' + div + ' homediv">' + code + '</div>');
|
||||
$(right + '.homediv.default').after(
|
||||
'<div class="' + div + ' homediv">' + code + '</div>'
|
||||
);
|
||||
|
||||
// Create the attached events
|
||||
switch(div) {
|
||||
// Login tool
|
||||
case 'loginer':
|
||||
$(current + ' a.to-anonymous').click(function() {
|
||||
return self.change('anonymouser');
|
||||
});
|
||||
|
||||
$(current + ' a.advanced').click(self.showAdvanced);
|
||||
$(current + ' form').submit(self.loginForm);
|
||||
|
||||
break;
|
||||
|
||||
// Anonymous login tool
|
||||
case 'anonymouser':
|
||||
$(current + ' a.to-home').click(function() {
|
||||
return self.change('loginer');
|
||||
});
|
||||
|
||||
$(current + ' form').submit(Connection.doAnonymous);
|
||||
|
||||
// Keyup event on anonymous join's room input
|
||||
$(current + ' input.room').keyup(function() {
|
||||
var value = $(this).val();
|
||||
var report = current + ' .report';
|
||||
var span = report + ' span';
|
||||
|
||||
if(!value) {
|
||||
$(report).hide();
|
||||
$(span).text('');
|
||||
}
|
||||
|
||||
else {
|
||||
$(report).show();
|
||||
$(span).text(JAPPIX_LOCATION + '?r=' + value);
|
||||
}
|
||||
});
|
||||
|
||||
break;
|
||||
|
||||
// Register tool
|
||||
case 'registerer':
|
||||
// Server input change
|
||||
$('#home input.server').keyup(function(e) {
|
||||
if($.trim($(this).val()) == HOST_MAIN) {
|
||||
$('#home .captcha_grp').show();
|
||||
$('#home input.captcha').removeAttr('disabled');
|
||||
} else {
|
||||
$('#home .captcha_grp').hide();
|
||||
$('#home input.captcha').attr('disabled', true);
|
||||
}
|
||||
});
|
||||
|
||||
// Register input placeholder
|
||||
// FIXME: breaks IE compatibility
|
||||
//$('#home input[placeholder]').placeholder();
|
||||
|
||||
// Register form submit
|
||||
$(current + ' form').submit(self.registerForm);
|
||||
|
||||
break;
|
||||
}
|
||||
self._eventsChange(
|
||||
$(current),
|
||||
div
|
||||
);
|
||||
}
|
||||
|
||||
// We focus on the first input
|
||||
|
@ -288,13 +349,14 @@ var Home = (function () {
|
|||
|
||||
try {
|
||||
// We get the values
|
||||
var lPath = '#home .loginer ';
|
||||
var lServer = $(lPath + '.server').val();
|
||||
var lNick = Common.nodeprep($(lPath + '.nick').val());
|
||||
var lPass = $(lPath + '.password').val();
|
||||
var lResource = $(lPath + '.resource').val();
|
||||
var lPriority = $(lPath + '.priority').val();
|
||||
var lRemember = $(lPath + '.remember').filter(':checked').size();
|
||||
var path_sel = $('#home .loginer');
|
||||
|
||||
var lServer = path_sel.find('.server').val();
|
||||
var lNick = Common.nodeprep(path_sel.find('.nick').val());
|
||||
var lPass = path_sel.find('.password').val();
|
||||
var lResource = path_sel.find('.resource').val();
|
||||
var lPriority = path_sel.find('.priority').val();
|
||||
var lRemember = path_sel.find('.remember').filter(':checked').size();
|
||||
|
||||
// Enough values?
|
||||
if(lServer && lNick && lPass && lResource && lPriority) {
|
||||
|
@ -303,12 +365,13 @@ var Home = (function () {
|
|||
$(lPath + 'input[type="text"], ' + lPath + 'input[type="password"]').each(function() {
|
||||
var select = $(this);
|
||||
|
||||
if(!select.val())
|
||||
if(!select.val()) {
|
||||
$(document).oneTime(10, function() {
|
||||
select.addClass('please-complete').focus();
|
||||
});
|
||||
else
|
||||
} else {
|
||||
select.removeClass('please-complete');
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch(e) {
|
||||
|
@ -328,17 +391,18 @@ var Home = (function () {
|
|||
self.registerForm = function() {
|
||||
|
||||
try {
|
||||
var rPath = '#home .registerer ';
|
||||
var path = '#home .registerer';
|
||||
var path_sel = $(path);
|
||||
|
||||
// Remove the success info
|
||||
$(rPath + '.success').remove();
|
||||
path_sel.find('.success').remove();
|
||||
|
||||
// Get the values
|
||||
var username = Common.nodeprep($(rPath + '.nick').val());
|
||||
var domain = $(rPath + '.server').val();
|
||||
var pass = $(rPath + '.password').val();
|
||||
var spass = $(rPath + '.spassword').val();
|
||||
var captcha = $(rPath + '.captcha').val();
|
||||
var username = Common.nodeprep(path_sel.find('.nick').val());
|
||||
var domain = path_sel.find('.server').val();
|
||||
var pass = path_sel.find('.password').val();
|
||||
var spass = path_sel.find('.spassword').val();
|
||||
var captcha = path_sel.find('.captcha').val();
|
||||
|
||||
// Enough values?
|
||||
if(domain && username && pass && spass && (pass == spass) && !((REGISTER_API == 'on') && (domain == HOST_MAIN) && !captcha)) {
|
||||
|
@ -351,15 +415,16 @@ var Home = (function () {
|
|||
|
||||
// Something is missing?
|
||||
else {
|
||||
$(rPath + 'input[type="text"], ' + rPath + 'input[type="password"]').each(function() {
|
||||
$(path + ' input[type="text"], ' + path + ' input[type="password"]').each(function() {
|
||||
var select = $(this);
|
||||
|
||||
if(!select.val() || (select.is('#spassword') && pass && (pass != spass)))
|
||||
if(!select.val() || (select.is('#spassword') && pass && (pass != spass))) {
|
||||
$(document).oneTime(10, function() {
|
||||
select.addClass('please-complete').focus();
|
||||
});
|
||||
else
|
||||
} else {
|
||||
select.removeClass('please-complete');
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch(e) {
|
||||
|
@ -394,12 +459,14 @@ var Home = (function () {
|
|||
// Allows the user to switch the home page
|
||||
$(button).click(function() {
|
||||
// Login button
|
||||
if($(this).is('.login'))
|
||||
if($(this).is('.login')) {
|
||||
return self.change('loginer');
|
||||
}
|
||||
|
||||
// Register button
|
||||
else
|
||||
else {
|
||||
return self.change('registerer');
|
||||
}
|
||||
});
|
||||
|
||||
// Allows the user to view the corporation & about infobox
|
||||
|
@ -430,31 +497,14 @@ var Home = (function () {
|
|||
|
||||
// Disables the browser HTTP-requests stopper
|
||||
$(document).keydown(function(e) {
|
||||
if((e.keyCode == 27) && !System.isDeveloper())
|
||||
if((e.keyCode == 27) && !System.isDeveloper()) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// Warns for an obsolete browser
|
||||
if(Utils.isObsolete()) {
|
||||
// Add the code
|
||||
$(locale).after(
|
||||
'<div class="obsolete">' +
|
||||
'<p>' + Common._e("Your browser is out of date!") + '</p>' +
|
||||
|
||||
'<a class="firefox browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Mozilla Firefox') + '" href="http://www.mozilla.com/firefox/"></a>' +
|
||||
'<a class="chrome browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Google Chrome') + '" href="http://www.google.com/chrome"></a>' +
|
||||
'<a class="safari browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Safari') + '" href="http://www.apple.com/safari/"></a>' +
|
||||
'<a class="opera browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Opera') + '" href="http://www.opera.com/"></a>' +
|
||||
'<a class="ie browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Internet Explorer') + '" href="http://www.microsoft.com/hk/windows/internet-explorer/"></a>' +
|
||||
'</div>'
|
||||
);
|
||||
|
||||
// Display it later
|
||||
$(home + '.obsolete').oneTime('1s', function() {
|
||||
$(this).slideDown();
|
||||
});
|
||||
|
||||
Console.warn('Jappix does not support this browser!');
|
||||
self._obsolete();
|
||||
}
|
||||
|
||||
Console.log('Welcome to Jappix! Happy coding in developer mode!');
|
||||
|
@ -473,4 +523,4 @@ var Home = (function () {
|
|||
|
||||
})();
|
||||
|
||||
Home.launch();
|
||||
Home.launch();
|
||||
|
|
|
@ -34,8 +34,6 @@ var HTTPAuth = (function () {
|
|||
try {
|
||||
// We add the login wait div
|
||||
Interface.showGeneralWait();
|
||||
|
||||
oArgs = {};
|
||||
|
||||
if(Common.hasWebSocket()) {
|
||||
// WebSocket supported & configured
|
||||
|
@ -67,15 +65,6 @@ var HTTPAuth = (function () {
|
|||
// Generate a priority
|
||||
lPriority = lPriority ? lPriority : 10;
|
||||
|
||||
// We retrieve what the user typed in the login inputs
|
||||
oArgs = {};
|
||||
oArgs.domain = $.trim(lServer);
|
||||
oArgs.username = $.trim(lNick);
|
||||
oArgs.resource = random_resource;
|
||||
oArgs.pass = lPass;
|
||||
oArgs.secure = true;
|
||||
oArgs.xmllang = XML_LANG;
|
||||
|
||||
// Store the resource (for reconnection)
|
||||
DataStore.setDB(Connection.desktop_hash, 'session', 'resource', random_resource);
|
||||
|
||||
|
@ -89,7 +78,14 @@ var HTTPAuth = (function () {
|
|||
DataStore.setDB(Connection.desktop_hash, 'priority', 1, 10);
|
||||
|
||||
// We connect !
|
||||
con.connect(oArgs);
|
||||
con.connect({
|
||||
'domain': $.trim(lServer),
|
||||
'username': $.trim(lNick),
|
||||
'resource': random_resource,
|
||||
'pass': lPass,
|
||||
'secure': true,
|
||||
'xmllang': XML_LANG
|
||||
});
|
||||
|
||||
// Change the page title
|
||||
Interface.title('wait');
|
||||
|
|
|
@ -45,11 +45,19 @@ var HTTPReply = (function () {
|
|||
// If "no"
|
||||
if(value == 'no') {
|
||||
aMsg.setType('error');
|
||||
aMsg.appendNode('error', {'code': '401', 'type': 'auth'});
|
||||
aMsg.appendNode('error', {
|
||||
'code': '401',
|
||||
'type': 'auth'
|
||||
});
|
||||
}
|
||||
|
||||
// We set the confirm node
|
||||
aMsg.appendNode('confirm', {'xmlns': xmlns, 'url': url, 'id': id, 'method': method});
|
||||
aMsg.appendNode('confirm', {
|
||||
'xmlns': xmlns,
|
||||
'url': url,
|
||||
'id': id,
|
||||
'method': method
|
||||
});
|
||||
|
||||
// We send the message
|
||||
con.send(aMsg, Errors.handleReply);
|
||||
|
|
|
@ -176,17 +176,16 @@ var Inbox = (function () {
|
|||
var value = $(Common.XMLFromString(DataStore.storageDB.getItem(current)));
|
||||
|
||||
// Create the storage node
|
||||
storage.appendChild(iq.buildNode('message', {
|
||||
'id': value.find('id').text().revertHtmlEnc(),
|
||||
'from': value.find('from').text().revertHtmlEnc(),
|
||||
'subject': value.find('subject').text().revertHtmlEnc(),
|
||||
'status': value.find('status').text().revertHtmlEnc(),
|
||||
'date': value.find('date').text().revertHtmlEnc(),
|
||||
'xmlns': NS_INBOX
|
||||
},
|
||||
|
||||
value.find('content').text().revertHtmlEnc()
|
||||
));
|
||||
storage.appendChild(
|
||||
iq.buildNode('message', {
|
||||
'id': value.find('id').text().revertHtmlEnc(),
|
||||
'from': value.find('from').text().revertHtmlEnc(),
|
||||
'subject': value.find('subject').text().revertHtmlEnc(),
|
||||
'status': value.find('status').text().revertHtmlEnc(),
|
||||
'date': value.find('date').text().revertHtmlEnc(),
|
||||
'xmlns': NS_INBOX
|
||||
}, value.find('content').text().revertHtmlEnc()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -207,18 +206,18 @@ var Inbox = (function () {
|
|||
|
||||
try {
|
||||
// Init
|
||||
var mPath = '#inbox .';
|
||||
var inbox_sel = $('#inbox');
|
||||
|
||||
// Reset the previous buddy search
|
||||
Search.resetBuddy('#inbox .inbox-new-to');
|
||||
|
||||
// We switch the divs
|
||||
$(mPath + 'inbox-results, #inbox .a-new-message, #inbox .a-delete-messages').hide();
|
||||
$(mPath + 'inbox-new, #inbox .a-show-messages').show();
|
||||
inbox_sel.find('.inbox-results, .a-new-message, .a-delete-messages').hide();
|
||||
inbox_sel.find('.inbox-new, .a-show-messages').show();
|
||||
|
||||
// We focus on the first input
|
||||
$(document).oneTime(10, function() {
|
||||
$(mPath + 'inbox-new-to-input').focus();
|
||||
inbox_sel.find('.inbox-new-to-input').focus();
|
||||
});
|
||||
|
||||
// We reset some stuffs
|
||||
|
@ -241,16 +240,16 @@ var Inbox = (function () {
|
|||
|
||||
try {
|
||||
// Init
|
||||
var mPath = '#inbox .';
|
||||
var inbox_sel = $('#inbox');
|
||||
|
||||
// We reset the forms
|
||||
$(mPath + 'inbox-new-block:not(form) input, ' + mPath + 'inbox-new textarea').val('').removeClass('please-complete');
|
||||
$(mPath + 'inbox-new-file a').remove();
|
||||
$(mPath + 'inbox-new-file input').show();
|
||||
inbox_sel.find('.inbox-new-block:not(form) input, .inbox-new textarea').val('').removeClass('please-complete');
|
||||
inbox_sel.find('.inbox-new-file a').remove();
|
||||
inbox_sel.find('.inbox-new-file input').show();
|
||||
|
||||
// We close an eventual opened message
|
||||
$(mPath + 'message-content').remove();
|
||||
$(mPath + 'one-message').removeClass('message-reading');
|
||||
inbox_sel.find('.message-content').remove();
|
||||
inbox_sel.find('.one-message').removeClass('message-reading');
|
||||
} catch(e) {
|
||||
Console.error('Inbox.cleanNewMessage', e);
|
||||
}
|
||||
|
@ -270,26 +269,26 @@ var Inbox = (function () {
|
|||
|
||||
try {
|
||||
// We send the message
|
||||
var mess = new JSJaCMessage();
|
||||
var message = new JSJaCMessage();
|
||||
|
||||
// Main attributes
|
||||
mess.setTo(to);
|
||||
mess.setSubject(subject);
|
||||
mess.setType('normal');
|
||||
message.setTo(to);
|
||||
message.setSubject(subject);
|
||||
message.setType('normal');
|
||||
|
||||
// Any file to attach?
|
||||
var attached = '#inbox .inbox-new-file a.file';
|
||||
|
||||
if(Common.exists(attached)) {
|
||||
body += '\n' +
|
||||
'\n' +
|
||||
$(attached).attr('data-attachedtitle') + ' - ' + $(attached).attr('data-attachedhref');
|
||||
'\n' +
|
||||
$(attached).attr('data-attachedtitle') + ' - ' + $(attached).attr('data-attachedhref');
|
||||
}
|
||||
|
||||
// Set body
|
||||
mess.setBody(body);
|
||||
message.setBody(body);
|
||||
|
||||
con.send(mess, Errors.handleReply);
|
||||
con.send(message, Errors.handleReply);
|
||||
} catch(e) {
|
||||
Console.error('Inbox.sendMessage', e);
|
||||
}
|
||||
|
@ -306,10 +305,10 @@ var Inbox = (function () {
|
|||
|
||||
try {
|
||||
// We get some informations
|
||||
var mPath = '#inbox ';
|
||||
var to = $(mPath + '.inbox-new-to-input').val();
|
||||
var body = $(mPath + '.inbox-new-textarea').val();
|
||||
var subject = $(mPath + '.inbox-new-subject-input').val();
|
||||
var inbox_sel = $('#inbox');
|
||||
var to = inbox_sel.find('.inbox-new-to-input').val();
|
||||
var body = inbox_sel.find('.inbox-new-textarea').val();
|
||||
var subject = inbox_sel.find('.inbox-new-subject-input').val();
|
||||
|
||||
if(to && body && subject) {
|
||||
// New array of XID
|
||||
|
@ -345,15 +344,15 @@ var Inbox = (function () {
|
|||
}
|
||||
|
||||
else {
|
||||
$(mPath + 'input[type="text"], ' + mPath + 'textarea').each(function() {
|
||||
var current = this;
|
||||
inbox_sel.find('input[type="text"], textarea').each(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
if(!$(current).val()) {
|
||||
if(!this_sel.val()) {
|
||||
$(document).oneTime(10, function() {
|
||||
$(current).addClass('please-complete').focus();
|
||||
this_sel.addClass('please-complete').focus();
|
||||
});
|
||||
} else {
|
||||
$(current).removeClass('please-complete');
|
||||
this_sel.removeClass('please-complete');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -374,17 +373,16 @@ var Inbox = (function () {
|
|||
self.showMessage = function() {
|
||||
|
||||
try {
|
||||
// Init
|
||||
var mPath = '#inbox .';
|
||||
var inbox_sel = $('#inbox');
|
||||
|
||||
// We switch the divs
|
||||
$(mPath + 'inbox-new').hide();
|
||||
$(mPath + 'inbox-results').show();
|
||||
inbox_sel.find('.inbox-new').hide();
|
||||
inbox_sel.find('.inbox-results').show();
|
||||
|
||||
// We show a new link in the menu
|
||||
$(mPath + 'a-show-messages').hide();
|
||||
$(mPath + 'a-delete-messages').show();
|
||||
$(mPath + 'a-new-message').show();
|
||||
inbox_sel.find('.a-show-messages').hide();
|
||||
inbox_sel.find('.a-delete-messages').show();
|
||||
inbox_sel.find('.a-new-message').show();
|
||||
|
||||
// We reset some stuffs
|
||||
self.cleanNewMessage();
|
||||
|
@ -484,10 +482,14 @@ var Inbox = (function () {
|
|||
|
||||
try {
|
||||
// Initialize the XML data
|
||||
var xml = '<message><id>' + id.htmlEnc().htmlEnc() + '</id><date>' + date.htmlEnc().htmlEnc() + '</date><from>' + from.htmlEnc().htmlEnc() + '</from><subject>' + subject.htmlEnc().htmlEnc() + '</subject><status>' + status.htmlEnc().htmlEnc() + '</status><content>' + content.htmlEnc().htmlEnc() + '</content>';
|
||||
|
||||
// End the XML data
|
||||
xml += '</message>';
|
||||
var xml = '<message>' +
|
||||
'<id>' + id.htmlEnc().htmlEnc() + '</id>' +
|
||||
'<date>' + date.htmlEnc().htmlEnc() + '</date>' +
|
||||
'<from>' + from.htmlEnc().htmlEnc() + '</from>' +
|
||||
'<subject>' + subject.htmlEnc().htmlEnc() + '</subject>' +
|
||||
'<status>' + status.htmlEnc().htmlEnc() + '</status>' +
|
||||
'<content>' + content.htmlEnc().htmlEnc() + '</content>' +
|
||||
'</message>';
|
||||
|
||||
// Store this message!
|
||||
DataStore.setDB(Connection.desktop_hash, 'inbox', id, xml);
|
||||
|
@ -504,7 +506,7 @@ var Inbox = (function () {
|
|||
* @param {string} id
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.deleteMessage = function() {
|
||||
self.deleteMessage = function(id) {
|
||||
|
||||
try {
|
||||
// Remove the message from the inbox
|
||||
|
@ -794,13 +796,13 @@ var Inbox = (function () {
|
|||
|
||||
// Display the current message
|
||||
self.displayMessage(
|
||||
value.find('from').text().revertHtmlEnc(),
|
||||
value.find('subject').text().revertHtmlEnc(),
|
||||
value.find('content').text().revertHtmlEnc(),
|
||||
value.find('status').text().revertHtmlEnc(),
|
||||
value.find('id').text().revertHtmlEnc(),
|
||||
value.find('date').text().revertHtmlEnc()
|
||||
);
|
||||
value.find('from').text().revertHtmlEnc(),
|
||||
value.find('subject').text().revertHtmlEnc(),
|
||||
value.find('content').text().revertHtmlEnc(),
|
||||
value.find('status').text().revertHtmlEnc(),
|
||||
value.find('id').text().revertHtmlEnc(),
|
||||
value.find('date').text().revertHtmlEnc()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -854,16 +856,30 @@ var Inbox = (function () {
|
|||
|
||||
// Hide the attach link, show the unattach one
|
||||
$('#inbox .inbox-new-file input').hide();
|
||||
$('#inbox .inbox-new-file').append('<a class="file ' + Common.encodeQuotes(Utils.fileCategory(Common.explodeThis('/', fType, 1))) + ' talk-images" href="' + Common.encodeQuotes(fURL) + '" target="_blank">' + fName.htmlEnc() + '</a><a href="#" class="remove one-button talk-images">' + Common._e("Remove") + '</a>');
|
||||
$('#inbox .inbox-new-file').append(
|
||||
'<a class="file ' + Common.encodeQuotes(Utils.fileCategory(Common.explodeThis('/', fType, 1))) + ' talk-images" ' +
|
||||
'href="' + Common.encodeQuotes(fURL) + '" ' +
|
||||
'target="_blank">' +
|
||||
fName.htmlEnc() +
|
||||
'</a>' +
|
||||
|
||||
'<a href="#" class="remove one-button talk-images">' +
|
||||
Common._e("Remove") +
|
||||
'</a>'
|
||||
);
|
||||
|
||||
// Set values to the file link
|
||||
$('#inbox .inbox-new-file a.file').attr('data-attachedtitle', fName)
|
||||
.attr('data-attachedhref', fURL);
|
||||
var inbox_file_sel = $('#inbox .inbox-new-file a.file');
|
||||
|
||||
inbox_file_sel.attr('data-attachedtitle', fName);
|
||||
inbox_file_sel.attr('data-attachedhref', fURL);
|
||||
|
||||
// Click events
|
||||
$('#inbox .inbox-new-file a.remove').click(function() {
|
||||
$('#inbox .inbox-new-file a').remove();
|
||||
$('#inbox .inbox-new-file input').show();
|
||||
var inbox_new_file_sel = $('#inbox .inbox-new-file');
|
||||
|
||||
inbox_new_file_sel.find('a.remove').click(function() {
|
||||
inbox_new_file_sel.find('a').remove();
|
||||
inbox_new_file_sel.find('input').show();
|
||||
|
||||
return false;
|
||||
});
|
||||
|
@ -899,10 +915,11 @@ var Inbox = (function () {
|
|||
// Send the message when enter pressend
|
||||
$(inbox + 'inbox-new input').keyup(function(e) {
|
||||
if(e.keyCode == 13) {
|
||||
if(Common.exists(dHovered))
|
||||
if(Common.exists(dHovered)) {
|
||||
Search.addBuddy(destination, $(dHovered).attr('data-xid'));
|
||||
else
|
||||
} else {
|
||||
self.checkMessage();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -948,7 +965,7 @@ var Inbox = (function () {
|
|||
|
||||
// File upload
|
||||
var attach_options = {
|
||||
dataType: 'xml',
|
||||
dataType: 'xml',
|
||||
beforeSubmit: self.waitAttach,
|
||||
success: self.handleAttach
|
||||
};
|
||||
|
|
|
@ -161,8 +161,9 @@ var IntegrateBox = (function () {
|
|||
self.close();
|
||||
|
||||
// Media integration not wanted?
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'integratemedias') == '0')
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'integratemedias') == '0') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Apply the HTML code
|
||||
var dom_code = self.code(service, url);
|
||||
|
|
|
@ -74,8 +74,9 @@ var Interface = (function () {
|
|||
|
||||
try {
|
||||
// Item exists?
|
||||
if(Common.exists('#general-wait'))
|
||||
if(Common.exists('#general-wait')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Generate the HTML code
|
||||
var html =
|
||||
|
@ -178,8 +179,9 @@ var Interface = (function () {
|
|||
var more_content = '#page-switch .more-content';
|
||||
|
||||
// Yet displayed?
|
||||
if(Common.exists(more_content))
|
||||
if(Common.exists(more_content)) {
|
||||
return Bubble.close();
|
||||
}
|
||||
|
||||
// Add the bubble
|
||||
Bubble.show(more_content);
|
||||
|
@ -397,32 +399,48 @@ var Interface = (function () {
|
|||
var date = DateUtils.getXMPPTime('local');
|
||||
var type = $('#' + hash).attr('data-type');
|
||||
var direction = $('html').attr('dir') || 'ltr';
|
||||
|
||||
var content_sel = $(content);
|
||||
|
||||
// Filter the content smileys
|
||||
$(content).find('img.emoticon').each(function() {
|
||||
content_sel.find('img.emoticon').each(function() {
|
||||
$(this).replaceWith($(this).attr('alt'));
|
||||
});
|
||||
|
||||
// Remove the useless attributes
|
||||
$(content).removeAttr('data-type').removeAttr('data-stamp');
|
||||
content_sel.removeAttr('data-type').removeAttr('data-stamp');
|
||||
|
||||
// Remove the content avatars
|
||||
$(content).find('.avatar-container').remove();
|
||||
content_sel.find('.avatar-container').remove();
|
||||
|
||||
// Remove the content info
|
||||
content_sel.find('.correction-edit, .message-marker, .corrected-info, .correction-label').remove();
|
||||
|
||||
// Remove the content click events
|
||||
$(content).find('a').removeAttr('onclick');
|
||||
content_sel.find('a').removeAttr('onclick');
|
||||
|
||||
// Extract the content HTML code
|
||||
content = $(content).parent().html();
|
||||
content = content_sel.parent().html();
|
||||
|
||||
// No avatar?
|
||||
if(!avatar || !avatar.match(/data:/))
|
||||
if(!avatar || !avatar.match(/data:/)) {
|
||||
avatar = 'none';
|
||||
}
|
||||
|
||||
// POST the values to the server
|
||||
$.post('./server/generate-chat.php', { 'content': content, 'xid': xid, 'nick': nick, 'avatar': avatar, 'date': date, 'type': type, 'direction': direction }, function(data) {
|
||||
$.post('./server/generate-chat.php', {
|
||||
'content': content,
|
||||
'xid': xid,
|
||||
'nick': nick,
|
||||
'avatar': avatar,
|
||||
'date': date,
|
||||
'type': type,
|
||||
'direction': direction
|
||||
}, function(data) {
|
||||
// Handled!
|
||||
$(path + 'tooltip-waitlog').replaceWith('<a class="tooltip-actionlog" href="./server/download-chat.php?id=' + data + '" target="_blank">' + Common._e("Download file!") + '</a>');
|
||||
$(path + 'tooltip-waitlog').replaceWith(
|
||||
'<a class="tooltip-actionlog" href="./server/download-chat.php?id=' + data + '" target="_blank">' + Common._e("Download file!") + '</a>'
|
||||
);
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Interface.generateChatLog', e);
|
||||
|
@ -433,6 +451,31 @@ var Interface = (function () {
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether chan has focus or not
|
||||
* @public
|
||||
* @param {string} hash
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.hasChanFocus = function(hash) {
|
||||
|
||||
var has_focus = true;
|
||||
|
||||
try {
|
||||
if(!$('#page-switch .' + hash).hasClass('activechan') ||
|
||||
!Common.isFocused() ||
|
||||
(self.chat_focus_hash != hash)) {
|
||||
has_focus = false;
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Interface.hasChanFocus', e);
|
||||
} finally {
|
||||
return has_focus;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Notifies the user from a new incoming message
|
||||
* @public
|
||||
|
@ -449,7 +492,7 @@ var Interface = (function () {
|
|||
var active = $(tested).hasClass('activechan');
|
||||
|
||||
// We notify the user if he has not the focus on the chat
|
||||
if(!active || !Common.isFocused() || (self.chat_focus_hash != hash)) {
|
||||
if(self.hasChanFocus(hash) === false) {
|
||||
if(!active) {
|
||||
if(type == 'personal') {
|
||||
$(tested + ', ' + chat_switch + 'more-button').addClass('chan-newmessage');
|
||||
|
@ -509,10 +552,11 @@ var Interface = (function () {
|
|||
|
||||
try {
|
||||
// Any pending events?
|
||||
if(Common.exists('.one-counter[data-counter]'))
|
||||
if(Common.exists('.one-counter[data-counter]')) {
|
||||
self.title('new');
|
||||
else
|
||||
} else {
|
||||
self.title('talk');
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Interface.updateTitle', e);
|
||||
}
|
||||
|
@ -534,8 +578,9 @@ var Interface = (function () {
|
|||
$(chat_switch + hash).removeClass('chan-newmessage chan-unread');
|
||||
|
||||
// We reset the global notifications if no more unread messages
|
||||
if(!$(chat_switch + 'chans .chan-newmessage').size())
|
||||
if(!$(chat_switch + 'chans .chan-newmessage').size()) {
|
||||
$(chat_switch + 'more-button').removeClass('chan-newmessage');
|
||||
}
|
||||
|
||||
// We reset the chat counter
|
||||
$('#' + hash).removeAttr('data-counter');
|
||||
|
@ -598,8 +643,9 @@ var Interface = (function () {
|
|||
// We show all the groups
|
||||
$('#roster .one-group').show();
|
||||
|
||||
if(Search.search_filtered)
|
||||
if(Search.search_filtered) {
|
||||
Search.funnelFilterBuddy();
|
||||
}
|
||||
|
||||
// Store this in the options
|
||||
if((from == 'roster') && Options.loaded()) {
|
||||
|
@ -687,6 +733,39 @@ var Interface = (function () {
|
|||
$(document).ready(function() {
|
||||
// Focus on the first visible input
|
||||
$(window).focus(self.inputFocus);
|
||||
|
||||
// Re-focus to visible chat/groupchat input if typing when input blurred
|
||||
$(document).keypress(function(evt) {
|
||||
try {
|
||||
// Don't trigger if not connected or popup opened
|
||||
if(Common.isConnected() && !Common.exists('div.lock')) {
|
||||
// Cannot work if an input/textarea is already focused or chat is not opened
|
||||
var target_input_sel = $('.page-engine-chan .message-area:visible');
|
||||
|
||||
if(!target_input_sel.size() || $('input, textarea').is(':focus')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get key value
|
||||
var key_value = $.trim(String.fromCharCode(evt.which));
|
||||
|
||||
// Re-focus on opened chat?
|
||||
if(key_value) {
|
||||
// Get input values
|
||||
value_input = target_input_sel.val();
|
||||
|
||||
// Append pressed key value
|
||||
target_input_sel.val(value_input + key_value);
|
||||
target_input_sel.focus();
|
||||
|
||||
// Put cursor at the end of input
|
||||
target_input_sel[0].selectionStart = target_input_sel[0].selectionEnd = value_input.length + 1;
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Interface.launch[autofocus]', e);
|
||||
}
|
||||
});
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Interface.launch', e);
|
||||
|
|
|
@ -20,6 +20,352 @@ var IQ = (function () {
|
|||
var self = {};
|
||||
|
||||
|
||||
/**
|
||||
* Handles OOB request
|
||||
* @private
|
||||
* @param {string} iqType
|
||||
* @param {string} iqID
|
||||
* @param {object} iqNode
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._handleOOBRequest = function(iqFrom, iqID, iqNode) {
|
||||
|
||||
try {
|
||||
/* REF: http://xmpp.org/extensions/xep-0066.html */
|
||||
|
||||
OOB.handle(iqFrom, iqID, 'iq', iqNode);
|
||||
|
||||
Console.log('Received IQ OOB request: ' + iqFrom);
|
||||
} catch(e) {
|
||||
Console.error('IQ._handleOOBRequest', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles OOB reply
|
||||
* @private
|
||||
* @param {object} iqResponse
|
||||
* @param {string} iqFrom
|
||||
* @param {string} iqType
|
||||
* @param {string} iqID
|
||||
* @param {object} iqNode
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._handleOOBReply = function(iqResponse, iqFrom, iqType, iqID, iqNode) {
|
||||
|
||||
try {
|
||||
// Get the values
|
||||
var oob_url = DataStore.getDB(Connection.desktop_hash, 'send/url', iqID);
|
||||
var oob_desc = DataStore.getDB(Connection.desktop_hash, 'send/desc', iqID);
|
||||
var notif_id = hex_md5(oob_url + oob_desc + iqType + iqFrom + iqID);
|
||||
|
||||
if($(iqNode).find('error').size()) {
|
||||
// Error?
|
||||
if($(iqNode).find('error not-acceptable').size()) {
|
||||
// Rejected?
|
||||
Notification.create('send_reject', iqFrom, [iqFrom, oob_url, 'iq', iqID, iqNode], oob_desc, notif_id);
|
||||
} else {
|
||||
// Failed?
|
||||
Notification.create('send_fail', iqFrom, [iqFrom, oob_url, 'iq', iqID, iqNode], oob_desc, notif_id);
|
||||
}
|
||||
|
||||
// Remove the file
|
||||
$.get(oob_url + '&action=remove');
|
||||
} else if(iqType == 'result') {
|
||||
// Success?
|
||||
Notification.create('send_accept', iqFrom, [iqFrom, oob_url, 'iq', iqID, iqNode], oob_desc, notif_id);
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('IQ._handleOOBReply', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles Software Version
|
||||
* @private
|
||||
* @param {object} iqResponse
|
||||
* @param {string} iqFrom
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._handleSoftwareVersion = function(iqResponse, iqFrom) {
|
||||
|
||||
try {
|
||||
/* REF: http://xmpp.org/extensions/xep-0092.html */
|
||||
|
||||
iqQuery = iqResponse.setQuery(NS_VERSION);
|
||||
|
||||
iqQuery.appendChild(iqResponse.buildNode('name', {'xmlns': NS_VERSION}, Caps.disco_infos.identity.name));
|
||||
iqQuery.appendChild(iqResponse.buildNode('version', {'xmlns': NS_VERSION}, JAPPIX_VERSION));
|
||||
iqQuery.appendChild(iqResponse.buildNode('os', {'xmlns': NS_VERSION}, BrowserDetect.OS));
|
||||
|
||||
con.send(iqResponse);
|
||||
|
||||
Console.log('Received software version query: ' + iqFrom);
|
||||
} catch(e) {
|
||||
Console.error('IQ._handleSoftwareVersion', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles Last Activity
|
||||
* @private
|
||||
* @param {object} iqResponse
|
||||
* @param {string} iqFrom
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._handleLastActivity = function(iqResponse, iqFrom) {
|
||||
|
||||
try {
|
||||
/* REF: http://xmpp.org/extensions/xep-0012.html */
|
||||
|
||||
iqQuery = iqResponse.setQuery(NS_LAST);
|
||||
iqQuery.setAttribute('seconds', DateUtils.getLastActivity());
|
||||
|
||||
con.send(iqResponse);
|
||||
|
||||
Console.log('Received last activity query: ' + iqFrom);
|
||||
} catch(e) {
|
||||
Console.error('IQ._handleLastActivity', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles Privacy Lists
|
||||
* @private
|
||||
* @param {object} iqResponse
|
||||
* @param {string} iqFrom
|
||||
* @param {string} iqQuery
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._handlePrivacyLists = function(iqResponse, iqFrom, iqQuery) {
|
||||
|
||||
try {
|
||||
// REF : http://xmpp.org/extensions/xep-0016.html
|
||||
|
||||
// Roster push
|
||||
con.send(iqResponse);
|
||||
|
||||
// Get the lists
|
||||
$(iqQuery).find('list').each(function() {
|
||||
Privacy.get($(this).attr('name'));
|
||||
});
|
||||
|
||||
Console.log('Received privacy lists push: ' + iqFrom);
|
||||
} catch(e) {
|
||||
Console.error('IQ._handlePrivacyLists', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles Roster Push
|
||||
* @private
|
||||
* @param {object} iqResponse
|
||||
* @param {string} iqFrom
|
||||
* @param {string} iqQuery
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._handleRosterPush = function(iqResponse, iqFrom, iqQuery) {
|
||||
|
||||
try {
|
||||
// REF : http://xmpp.org/extensions/xep-0092.html
|
||||
|
||||
// Roster push
|
||||
con.send(iqResponse);
|
||||
|
||||
// Get the values
|
||||
$(iqQuery).find('item').each(function() {
|
||||
Roster.parse($(this), 'presence');
|
||||
});
|
||||
|
||||
Console.log('Received roster push: ' + iqFrom);
|
||||
} catch(e) {
|
||||
Console.error('IQ._handleRosterPush', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles Roster Item Exchange
|
||||
* @private
|
||||
* @param {object} iqNode
|
||||
* @param {string} iqFrom
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._handleRosterItemExchange = function(iqNode, iqFrom) {
|
||||
|
||||
try {
|
||||
// Open a new notification
|
||||
Notification.create('rosterx', iqFrom, [iqNode], '');
|
||||
|
||||
Console.log('Roster Item Exchange from: ' + iqFrom);
|
||||
} catch(e) {
|
||||
Console.error('IQ._handleRosterItemExchange', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles Disco Info
|
||||
* @private
|
||||
* @param {object} iqResponse
|
||||
* @param {string} iqFrom
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._handleDiscoInfo = function(iqResponse, iqFrom) {
|
||||
|
||||
try {
|
||||
/* REF: http://xmpp.org/extensions/xep-0030.html */
|
||||
|
||||
iqQuery = iqResponse.setQuery(NS_DISCO_INFO);
|
||||
|
||||
// We set the name of the client
|
||||
iqQuery.appendChild(iqResponse.buildNode('identity', {
|
||||
'category': Caps.disco_infos.identity.category,
|
||||
'type': Caps.disco_infos.identity.type,
|
||||
'name': Caps.disco_infos.identity.name,
|
||||
'xmlns': NS_DISCO_INFO
|
||||
}));
|
||||
|
||||
// We set all the supported features
|
||||
var disco_infos = Caps.myDiscoInfos();
|
||||
|
||||
$.each(disco_infos, function(i, disco_info) {
|
||||
iqQuery.appendChild(iqResponse.buildNode('feature', {'var': disco_info, 'xmlns': NS_DISCO_INFO}));
|
||||
});
|
||||
|
||||
con.send(iqResponse);
|
||||
|
||||
Console.log('Received disco#infos query: ' + iqFrom);
|
||||
} catch(e) {
|
||||
Console.error('IQ._handleDiscoInfo', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles User Time
|
||||
* @private
|
||||
* @param {object} iqResponse
|
||||
* @param {string} iqFrom
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._handleUserTime = function(iqResponse, iqFrom) {
|
||||
|
||||
try {
|
||||
/* REF: http://xmpp.org/extensions/xep-0202.html */
|
||||
|
||||
var iqTime = iqResponse.appendNode('time', {
|
||||
'xmlns': NS_URN_TIME
|
||||
});
|
||||
|
||||
iqTime.appendChild(iqResponse.buildNode('tzo', {
|
||||
'xmlns': NS_URN_TIME
|
||||
}, DateUtils.getTZO()));
|
||||
|
||||
iqTime.appendChild(iqResponse.buildNode('utc', {
|
||||
'xmlns': NS_URN_TIME
|
||||
}, DateUtils.getXMPPTime('utc')));
|
||||
|
||||
con.send(iqResponse);
|
||||
|
||||
Console.log('Received local time query: ' + iqFrom);
|
||||
} catch(e) {
|
||||
Console.error('IQ._handleUserTime', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles Ping
|
||||
* @private
|
||||
* @param {object} iqResponse
|
||||
* @param {string} iqFrom
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._handlePing = function(iqResponse, iqFrom) {
|
||||
|
||||
try {
|
||||
/* REF: http://xmpp.org/extensions/xep-0199.html */
|
||||
|
||||
con.send(iqResponse);
|
||||
|
||||
Console.log('Received a ping: ' + iqFrom);
|
||||
} catch(e) {
|
||||
Console.error('IQ._handlePing', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles Jingle
|
||||
* @private
|
||||
* @param {string} iqFrom
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._handleJingle = function(iqFrom) {
|
||||
|
||||
try {
|
||||
/* REF: http://xmpp.org/extensions/xep-0166.html */
|
||||
|
||||
// Handled via JSJaCJingle.route() (see above)
|
||||
|
||||
Console.log('Received a Jingle packet: ' + iqFrom);
|
||||
} catch(e) {
|
||||
Console.error('IQ._handleJingle', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Raises a not implemented error
|
||||
* @private
|
||||
* @param {object} iqResponse
|
||||
* @param {object} iqNode
|
||||
* @param {string} iqFrom
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._raiseNotImplemented = function(iqResponse, iqNode, iqFrom) {
|
||||
|
||||
try {
|
||||
// Change IQ type
|
||||
iqResponse.setType('error');
|
||||
|
||||
// Append stanza content
|
||||
for(var c = 0; c < iqNode.childNodes.length; c++) {
|
||||
iqResponse.getNode().appendChild(iqNode.childNodes.item(c).cloneNode(true));
|
||||
}
|
||||
|
||||
// Append error content
|
||||
var iqError = iqResponse.appendNode('error', {'xmlns': NS_CLIENT, 'code': '501', 'type': 'cancel'});
|
||||
iqError.appendChild(iqResponse.buildNode('feature-not-implemented', {'xmlns': NS_STANZAS}));
|
||||
iqError.appendChild(iqResponse.buildNode('text', {'xmlns': NS_STANZAS}, Common._e("The feature requested is not implemented by the recipient or server and therefore cannot be processed.")));
|
||||
|
||||
con.send(iqResponse);
|
||||
|
||||
Console.log('Received an unsupported IQ query from: ' + iqFrom);
|
||||
} catch(e) {
|
||||
Console.error('IQ._raiseNotImplemented', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles an incoming IQ packet
|
||||
* @public
|
||||
|
@ -37,9 +383,6 @@ var IQ = (function () {
|
|||
var iqQuery = iq.getQuery();
|
||||
var iqType = iq.getType();
|
||||
|
||||
// Handle Jingle packet?
|
||||
JSJaCJingle_route(iq);
|
||||
|
||||
// Build the response
|
||||
var iqResponse = new JSJaCIQ();
|
||||
|
||||
|
@ -49,178 +392,62 @@ var IQ = (function () {
|
|||
|
||||
// OOB request
|
||||
if((iqQueryXMLNS == NS_IQOOB) && (iqType == 'set')) {
|
||||
/* REF: http://xmpp.org/extensions/xep-0066.html */
|
||||
|
||||
OOB.handle(iqFrom, iqID, 'iq', iqNode);
|
||||
|
||||
Console.log('Received IQ OOB request: ' + iqFrom);
|
||||
self._handleOOBRequest(iqFrom, iqID, iqNode);
|
||||
}
|
||||
|
||||
// OOB reply
|
||||
else if(DataStore.getDB(Connection.desktop_hash, 'send/url', iqID)) {
|
||||
// Get the values
|
||||
var oob_url = DataStore.getDB(Connection.desktop_hash, 'send/url', iqID);
|
||||
var oob_desc = DataStore.getDB(Connection.desktop_hash, 'send/desc', iqID);
|
||||
var notif_id = hex_md5(oob_url + oob_desc + iqType + iqFrom + iqID);
|
||||
|
||||
if($(iqNode).find('error').size()) {
|
||||
// Error?
|
||||
if($(iqNode).find('error not-acceptable').size()) {
|
||||
// Rejected?
|
||||
Notification.create('send_reject', iqFrom, [iqFrom, oob_url, 'iq', iqID, iqNode], oob_desc, notif_id);
|
||||
} else {
|
||||
// Failed?
|
||||
Notification.create('send_fail', iqFrom, [iqFrom, oob_url, 'iq', iqID, iqNode], oob_desc, notif_id);
|
||||
}
|
||||
|
||||
// Remove the file
|
||||
$.get(oob_url + '&action=remove');
|
||||
} else if(iqType == 'result') {
|
||||
// Success?
|
||||
Notification.create('send_accept', iqFrom, [iqFrom, oob_url, 'iq', iqID, iqNode], oob_desc, notif_id);
|
||||
}
|
||||
self._handleOOBReply(iqResponse, iqFrom, iqType, iqID, iqNode);
|
||||
}
|
||||
|
||||
// Software version query
|
||||
else if((iqQueryXMLNS == NS_VERSION) && (iqType == 'get')) {
|
||||
/* REF: http://xmpp.org/extensions/xep-0092.html */
|
||||
|
||||
iqQuery = iqResponse.setQuery(NS_VERSION);
|
||||
|
||||
iqQuery.appendChild(iqResponse.buildNode('name', {'xmlns': NS_VERSION}, 'Jappix'));
|
||||
iqQuery.appendChild(iqResponse.buildNode('version', {'xmlns': NS_VERSION}, JAPPIX_VERSION));
|
||||
iqQuery.appendChild(iqResponse.buildNode('os', {'xmlns': NS_VERSION}, BrowserDetect.OS));
|
||||
|
||||
con.send(iqResponse);
|
||||
|
||||
Console.log('Received software version query: ' + iqFrom);
|
||||
self._handleSoftwareVersion(iqResponse, iqFrom);
|
||||
}
|
||||
|
||||
// Last activity query
|
||||
else if((iqQueryXMLNS == NS_LAST) && (iqType == 'get')) {
|
||||
/* REF: http://xmpp.org/extensions/xep-0012.html */
|
||||
|
||||
iqQuery = iqResponse.setQuery(NS_LAST);
|
||||
iqQuery.setAttribute('seconds', DateUtils.getLastActivity());
|
||||
|
||||
con.send(iqResponse);
|
||||
|
||||
Console.log('Received last activity query: ' + iqFrom);
|
||||
self._handleLastActivity(iqResponse, iqFrom);
|
||||
}
|
||||
|
||||
// Privacy lists push
|
||||
else if((iqQueryXMLNS == NS_PRIVACY) && (iqType == 'set') && Common.isSafeStanza(iq)) {
|
||||
// REF : http://xmpp.org/extensions/xep-0016.html
|
||||
|
||||
// Roster push
|
||||
con.send(iqResponse);
|
||||
|
||||
// Get the lists
|
||||
$(iqQuery).find('list').each(function() {
|
||||
Privacy.get($(this).attr('name'));
|
||||
});
|
||||
|
||||
Console.log('Received privacy lists push: ' + iqFrom);
|
||||
self._handlePrivacyLists(iqResponse, iqFrom, iqQuery);
|
||||
}
|
||||
|
||||
// Roster push
|
||||
else if((iqQueryXMLNS == NS_ROSTER) && (iqType == 'set') && Common.isSafeStanza(iq)) {
|
||||
// REF : http://xmpp.org/extensions/xep-0092.html
|
||||
|
||||
// Roster push
|
||||
con.send(iqResponse);
|
||||
|
||||
// Get the values
|
||||
$(iqQuery).find('item').each(function() {
|
||||
Roster.parse($(this), 'presence');
|
||||
});
|
||||
|
||||
Console.log('Received roster push: ' + iqFrom);
|
||||
self._handleRosterPush(iqResponse, iqFrom, iqQuery);
|
||||
}
|
||||
|
||||
// Roster Item Exchange query
|
||||
else if($(iqNode).find('x[xmlns="' + NS_ROSTERX + '"]').size()) {
|
||||
// Open a new notification
|
||||
Notification.create('rosterx', iqFrom, [iqNode], '');
|
||||
|
||||
Console.log('Roster Item Exchange from: ' + iqFrom);
|
||||
self._handleRosterItemExchange(iqNode, iqFrom);
|
||||
}
|
||||
|
||||
// Disco info query
|
||||
else if((iqQueryXMLNS == NS_DISCO_INFO) && (iqType == 'get')) {
|
||||
/* REF: http://xmpp.org/extensions/xep-0030.html */
|
||||
|
||||
iqQuery = iqResponse.setQuery(NS_DISCO_INFO);
|
||||
|
||||
// We set the name of the client
|
||||
iqQuery.appendChild(iqResponse.buildNode('identity', {
|
||||
'category': 'client',
|
||||
'type': 'web',
|
||||
'name': 'Jappix',
|
||||
'xmlns': NS_DISCO_INFO
|
||||
}));
|
||||
|
||||
// We set all the supported features
|
||||
var disco_infos = Caps.myDiscoInfos();
|
||||
|
||||
$.each(disco_infos, function(i, disco_info) {
|
||||
iqQuery.appendChild(iqResponse.buildNode('feature', {'var': disco_info, 'xmlns': NS_DISCO_INFO}));
|
||||
});
|
||||
|
||||
con.send(iqResponse);
|
||||
|
||||
Console.log('Received disco#infos query: ' + iqFrom);
|
||||
self._handleDiscoInfo(iqResponse, iqFrom);
|
||||
}
|
||||
|
||||
// User time query
|
||||
else if($(iqNode).find('time').size() && (iqType == 'get')) {
|
||||
/* REF: http://xmpp.org/extensions/xep-0202.html */
|
||||
|
||||
var iqTime = iqResponse.appendNode('time', {'xmlns': NS_URN_TIME});
|
||||
iqTime.appendChild(iqResponse.buildNode('tzo', {'xmlns': NS_URN_TIME}, DateUtils.getTZO()));
|
||||
iqTime.appendChild(iqResponse.buildNode('utc', {'xmlns': NS_URN_TIME}, DateUtils.getXMPPTime('utc')));
|
||||
|
||||
con.send(iqResponse);
|
||||
|
||||
Console.log('Received local time query: ' + iqFrom);
|
||||
self._handleUserTime(iqResponse, iqFrom);
|
||||
}
|
||||
|
||||
// Ping
|
||||
else if($(iqNode).find('ping').size() && (iqType == 'get')) {
|
||||
/* REF: http://xmpp.org/extensions/xep-0199.html */
|
||||
|
||||
con.send(iqResponse);
|
||||
|
||||
Console.log('Received a ping: ' + iqFrom);
|
||||
self._handlePing(iqResponse, iqFrom);
|
||||
}
|
||||
|
||||
// Jingle
|
||||
else if($(iqNode).find('jingle').size()) {
|
||||
/* REF: http://xmpp.org/extensions/xep-0166.html */
|
||||
|
||||
// Handled via JSJaCJingle_route() (see above)
|
||||
|
||||
Console.log('Received a Jingle packet: ' + iqFrom);
|
||||
self._handleJingle(iqFrom);
|
||||
}
|
||||
|
||||
// Not implemented
|
||||
else if(!$(iqNode).find('error').size() && ((iqType == 'get') || (iqType == 'set'))) {
|
||||
// Change IQ type
|
||||
iqResponse.setType('error');
|
||||
|
||||
// Append stanza content
|
||||
for(var c = 0; c < iqNode.childNodes.length; c++) {
|
||||
iqResponse.getNode().appendChild(iqNode.childNodes.item(c).cloneNode(true));
|
||||
}
|
||||
|
||||
// Append error content
|
||||
var iqError = iqResponse.appendNode('error', {'xmlns': NS_CLIENT, 'code': '501', 'type': 'cancel'});
|
||||
iqError.appendChild(iqResponse.buildNode('feature-not-implemented', {'xmlns': NS_STANZAS}));
|
||||
iqError.appendChild(iqResponse.buildNode('text', {'xmlns': NS_STANZAS}, Common._e("The feature requested is not implemented by the recipient or server and therefore cannot be processed.")));
|
||||
|
||||
con.send(iqResponse);
|
||||
|
||||
Console.log('Received an unsupported IQ query from: ' + iqFrom);
|
||||
self._raiseNotImplemented(iqResponse, iqNode, iqFrom);
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('IQ.handle', e);
|
||||
|
|
|
@ -1,138 +1,138 @@
|
|||
/**
|
||||
* jQuery.timers - Timer abstractions for jQuery
|
||||
* Written by Blair Mitchelmore (blair DOT mitchelmore AT gmail DOT com)
|
||||
* Licensed under the WTFPL (http://sam.zoy.org/wtfpl/).
|
||||
* Date: 2009/10/16
|
||||
*
|
||||
* @author Blair Mitchelmore
|
||||
* @version 1.2
|
||||
*
|
||||
**/
|
||||
|
||||
jQuery.fn.extend({
|
||||
everyTime: function(interval, label, fn, times) {
|
||||
return this.each(function() {
|
||||
jQuery.timer.add(this, interval, label, fn, times);
|
||||
});
|
||||
},
|
||||
oneTime: function(interval, label, fn) {
|
||||
return this.each(function() {
|
||||
jQuery.timer.add(this, interval, label, fn, 1);
|
||||
});
|
||||
},
|
||||
stopTime: function(label, fn) {
|
||||
return this.each(function() {
|
||||
jQuery.timer.remove(this, label, fn);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
jQuery.extend({
|
||||
timer: {
|
||||
global: [],
|
||||
guid: 1,
|
||||
dataKey: "jQuery.timer",
|
||||
regex: /^([0-9]+(?:\.[0-9]*)?)\s*(.*s)?$/,
|
||||
powers: {
|
||||
// Yeah this is major overkill...
|
||||
'ms': 1,
|
||||
'cs': 10,
|
||||
'ds': 100,
|
||||
's': 1000,
|
||||
'das': 10000,
|
||||
'hs': 100000,
|
||||
'ks': 1000000
|
||||
},
|
||||
timeParse: function(value) {
|
||||
if (value == undefined || value == null)
|
||||
return null;
|
||||
var result = this.regex.exec(jQuery.trim(value.toString()));
|
||||
if (result[2]) {
|
||||
var num = parseFloat(result[1]);
|
||||
var mult = this.powers[result[2]] || 1;
|
||||
return num * mult;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
},
|
||||
add: function(element, interval, label, fn, times) {
|
||||
var counter = 0;
|
||||
|
||||
if (jQuery.isFunction(label)) {
|
||||
if (!times)
|
||||
times = fn;
|
||||
fn = label;
|
||||
label = interval;
|
||||
}
|
||||
|
||||
interval = jQuery.timer.timeParse(interval);
|
||||
|
||||
if (typeof interval != 'number' || isNaN(interval) || interval < 0)
|
||||
return;
|
||||
|
||||
if (typeof times != 'number' || isNaN(times) || times < 0)
|
||||
times = 0;
|
||||
|
||||
times = times || 0;
|
||||
|
||||
var timers = jQuery.data(element, this.dataKey) || jQuery.data(element, this.dataKey, {});
|
||||
|
||||
if (!timers[label])
|
||||
timers[label] = {};
|
||||
|
||||
fn.timerID = fn.timerID || this.guid++;
|
||||
|
||||
var handler = function() {
|
||||
if ((++counter > times && times !== 0) || fn.call(element, counter) === false)
|
||||
jQuery.timer.remove(element, label, fn);
|
||||
};
|
||||
|
||||
handler.timerID = fn.timerID;
|
||||
|
||||
if (!timers[label][fn.timerID])
|
||||
timers[label][fn.timerID] = window.setInterval(handler,interval);
|
||||
|
||||
this.global.push( element );
|
||||
|
||||
},
|
||||
remove: function(element, label, fn) {
|
||||
var timers = jQuery.data(element, this.dataKey), ret;
|
||||
|
||||
if ( timers ) {
|
||||
|
||||
if (!label) {
|
||||
for ( label in timers )
|
||||
this.remove(element, label, fn);
|
||||
} else if ( timers[label] ) {
|
||||
if ( fn ) {
|
||||
if ( fn.timerID ) {
|
||||
window.clearInterval(timers[label][fn.timerID]);
|
||||
delete timers[label][fn.timerID];
|
||||
}
|
||||
} else {
|
||||
for ( var fn in timers[label] ) {
|
||||
window.clearInterval(timers[label][fn]);
|
||||
delete timers[label][fn];
|
||||
}
|
||||
}
|
||||
|
||||
for ( ret in timers[label] ) break;
|
||||
if ( !ret ) {
|
||||
ret = null;
|
||||
delete timers[label];
|
||||
}
|
||||
}
|
||||
|
||||
for ( ret in timers ) break;
|
||||
if ( !ret )
|
||||
jQuery.removeData(element, this.dataKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
jQuery(window).bind("unload", function() {
|
||||
jQuery.each(jQuery.timer.global, function(index, item) {
|
||||
jQuery.timer.remove(item);
|
||||
});
|
||||
});
|
||||
/**
|
||||
* jQuery.timers - Timer abstractions for jQuery
|
||||
* Written by Blair Mitchelmore (blair DOT mitchelmore AT gmail DOT com)
|
||||
* Licensed under the WTFPL (http://sam.zoy.org/wtfpl/).
|
||||
* Date: 2009/10/16
|
||||
*
|
||||
* @author Blair Mitchelmore
|
||||
* @version 1.2
|
||||
*
|
||||
**/
|
||||
|
||||
jQuery.fn.extend({
|
||||
everyTime: function(interval, label, fn, times) {
|
||||
return this.each(function() {
|
||||
jQuery.timer.add(this, interval, label, fn, times);
|
||||
});
|
||||
},
|
||||
oneTime: function(interval, label, fn) {
|
||||
return this.each(function() {
|
||||
jQuery.timer.add(this, interval, label, fn, 1);
|
||||
});
|
||||
},
|
||||
stopTime: function(label, fn) {
|
||||
return this.each(function() {
|
||||
jQuery.timer.remove(this, label, fn);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
jQuery.extend({
|
||||
timer: {
|
||||
global: [],
|
||||
guid: 1,
|
||||
dataKey: "jQuery.timer",
|
||||
regex: /^([0-9]+(?:\.[0-9]*)?)\s*(.*s)?$/,
|
||||
powers: {
|
||||
// Yeah this is major overkill...
|
||||
'ms': 1,
|
||||
'cs': 10,
|
||||
'ds': 100,
|
||||
's': 1000,
|
||||
'das': 10000,
|
||||
'hs': 100000,
|
||||
'ks': 1000000
|
||||
},
|
||||
timeParse: function(value) {
|
||||
if (value == undefined || value == null)
|
||||
return null;
|
||||
var result = this.regex.exec(jQuery.trim(value.toString()));
|
||||
if (result[2]) {
|
||||
var num = parseFloat(result[1]);
|
||||
var mult = this.powers[result[2]] || 1;
|
||||
return num * mult;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
},
|
||||
add: function(element, interval, label, fn, times) {
|
||||
var counter = 0;
|
||||
|
||||
if (jQuery.isFunction(label)) {
|
||||
if (!times)
|
||||
times = fn;
|
||||
fn = label;
|
||||
label = interval;
|
||||
}
|
||||
|
||||
interval = jQuery.timer.timeParse(interval);
|
||||
|
||||
if (typeof interval != 'number' || isNaN(interval) || interval < 0)
|
||||
return;
|
||||
|
||||
if (typeof times != 'number' || isNaN(times) || times < 0)
|
||||
times = 0;
|
||||
|
||||
times = times || 0;
|
||||
|
||||
var timers = jQuery.data(element, this.dataKey) || jQuery.data(element, this.dataKey, {});
|
||||
|
||||
if (!timers[label])
|
||||
timers[label] = {};
|
||||
|
||||
fn.timerID = fn.timerID || this.guid++;
|
||||
|
||||
var handler = function() {
|
||||
if ((++counter > times && times !== 0) || fn.call(element, counter) === false)
|
||||
jQuery.timer.remove(element, label, fn);
|
||||
};
|
||||
|
||||
handler.timerID = fn.timerID;
|
||||
|
||||
if (!timers[label][fn.timerID])
|
||||
timers[label][fn.timerID] = window.setInterval(handler,interval);
|
||||
|
||||
this.global.push( element );
|
||||
|
||||
},
|
||||
remove: function(element, label, fn) {
|
||||
var timers = jQuery.data(element, this.dataKey), ret;
|
||||
|
||||
if ( timers ) {
|
||||
|
||||
if (!label) {
|
||||
for ( label in timers )
|
||||
this.remove(element, label, fn);
|
||||
} else if ( timers[label] ) {
|
||||
if ( fn ) {
|
||||
if ( fn.timerID ) {
|
||||
window.clearInterval(timers[label][fn.timerID]);
|
||||
delete timers[label][fn.timerID];
|
||||
}
|
||||
} else {
|
||||
for ( var fn in timers[label] ) {
|
||||
window.clearInterval(timers[label][fn]);
|
||||
delete timers[label][fn];
|
||||
}
|
||||
}
|
||||
|
||||
for ( ret in timers[label] ) break;
|
||||
if ( !ret ) {
|
||||
ret = null;
|
||||
delete timers[label];
|
||||
}
|
||||
}
|
||||
|
||||
for ( ret in timers ) break;
|
||||
if ( !ret )
|
||||
jQuery.removeData(element, this.dataKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
jQuery(window).bind("unload", function() {
|
||||
jQuery.each(jQuery.timer.global, function(index, item) {
|
||||
jQuery.timer.remove(item);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -14,11 +14,11 @@ Authors: Stefan Strigler, Valérian Saliou, Zash, Maranda
|
|||
* @fileoverview Magic dependency loading. Taken from script.aculo.us
|
||||
* and modified to break it.
|
||||
* @author Stefan Strigler steve@zeank.in-berlin.de
|
||||
* @version $Revision$
|
||||
* @version 1.3
|
||||
*/
|
||||
|
||||
var JSJaC = {
|
||||
Version: '$Rev$',
|
||||
Version: '1.3',
|
||||
bind: function(fn, obj, optArg) {
|
||||
return function(arg) {
|
||||
return fn.apply(obj, [arg, optArg]);
|
||||
|
@ -26,9 +26,6 @@ var JSJaC = {
|
|||
}
|
||||
};
|
||||
|
||||
if (typeof JSJaCConnection == 'undefined')
|
||||
JSJaC.load();
|
||||
|
||||
|
||||
|
||||
/* Copyright 2006 Erik Arvidsson
|
||||
|
@ -52,7 +49,7 @@ if (typeof JSJaCConnection == 'undefined')
|
|||
* this code is taken from
|
||||
* http://webfx.eae.net/dhtml/xmlextras/xmlextras.html
|
||||
* @author Stefan Strigler steve@zeank.in-berlin.de
|
||||
* @version $Revision$
|
||||
* @version 1.3
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -282,7 +279,7 @@ if (window.XMLSerializer &&
|
|||
/**
|
||||
* @fileoverview Collection of functions to make live easier
|
||||
* @author Stefan Strigler
|
||||
* @version $Revision$
|
||||
* @version 1.3
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -1381,7 +1378,7 @@ JSJaCJSON.parse = function (str) {
|
|||
* @fileoverview This file contains all things that make life easier when
|
||||
* dealing with JIDs
|
||||
* @author Stefan Strigler
|
||||
* @version $Revision$
|
||||
* @version 1.3
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -1714,7 +1711,7 @@ var JSJaCBuilder = {
|
|||
/**
|
||||
* @fileoverview Contains all Jabber/XMPP packet related classes.
|
||||
* @author Stefan Strigler steve@zeank.in-berlin.de
|
||||
* @version $Revision$
|
||||
* @version 1.3
|
||||
*/
|
||||
|
||||
var JSJACPACKET_USE_XMLNS = true;
|
||||
|
@ -2567,7 +2564,7 @@ function JSJaCKeys(func,oDbg) {
|
|||
* @fileoverview Contains all things in common for all subtypes of connections
|
||||
* supported.
|
||||
* @author Stefan Strigler steve@zeank.in-berlin.de
|
||||
* @version $Revision$
|
||||
* @version 1.3
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -3601,10 +3598,6 @@ JSJaCConnection.prototype._handlePID = function(packet) {
|
|||
if (!packet.getID())
|
||||
return false;
|
||||
|
||||
if (packet.pType() != 'iq' ||
|
||||
(packet.getType() != 'error' && packet.getType() != 'result'))
|
||||
return false;
|
||||
|
||||
var jid = packet.getFrom() || this.jid;
|
||||
|
||||
if (packet.getFrom() == this.domain)
|
||||
|
@ -3723,7 +3716,7 @@ JSJaCConnection.prototype._parseStreamFeatures = function(doc) {
|
|||
|
||||
// Get legacy session capability if available
|
||||
this.legacy_sessions=null;
|
||||
if (doc.getElementsByTagName("session")[0]) {
|
||||
if (doc.getElementsByTagName("session")) {
|
||||
this.legacy_sessions=true;
|
||||
}
|
||||
|
||||
|
@ -3955,7 +3948,7 @@ JSJaCConnection.prototype._setStatus = function(status) {
|
|||
/**
|
||||
* @fileoverview All stuff related to HTTP Binding
|
||||
* @author Stefan Strigler steve@zeank.in-berlin.de
|
||||
* @version $Revision$
|
||||
* @version 1.3
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -4865,7 +4858,26 @@ JSJaCWebSocketConnection.prototype._parseXml = function(s) {
|
|||
this.oDbg.log('Parsing: ' + s, 4);
|
||||
try {
|
||||
doc = XmlDocument.create('stream', NS_STREAM);
|
||||
if(s.indexOf('<stream:stream') === -1) {
|
||||
if(s.trim() == '</stream:stream>') {
|
||||
// Consider session as closed
|
||||
this.oDbg.log("session terminated", 1);
|
||||
|
||||
clearTimeout(this._timeout); // remove timer
|
||||
clearInterval(this._interval);
|
||||
clearInterval(this._inQto);
|
||||
|
||||
try {
|
||||
DataStore.removeDB(MINI_HASH, 'jsjac', 'state');
|
||||
} catch (e) {}
|
||||
|
||||
this._connected = false;
|
||||
this._handleEvent('onerror',JSJaCError('503','cancel','session-terminate'));
|
||||
|
||||
this.oDbg.log("Disconnected.",1);
|
||||
this._handleEvent('ondisconnect');
|
||||
|
||||
return null;
|
||||
} else if(s.indexOf('<stream:stream') === -1) {
|
||||
// Wrap every stanza into stream element, so that XML namespaces work properly.
|
||||
doc.loadXML("<stream:stream xmlns:stream='" + NS_STREAM + "' xmlns='jabber:client'>" + s + "</stream:stream>");
|
||||
return doc.documentElement.firstChild;
|
||||
|
@ -5018,3 +5030,61 @@ JSJaCWebSocketConnection.prototype._sendRaw = function(xml, cb, arg) {
|
|||
return true;
|
||||
};
|
||||
|
||||
/*exported JSJaCUtils */
|
||||
|
||||
/**
|
||||
* Various utilities put together so that they don't pollute global
|
||||
* name space.
|
||||
* @namespace
|
||||
*/
|
||||
var JSJaCUtils = {
|
||||
/**
|
||||
* XOR two strings of equal length.
|
||||
* @param {string} s1 first string to XOR.
|
||||
* @param {string} s2 second string to XOR.
|
||||
* @return {string} s1 ^ s2.
|
||||
*/
|
||||
xor: function(s1, s2) {
|
||||
/*jshint bitwise: false */
|
||||
if(!s1) {
|
||||
return s2;
|
||||
}
|
||||
if(!s2) {
|
||||
return s1;
|
||||
}
|
||||
|
||||
var result = '';
|
||||
for(var i = 0; i < s1.length; i++) {
|
||||
result += String.fromCharCode(s1.charCodeAt(i) ^ s2.charCodeAt(i));
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
* Create nonce value of given size.
|
||||
* @param {int} size size of the nonce that should be generated.
|
||||
* @return {string} generated nonce.
|
||||
*/
|
||||
cnonce: function(size) {
|
||||
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
var cnonce = '';
|
||||
for (var i = 0; i < size; i++) {
|
||||
cnonce += tab.charAt(Math.round(Math.random(new Date().getTime()) * (tab.length - 1)));
|
||||
}
|
||||
return cnonce;
|
||||
},
|
||||
|
||||
/**
|
||||
* Current timestamp.
|
||||
* @return Seconds since 1.1.1970.
|
||||
* @type int
|
||||
*/
|
||||
now: function() {
|
||||
if (Date.now && typeof Date.now == 'function') {
|
||||
return Date.now();
|
||||
} else {
|
||||
return new Date().getTime();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -1,116 +1,116 @@
|
|||
// jXHR.js (JSON-P XHR)
|
||||
// v0.1 (c) Kyle Simpson
|
||||
// License: MIT
|
||||
// modified by gueron Jonathan to work with strophe lib
|
||||
// for http://www.iadvize.com
|
||||
|
||||
(function(global){
|
||||
var SETTIMEOUT = global.setTimeout, // for better compression
|
||||
doc = global.document,
|
||||
callback_counter = 0;
|
||||
|
||||
global.jXHR = function() {
|
||||
var script_url,
|
||||
script_loaded,
|
||||
jsonp_callback,
|
||||
scriptElem,
|
||||
publicAPI = null;
|
||||
|
||||
function removeScript() { try { scriptElem.parentNode.removeChild(scriptElem); } catch (err) { } }
|
||||
|
||||
function reset() {
|
||||
script_loaded = false;
|
||||
script_url = "";
|
||||
removeScript();
|
||||
scriptElem = null;
|
||||
fireReadyStateChange(0);
|
||||
}
|
||||
|
||||
function ThrowError(msg) {
|
||||
try {
|
||||
publicAPI.onerror.call(publicAPI,msg,script_url);
|
||||
} catch (err) {
|
||||
//throw new Error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
function handleScriptLoad() {
|
||||
if ((this.readyState && this.readyState!=="complete" && this.readyState!=="loaded") || script_loaded) { return; }
|
||||
this.onload = this.onreadystatechange = null; // prevent memory leak
|
||||
script_loaded = true;
|
||||
if (publicAPI.readyState !== 4) ThrowError("handleScriptLoad: Script failed to load ["+script_url+"].");
|
||||
removeScript();
|
||||
}
|
||||
|
||||
function parseXMLString(xmlStr) {
|
||||
var xmlDoc = null;
|
||||
if(window.DOMParser) {
|
||||
var parser = new DOMParser();
|
||||
xmlDoc = parser.parseFromString(xmlStr,"text/xml");
|
||||
}
|
||||
else {
|
||||
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
|
||||
xmlDoc.async="false";
|
||||
xmlDoc.loadXML(xmlStr);
|
||||
}
|
||||
return xmlDoc;
|
||||
}
|
||||
|
||||
function fireReadyStateChange(rs,args) {
|
||||
|
||||
args = args || [];
|
||||
publicAPI.readyState = rs;
|
||||
if (rs == 4) {
|
||||
publicAPI.responseText = args[0].reply;
|
||||
publicAPI.responseXML = parseXMLString(args[0].reply);
|
||||
}
|
||||
if (typeof publicAPI.onreadystatechange === "function") publicAPI.onreadystatechange.apply(publicAPI,args);
|
||||
}
|
||||
|
||||
publicAPI = {
|
||||
onerror:null,
|
||||
onreadystatechange:null,
|
||||
readyState:0,
|
||||
status:200,
|
||||
responseBody: null,
|
||||
responseText: null,
|
||||
responseXML: null,
|
||||
open:function(method,url){
|
||||
reset();
|
||||
var internal_callback = "cb"+(callback_counter++);
|
||||
(function(icb){
|
||||
global.jXHR[icb] = function() {
|
||||
try { fireReadyStateChange.call(publicAPI,4,arguments); }
|
||||
catch(err) {
|
||||
publicAPI.readyState = -1;
|
||||
ThrowError("Script failed to run ["+script_url+"].");
|
||||
}
|
||||
global.jXHR[icb] = null;
|
||||
};
|
||||
})(internal_callback);
|
||||
script_url = url + '?callback=?jXHR&data=';
|
||||
script_url = script_url.replace(/=\?jXHR/,"=jXHR."+internal_callback);
|
||||
fireReadyStateChange(1);
|
||||
},
|
||||
send:function(data){
|
||||
script_url = script_url + encodeURIComponent(data);
|
||||
SETTIMEOUT(function(){
|
||||
scriptElem = doc.createElement("script");
|
||||
scriptElem.setAttribute("type","text/javascript");
|
||||
scriptElem.onload = scriptElem.onreadystatechange = function(){handleScriptLoad.call(scriptElem);};
|
||||
scriptElem.setAttribute("src",script_url);
|
||||
doc.getElementsByTagName("head")[0].appendChild(scriptElem);
|
||||
},0);
|
||||
fireReadyStateChange(2);
|
||||
},
|
||||
abort:function(){},
|
||||
setRequestHeader:function(){}, // noop
|
||||
getResponseHeader:function(){return "";}, // basically noop
|
||||
getAllResponseHeaders:function(){return [];} // ditto
|
||||
};
|
||||
|
||||
reset();
|
||||
|
||||
return publicAPI;
|
||||
};
|
||||
})(window);
|
||||
// jXHR.js (JSON-P XHR)
|
||||
// v0.1 (c) Kyle Simpson
|
||||
// License: MIT
|
||||
// modified by gueron Jonathan to work with strophe lib
|
||||
// for http://www.iadvize.com
|
||||
|
||||
(function(global){
|
||||
var SETTIMEOUT = global.setTimeout, // for better compression
|
||||
doc = global.document,
|
||||
callback_counter = 0;
|
||||
|
||||
global.jXHR = function() {
|
||||
var script_url,
|
||||
script_loaded,
|
||||
jsonp_callback,
|
||||
scriptElem,
|
||||
publicAPI = null;
|
||||
|
||||
function removeScript() { try { scriptElem.parentNode.removeChild(scriptElem); } catch (err) { } }
|
||||
|
||||
function reset() {
|
||||
script_loaded = false;
|
||||
script_url = "";
|
||||
removeScript();
|
||||
scriptElem = null;
|
||||
fireReadyStateChange(0);
|
||||
}
|
||||
|
||||
function ThrowError(msg) {
|
||||
try {
|
||||
publicAPI.onerror.call(publicAPI,msg,script_url);
|
||||
} catch (err) {
|
||||
//throw new Error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
function handleScriptLoad() {
|
||||
if ((this.readyState && this.readyState!=="complete" && this.readyState!=="loaded") || script_loaded) { return; }
|
||||
this.onload = this.onreadystatechange = null; // prevent memory leak
|
||||
script_loaded = true;
|
||||
if (publicAPI.readyState !== 4) ThrowError("handleScriptLoad: Script failed to load ["+script_url+"].");
|
||||
removeScript();
|
||||
}
|
||||
|
||||
function parseXMLString(xmlStr) {
|
||||
var xmlDoc = null;
|
||||
if(window.DOMParser) {
|
||||
var parser = new DOMParser();
|
||||
xmlDoc = parser.parseFromString(xmlStr,"text/xml");
|
||||
}
|
||||
else {
|
||||
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
|
||||
xmlDoc.async="false";
|
||||
xmlDoc.loadXML(xmlStr);
|
||||
}
|
||||
return xmlDoc;
|
||||
}
|
||||
|
||||
function fireReadyStateChange(rs,args) {
|
||||
|
||||
args = args || [];
|
||||
publicAPI.readyState = rs;
|
||||
if (rs == 4) {
|
||||
publicAPI.responseText = args[0].reply;
|
||||
publicAPI.responseXML = parseXMLString(args[0].reply);
|
||||
}
|
||||
if (typeof publicAPI.onreadystatechange === "function") publicAPI.onreadystatechange.apply(publicAPI,args);
|
||||
}
|
||||
|
||||
publicAPI = {
|
||||
onerror:null,
|
||||
onreadystatechange:null,
|
||||
readyState:0,
|
||||
status:200,
|
||||
responseBody: null,
|
||||
responseText: null,
|
||||
responseXML: null,
|
||||
open:function(method,url){
|
||||
reset();
|
||||
var internal_callback = "cb"+(callback_counter++);
|
||||
(function(icb){
|
||||
global.jXHR[icb] = function() {
|
||||
try { fireReadyStateChange.call(publicAPI,4,arguments); }
|
||||
catch(err) {
|
||||
publicAPI.readyState = -1;
|
||||
ThrowError("Script failed to run ["+script_url+"].");
|
||||
}
|
||||
global.jXHR[icb] = null;
|
||||
};
|
||||
})(internal_callback);
|
||||
script_url = url + '?callback=?jXHR&data=';
|
||||
script_url = script_url.replace(/=\?jXHR/,"=jXHR."+internal_callback);
|
||||
fireReadyStateChange(1);
|
||||
},
|
||||
send:function(data){
|
||||
script_url = script_url + encodeURIComponent(data);
|
||||
SETTIMEOUT(function(){
|
||||
scriptElem = doc.createElement("script");
|
||||
scriptElem.setAttribute("type","text/javascript");
|
||||
scriptElem.onload = scriptElem.onreadystatechange = function(){handleScriptLoad.call(scriptElem);};
|
||||
scriptElem.setAttribute("src",script_url);
|
||||
doc.getElementsByTagName("head")[0].appendChild(scriptElem);
|
||||
},0);
|
||||
fireReadyStateChange(2);
|
||||
},
|
||||
abort:function(){},
|
||||
setRequestHeader:function(){}, // noop
|
||||
getResponseHeader:function(){return "";}, // basically noop
|
||||
getAllResponseHeaders:function(){return [];} // ditto
|
||||
};
|
||||
|
||||
reset();
|
||||
|
||||
return publicAPI;
|
||||
};
|
||||
})(window);
|
||||
|
|
|
@ -34,22 +34,30 @@ var Links = (function () {
|
|||
var target;
|
||||
|
||||
// Links style
|
||||
if(!style)
|
||||
if(!style) {
|
||||
style = '';
|
||||
else
|
||||
} else {
|
||||
style = ' style="' + style + '"';
|
||||
}
|
||||
|
||||
// Open in new tabs
|
||||
if(mode != 'xhtml-im')
|
||||
if(mode != 'xhtml-im') {
|
||||
target = ' target="_blank"';
|
||||
else
|
||||
} else {
|
||||
target = '';
|
||||
}
|
||||
|
||||
// XMPP address
|
||||
string = string.replace(/(\s|<br \/>|^)(([a-zA-Z0-9\._-]+)@([a-zA-Z0-9\.\/_-]+))(,|\s|$)/gi, '$1<a href="xmpp:$2" target="_blank"' + style + '>$2</a>$5');
|
||||
string = string.replace(
|
||||
/(\s|<br \/>|^)(([a-zA-Z0-9\._-]+)@([a-zA-Z0-9\.\/_-]+))(,|\s|$)/gi,
|
||||
'$1<a href="xmpp:$2" target="_blank"' + style + '>$2</a>$5'
|
||||
);
|
||||
|
||||
// Simple link
|
||||
string = string.replace(/(\s|<br \/>|^|\()((https?|ftp|file|xmpp|irc|mailto|vnc|webcal|ssh|ldap|smb|magnet|spotify)(:)([^<>'"\s\)]+))/gim, '$1<a href="$2"' + target + style + '>$2</a>');
|
||||
string = string.replace(
|
||||
/(\s|<br \/>|^|\()((https?|ftp|file|xmpp|irc|mailto|vnc|webcal|ssh|ldap|smb|magnet|spotify)(:)([^<>'"\s\)]+))/gim,
|
||||
'$1<a href="$2"' + target + style + '>$2</a>'
|
||||
);
|
||||
|
||||
return string;
|
||||
} catch(e) {
|
||||
|
|
|
@ -35,6 +35,7 @@ var MAM = (function () {
|
|||
self.map_reqs = {};
|
||||
self.map_pending = {};
|
||||
self.map_states = {};
|
||||
self.map_messages = {};
|
||||
self.msg_queue = {};
|
||||
|
||||
|
||||
|
@ -311,11 +312,16 @@ var MAM = (function () {
|
|||
if(c_message[0]) {
|
||||
// Re-build a proper JSJaC message stanza
|
||||
var message = JSJaCPacket.wrapNode(c_message[0]);
|
||||
var message_node = message.getNode();
|
||||
|
||||
// Check message type
|
||||
var type = message.getType() || 'chat';
|
||||
|
||||
if(type == 'chat') {
|
||||
// Display function
|
||||
var c_display_fn;
|
||||
var c_display_msg_bool = false;
|
||||
|
||||
// Read message data
|
||||
var xid = Common.bareXID(Common.getStanzaFrom(message));
|
||||
var id = message.getID();
|
||||
|
@ -331,50 +337,100 @@ var MAM = (function () {
|
|||
var hash = hex_md5(xid);
|
||||
var body = message.getBody();
|
||||
|
||||
// Read delay (required since we deal w/ a past message!)
|
||||
var time, stamp;
|
||||
var delay = c_delay.attr('stamp');
|
||||
// Content message?
|
||||
if(body) {
|
||||
// Read delay (required since we deal w/ a past message!)
|
||||
var time, stamp;
|
||||
var delay = c_delay.attr('stamp');
|
||||
|
||||
if(delay) {
|
||||
time = DateUtils.relative(delay);
|
||||
stamp = DateUtils.extractStamp(Date.jab2date(delay));
|
||||
}
|
||||
|
||||
// Last-minute checks before display
|
||||
if(time && stamp && body) {
|
||||
var mam_chunk_path = '#' + hash + ' .mam-chunk';
|
||||
|
||||
// No chat auto-scroll?
|
||||
var no_scroll = Common.exists(mam_chunk_path);
|
||||
|
||||
// Select the custom target
|
||||
var c_target_sel = function() {
|
||||
return $(mam_chunk_path).filter(function() {
|
||||
return $(this).attr('data-start') <= stamp && $(this).attr('data-end') >= stamp;
|
||||
}).filter(':first');
|
||||
};
|
||||
|
||||
// Display the message in that target
|
||||
var c_msg_display = function() {
|
||||
Message.display(type, from_xid, hash, b_name.htmlEnc(), body, time, stamp, 'old-message', true, null, mode, null, c_target_sel(), no_scroll);
|
||||
};
|
||||
|
||||
// Hack: do not display the message in case we would duplicate it w/ current session messages
|
||||
// only used when initiating a new chat, avoids collisions
|
||||
if(!(xid in self.map_states) && $('#' + hash).find('.one-line.user-message:last').text() == body) {
|
||||
return;
|
||||
if(delay) {
|
||||
time = DateUtils.relative(delay);
|
||||
stamp = DateUtils.extractStamp(Date.jab2date(delay));
|
||||
}
|
||||
|
||||
// Last-minute checks before display
|
||||
if(time && stamp) {
|
||||
var mam_chunk_path = '#' + hash + ' .mam-chunk';
|
||||
|
||||
// Markable message?
|
||||
var is_markable = Markers.hasRequestMarker(message_node);
|
||||
|
||||
// No chat auto-scroll?
|
||||
var no_scroll = Common.exists(mam_chunk_path);
|
||||
|
||||
// Select the custom target
|
||||
var c_target_sel = function() {
|
||||
return $(mam_chunk_path).filter(function() {
|
||||
return $(this).attr('data-start') <= stamp && $(this).attr('data-end') >= stamp;
|
||||
}).filter(':first');
|
||||
};
|
||||
|
||||
if(c_target_sel().size()) {
|
||||
// Display the message in that target
|
||||
c_msg_display();
|
||||
c_display_fn = function() {
|
||||
// Display message
|
||||
Message.display(
|
||||
type,
|
||||
from_xid,
|
||||
hash,
|
||||
b_name.htmlEnc(),
|
||||
body,
|
||||
time,
|
||||
stamp,
|
||||
'old-message',
|
||||
true,
|
||||
null,
|
||||
mode,
|
||||
id + '-mam',
|
||||
c_target_sel(),
|
||||
no_scroll,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
is_markable
|
||||
);
|
||||
|
||||
self.map_messages[id] = 1;
|
||||
};
|
||||
|
||||
c_display_msg_bool = c_target_sel().size() ? true : false;
|
||||
|
||||
// Hack: do not display the message in case we would duplicate it w/ current session messages
|
||||
// only used when initiating a new chat, avoids collisions
|
||||
if(!(xid in self.map_states) && $('#' + hash).find('.one-line.user-message:last').text() == body) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if(Markers.hasResponseMarker(message_node)) {
|
||||
// Marked message? (by other party)
|
||||
if(mode == 'him') {
|
||||
var marked_message_id = Markers.getMessageID(message_node);
|
||||
|
||||
c_display_fn = function() {
|
||||
var is_mam_marker = true;
|
||||
|
||||
Markers.handle(
|
||||
from_xid,
|
||||
message_node,
|
||||
is_mam_marker
|
||||
);
|
||||
};
|
||||
|
||||
c_display_msg_bool = (self.map_messages[marked_message_id] === 1) ? true : false;
|
||||
}
|
||||
}
|
||||
|
||||
// Display message?
|
||||
if(typeof c_display_fn == 'function') {
|
||||
if(c_display_msg_bool === true) {
|
||||
// Display message now
|
||||
c_display_fn();
|
||||
} else {
|
||||
// Delay display (we may not have received the MAM reply ATM)
|
||||
if(typeof self.msg_queue[xid] != 'object') {
|
||||
self.msg_queue[xid] = [];
|
||||
}
|
||||
|
||||
self.msg_queue[xid].push(c_msg_display);
|
||||
self.msg_queue[xid].push(c_display_fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
428
source/app/javascripts/markers.js
Normal file
|
@ -0,0 +1,428 @@
|
|||
/*
|
||||
|
||||
Jappix - An open social platform
|
||||
Implementation of XEP-0333: Chat Markers
|
||||
|
||||
-------------------------------------------------
|
||||
|
||||
License: AGPL
|
||||
Author: Valérian Saliou
|
||||
|
||||
*/
|
||||
|
||||
// Bundle
|
||||
var Markers = (function () {
|
||||
|
||||
/**
|
||||
* Alias of this
|
||||
* @private
|
||||
*/
|
||||
var self = {};
|
||||
|
||||
|
||||
/* Constants */
|
||||
self.MARK_TYPE_MARKABLE = 'markable';
|
||||
self.MARK_TYPE_RECEIVED = 'received';
|
||||
self.MARK_TYPE_DISPLAYED = 'displayed';
|
||||
self.MARK_TYPE_ACKNOWLEDGED = 'acknowledged';
|
||||
|
||||
self.MARK_TYPES = {};
|
||||
self.MARK_TYPES[self.MARK_TYPE_MARKABLE] = 1;
|
||||
self.MARK_TYPES[self.MARK_TYPE_RECEIVED] = 1;
|
||||
self.MARK_TYPES[self.MARK_TYPE_DISPLAYED] = 1;
|
||||
self.MARK_TYPES[self.MARK_TYPE_ACKNOWLEDGED] = 1;
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether entity supports message markers
|
||||
* @public
|
||||
* @param {string} xid
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.hasSupport = function(xid) {
|
||||
|
||||
var has_support = false;
|
||||
|
||||
try {
|
||||
has_support = true ? $('#' + hex_md5(xid)).attr('data-markers') == 'true' : false;
|
||||
} catch(e) {
|
||||
Console.error('Markers.hasSupport', e);
|
||||
} finally {
|
||||
return has_support;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether request message is marked or not
|
||||
* @public
|
||||
* @param {object} message
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.hasRequestMarker = function(message) {
|
||||
|
||||
var has_request_marker = false;
|
||||
|
||||
try {
|
||||
has_request_marker = ($(message).find('markable[xmlns="' + NS_URN_MARKERS + '"]').size() ? true : false);
|
||||
} catch(e) {
|
||||
Console.error('Markers.hasRequestMarker', e);
|
||||
} finally {
|
||||
return has_request_marker;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether response message is marked or not
|
||||
* @public
|
||||
* @param {object} message
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.hasResponseMarker = function(message) {
|
||||
|
||||
var has_response_marker = false;
|
||||
|
||||
try {
|
||||
var marker_sel = $(message).find('[xmlns="' + NS_URN_MARKERS + '"]');
|
||||
|
||||
if(marker_sel.size()) {
|
||||
var mark_type = marker_sel.prop('tagName').toLowerCase();
|
||||
|
||||
switch(mark_type) {
|
||||
case self.MARK_TYPE_RECEIVED:
|
||||
case self.MARK_TYPE_DISPLAYED:
|
||||
case self.MARK_TYPE_ACKNOWLEDGED:
|
||||
has_response_marker = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Markers.hasResponseMarker', e);
|
||||
} finally {
|
||||
return has_response_marker;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the marked message ID
|
||||
* @public
|
||||
* @param {object} message
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.getMessageID = function(message) {
|
||||
|
||||
var message_id = null;
|
||||
|
||||
try {
|
||||
message_id = $(message).find('[xmlns="' + NS_URN_MARKERS + '"]').attr('id');
|
||||
} catch(e) {
|
||||
Console.error('Markers.getMessageID', e);
|
||||
} finally {
|
||||
return message_id;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Marks a message
|
||||
* @public
|
||||
* @param {object} message
|
||||
* @return {undefined}
|
||||
*/
|
||||
self.mark = function(message) {
|
||||
|
||||
try {
|
||||
message.appendNode('markable', {
|
||||
'xmlns': NS_URN_MARKERS
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Markers.mark', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Changes received message status (once received or read)
|
||||
* @public
|
||||
* @param {string} mark_type
|
||||
* @param {object} message_id
|
||||
* @return {undefined}
|
||||
*/
|
||||
self.change = function(to, mark_type, message_id, message_sel) {
|
||||
|
||||
try {
|
||||
if(!(mark_type in self.MARK_TYPES)) {
|
||||
throw 'Marker type (' + mark_type + ') not supported, aborting.';
|
||||
}
|
||||
|
||||
// Store mark state
|
||||
message_sel.attr('data-mark', mark_type);
|
||||
|
||||
var message = new JSJaCMessage();
|
||||
|
||||
message.setType('chat');
|
||||
message.setTo(to);
|
||||
|
||||
message.appendNode(mark_type, {
|
||||
'xmlns': NS_URN_MARKERS,
|
||||
'id': message_id
|
||||
});
|
||||
|
||||
con.send(message);
|
||||
|
||||
Console.debug('Markers.change', 'Changed marker to: ' + mark_type + ' for message with ID: ' + message_id + ' from: ' + to);
|
||||
} catch(e) {
|
||||
Console.error('Markers.change', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles marker change coming from Carbons
|
||||
* @public
|
||||
* @param {string} message
|
||||
* @return {undefined}
|
||||
*/
|
||||
self.handleCarbonChange = function(message) {
|
||||
|
||||
try {
|
||||
// Check the marker element is existing
|
||||
var marker_sel = $(message).find('[xmlns="' + NS_URN_MARKERS + '"]');
|
||||
|
||||
if(marker_sel.size()) {
|
||||
var xid = Common.bareXID(message.getTo());
|
||||
|
||||
var mark_type = marker_sel.prop('tagName').toLowerCase();
|
||||
var mark_handle = false;
|
||||
|
||||
// Filter allowed markers
|
||||
switch(mark_type) {
|
||||
case self.MARK_TYPE_RECEIVED:
|
||||
case self.MARK_TYPE_DISPLAYED:
|
||||
case self.MARK_TYPE_ACKNOWLEDGED:
|
||||
mark_handle = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if(mark_handle === true) {
|
||||
var mark_message_id = marker_sel.attr('id');
|
||||
|
||||
var message_sel = $('#' + hex_md5(xid) + ' .content .one-line[data-mode="him"][data-markable="true"]').filter(function() {
|
||||
return ($(this).attr('data-id') + '') === (mark_message_id + '');
|
||||
}).filter(':last');
|
||||
|
||||
if(!message_sel.size()) {
|
||||
Console.warn('Markers.handleCarbonChange', 'Unknown message marker to keep in sync with Carbons for: ' + xid);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Store mark state
|
||||
message_sel.attr('data-mark', mark_type);
|
||||
|
||||
Console.debug('Markers.handleCarbonChange', 'Received Carbons chat marker (' + mark_type + ') from another resource for: ' + from);
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Markers.handleCarbonChange', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles a marked message
|
||||
* @public
|
||||
* @param {string} from
|
||||
* @param {object} message
|
||||
* @param {boolean} is_mam_marker
|
||||
* @return {undefined}
|
||||
*/
|
||||
self.handle = function(from, message, is_mam_marker) {
|
||||
|
||||
try {
|
||||
var xid = Common.bareXID(from);
|
||||
var marker_sel = $(message).find('[xmlns="' + NS_URN_MARKERS + '"]');
|
||||
|
||||
if(marker_sel.size()) {
|
||||
var mark_type = marker_sel.prop('tagName').toLowerCase();
|
||||
var mark_message_id = marker_sel.attr('id');
|
||||
|
||||
if(is_mam_marker === true) {
|
||||
mark_message_id += '-mam';
|
||||
}
|
||||
|
||||
// Filter allowed markers
|
||||
var mark_valid = false;
|
||||
|
||||
switch(mark_type) {
|
||||
case self.MARK_TYPE_RECEIVED:
|
||||
case self.MARK_TYPE_DISPLAYED:
|
||||
case self.MARK_TYPE_ACKNOWLEDGED:
|
||||
mark_valid = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if(mark_valid === false) {
|
||||
Console.warn('Markers.handle', 'Dropping unexpected chat marker (' + mark_type + ') from: ' + from);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find marked message target
|
||||
var message_sel = $('#' + hex_md5(xid) + ' .content .one-line[data-mode="me"]').filter(function() {
|
||||
return ($(this).attr('data-id') + '') === (mark_message_id + '');
|
||||
}).filter(':last');
|
||||
|
||||
if(!message_sel.size()) {
|
||||
Console.warn('Markers.handle', 'Dropping chat marker (' + mark_type + ') for inexisting message ID (' + mark_message_id + ') from: ' + from);
|
||||
return false;
|
||||
}
|
||||
|
||||
Console.debug('Markers.handle', 'Received chat marker (' + mark_type + ') from: ' + from);
|
||||
|
||||
// Finally display received marker
|
||||
self._display(xid, message_sel, mark_type);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
} catch(e) {
|
||||
Console.error('Markers.handle', e);
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adds the markers input events
|
||||
* @public
|
||||
* @param {object} target
|
||||
* @param {string} xid
|
||||
* @param {string} hash
|
||||
* @param {string} type
|
||||
* @return {undefined}
|
||||
*/
|
||||
self.events = function(target, xid, hash, type) {
|
||||
|
||||
try {
|
||||
target.focus(function() {
|
||||
// Not needed
|
||||
if(target.is(':disabled')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Send displayed message marker?
|
||||
if(type == 'chat' && self.hasSupport(xid) === true) {
|
||||
var last_message = $('#' + hash + ' .content .one-line.user-message[data-markable="true"]:last');
|
||||
|
||||
if(last_message.attr('data-mark') != self.MARK_TYPE_DISPLAYED) {
|
||||
var last_message_id = last_message.attr('data-id');
|
||||
var full_xid = Presence.highestPriority(xid) || xid;
|
||||
|
||||
if(last_message_id) {
|
||||
self.change(
|
||||
full_xid,
|
||||
self.MARK_TYPE_DISPLAYED,
|
||||
last_message_id,
|
||||
last_message
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Markers.events', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Displays a marker
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @param {object} message_sel
|
||||
* @param {string} mark_type
|
||||
* @return {boolean}
|
||||
*/
|
||||
self._display = function(xid, message_sel, mark_type) {
|
||||
|
||||
try {
|
||||
// Get marker state translation
|
||||
var marker_sel = message_sel.find('.message-marker');
|
||||
var mark_message = null;
|
||||
var css_classes = 'talk-images message-marker-read';
|
||||
var marker_category = null;
|
||||
|
||||
switch(mark_type) {
|
||||
case self.MARK_TYPE_RECEIVED:
|
||||
marker_category = 'delivered';
|
||||
|
||||
marker_sel.removeClass(css_classes);
|
||||
marker_sel.text(
|
||||
Common._e("Delivered")
|
||||
);
|
||||
break;
|
||||
|
||||
case self.MARK_TYPE_DISPLAYED:
|
||||
case self.MARK_TYPE_ACKNOWLEDGED:
|
||||
marker_category = 'read';
|
||||
|
||||
marker_sel.addClass(css_classes);
|
||||
marker_sel.text(
|
||||
Common._e("Read")
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if(marker_category !== null) {
|
||||
marker_sel.attr('data-category', marker_category);
|
||||
}
|
||||
|
||||
// Reset sending state
|
||||
message_sel.removeClass('is-sending');
|
||||
|
||||
// Toggle marker visibility
|
||||
message_sel.parents('.content').find('.one-line .message-marker').filter(function() {
|
||||
var data_category = $(this).attr('data-category');
|
||||
|
||||
if(data_category != 'delivered' && data_category != 'read') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Leave older "read" checkpoint on screen
|
||||
if(marker_category == 'delivered') {
|
||||
return data_category == marker_category;
|
||||
}
|
||||
|
||||
return true;
|
||||
}).hide();
|
||||
marker_sel.show();
|
||||
|
||||
return true;
|
||||
} catch(e) {
|
||||
Console.error('Markers._display', e);
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return class scope
|
||||
*/
|
||||
return self;
|
||||
|
||||
})();
|
|
@ -93,12 +93,14 @@ var Me = (function () {
|
|||
self.instance = function() {
|
||||
|
||||
try {
|
||||
var me_sel = $('#me');
|
||||
|
||||
// Click events
|
||||
$('#me .content a.go').click(function() {
|
||||
me_sel.find('.content a.go').click(function() {
|
||||
self.close();
|
||||
});
|
||||
|
||||
$('#me .bottom .finish').click(self.close);
|
||||
me_sel.find('.bottom .finish').click(self.close);
|
||||
} catch(e) {
|
||||
Console.error('Me.instance', e);
|
||||
}
|
||||
|
|
|
@ -748,7 +748,7 @@ var JappixMini = (function () {
|
|||
var resources_obj = {};
|
||||
|
||||
// Is this a groupchat?
|
||||
if(JappixCommon.exists('#jappix_mini div.jm_conversation[data-type="groupchat"][data-xid="' + JappixCommon.encodeQuotes(xid) + '"]')) {
|
||||
if(JappixCommon.exists('#jappix_mini div.jm_conversation[data-type="groupchat"][data-xid="' + JappixCommon.escapeQuotes(xid) + '"]')) {
|
||||
xid = from;
|
||||
}
|
||||
|
||||
|
@ -1003,7 +1003,7 @@ var JappixMini = (function () {
|
|||
is_groupchat = true;
|
||||
|
||||
// Groupchat buddy presence (not me)
|
||||
if(resource != unescape(jQuery(groupchat_path).attr('data-nick'))) {
|
||||
if(resource != JappixCommon.unescapeQuotes(jQuery(groupchat_path).attr('data-nick'))) {
|
||||
// Regenerate some stuffs
|
||||
var groupchat = xid;
|
||||
var groupchat_hash = hash;
|
||||
|
@ -1059,7 +1059,7 @@ var JappixMini = (function () {
|
|||
// Check against search string
|
||||
var search = jQuery('#jappix_mini div.jm_roster div.jm_search input.jm_searchbox').val();
|
||||
var regex = new RegExp('((^)|( ))' + JappixCommon.escapeRegex(search), 'gi');
|
||||
var nick = unescape(jQuery(friend).data('nick'));
|
||||
var nick = JappixCommon.unescapeQuotes(jQuery(friend).data('nick'));
|
||||
|
||||
if(search && !nick.match(regex)) {
|
||||
jQuery(friend).hide();
|
||||
|
@ -1110,7 +1110,7 @@ var JappixMini = (function () {
|
|||
// Is it a valid server presence?
|
||||
var valid = false;
|
||||
|
||||
if(!resource || (resource == unescape(jQuery('#jappix_mini #chat-' + hash + '[data-type="groupchat"]').attr('data-nick')))) {
|
||||
if(!resource || (resource == JappixCommon.unescapeQuotes(jQuery('#jappix_mini #chat-' + hash + '[data-type="groupchat"]').attr('data-nick')))) {
|
||||
valid = true;
|
||||
}
|
||||
|
||||
|
@ -1154,7 +1154,7 @@ var JappixMini = (function () {
|
|||
self.presence('', '', '', '', room + '/' + nickname, '', true, self.handleMUC);
|
||||
|
||||
// Update the nickname marker
|
||||
jQuery('#jappix_mini #chat-' + hash).attr('data-nick', escape(nickname));
|
||||
jQuery('#jappix_mini #chat-' + hash).attr('data-nick', JappixCommon.escapeQuotes(nickname));
|
||||
}
|
||||
|
||||
// Handle normal presence
|
||||
|
@ -1258,7 +1258,7 @@ var JappixMini = (function () {
|
|||
|
||||
// If the roster does not give us any nick the user may have send us a nickname to use with his first message
|
||||
// @see http://xmpp.org/extensions/xep-0172.html
|
||||
var known_roster_entry = jQuery('#jappix_mini a.jm_friend[data-xid="' + xid + '"]');
|
||||
var known_roster_entry = jQuery('#jappix_mini a.jm_friend[data-xid="' + JappixCommon.escapeQuotes(xid) + '"]');
|
||||
|
||||
if(known_roster_entry.size() === 0) {
|
||||
var subscription = known_roster_entry.attr('data-sub');
|
||||
|
@ -1952,7 +1952,7 @@ var JappixMini = (function () {
|
|||
|
||||
jQuery('#jappix_mini div.jm_conversation[data-type="groupchat"]').each(function() {
|
||||
var this_sub_sel = jQuery(this);
|
||||
pr_xid.push(unescape(this_sub_sel.attr('data-xid')) + '/' + unescape(this_sub_sel.attr('data-nick')));
|
||||
pr_xid.push(JappixCommon.unescapeQuotes(this_sub_sel.attr('data-xid')) + '/' + JappixCommon.unescapeQuotes(this_sub_sel.attr('data-nick')));
|
||||
});
|
||||
|
||||
// Loop on XIDs
|
||||
|
@ -2032,7 +2032,7 @@ var JappixMini = (function () {
|
|||
var chat_pwd = MINI_SUGGEST_PASSWORDS[i] || '';
|
||||
|
||||
chans_html +=
|
||||
'<a class="jm_suggest_groupchat" href="#" data-xid="' + escape(chat_room) + '" data-pwd="' + escape(chat_pwd) + '">' +
|
||||
'<a class="jm_suggest_groupchat" href="#" data-xid="' + JappixCommon.escapeQuotes(chat_room) + '" data-pwd="' + JappixCommon.escapeQuotes(chat_pwd) + '">' +
|
||||
'<span class="jm_chan_icon jm_images"></span>' +
|
||||
'<span class="jm_chan_name">' + JappixCommon.getXIDNick(chat_room).htmlEnc() + '</span>' +
|
||||
'</a>';
|
||||
|
@ -2064,12 +2064,12 @@ var JappixMini = (function () {
|
|||
if(!chat_nick) {
|
||||
chat_nick = JappixCommon.getXIDNick(chat_xid);
|
||||
} else {
|
||||
chat_nick = unescape(chat_nick);
|
||||
chat_nick = JappixCommon.unescapeQuotes(chat_nick);
|
||||
}
|
||||
|
||||
// Generate HTML for current chat
|
||||
chans_html +=
|
||||
'<a class="jm_suggest_chat" href="#" data-xid="' + escape(chat_xid) + '">' +
|
||||
'<a class="jm_suggest_chat" href="#" data-xid="' + JappixCommon.escapeQuotes(chat_xid) + '">' +
|
||||
'<span class="jm_chan_icon jm_images"></span>' +
|
||||
'<span class="jm_chan_name">' + JappixCommon.getXIDNick(chat_nick).htmlEnc() + '</span>' +
|
||||
'</a>';
|
||||
|
@ -2103,18 +2103,18 @@ var JappixMini = (function () {
|
|||
|
||||
// Chat?
|
||||
if(this_sub_sel.is('.jm_suggest_chat')) {
|
||||
var current_chat = unescape(this_sub_sel.attr('data-xid'));
|
||||
var current_chat = JappixCommon.unescapeQuotes(this_sub_sel.attr('data-xid'));
|
||||
|
||||
self.chat('chat', current_chat, this_sub_sel.find('span.jm_chan_name').text(), hex_md5(current_chat));
|
||||
}
|
||||
|
||||
// Groupchat?
|
||||
else if(this_sub_sel.is('.jm_suggest_groupchat')) {
|
||||
var current_groupchat = unescape(this_sub_sel.attr('data-xid'));
|
||||
var current_groupchat = JappixCommon.unescapeQuotes(this_sub_sel.attr('data-xid'));
|
||||
var current_password = this_sub_sel.attr('data-pwd') || null;
|
||||
|
||||
if(current_password)
|
||||
current_password = unescape(current_password);
|
||||
current_password = JappixCommon.unescapeQuotes(current_password);
|
||||
|
||||
self.chat('groupchat', current_groupchat, this_sub_sel.find('span.jm_chan_name').text(), hex_md5(current_groupchat), current_password);
|
||||
}
|
||||
|
@ -2194,7 +2194,7 @@ var JappixMini = (function () {
|
|||
// Filter buddies
|
||||
jQuery('#jappix_mini div.jm_roster div.jm_buddies a.jm_online').each(function() {
|
||||
var this_sub_sel = jQuery(this);
|
||||
var nick = unescape(this_sub_sel.data('nick'));
|
||||
var nick = JappixCommon.unescapeQuotes(this_sub_sel.data('nick'));
|
||||
|
||||
if(nick.match(regex)) {
|
||||
this_sub_sel.show();
|
||||
|
@ -2380,7 +2380,7 @@ var JappixMini = (function () {
|
|||
// Restore chat click events
|
||||
jQuery('#jappix_mini div.jm_conversation').each(function() {
|
||||
var this_sub_sel = jQuery(this);
|
||||
self.chatEvents(this_sub_sel.attr('data-type'), unescape(this_sub_sel.attr('data-xid')), this_sub_sel.attr('data-hash'));
|
||||
self.chatEvents(this_sub_sel.attr('data-type'), JappixCommon.unescapeQuotes(this_sub_sel.attr('data-xid')), this_sub_sel.attr('data-hash'));
|
||||
});
|
||||
|
||||
// Restore init marker on all groupchats
|
||||
|
@ -2447,7 +2447,7 @@ var JappixMini = (function () {
|
|||
// Using a try/catch override IE issues
|
||||
try {
|
||||
var this_sel = jQuery(this);
|
||||
self.chat('chat', unescape(this_sel.attr('data-xid')), unescape(this_sel.attr('data-nick')), this_sel.attr('data-hash'));
|
||||
self.chat('chat', JappixCommon.unescapeQuotes(this_sel.attr('data-xid')), JappixCommon.unescapeQuotes(this_sel.attr('data-nick')), this_sel.attr('data-hash'));
|
||||
}
|
||||
|
||||
catch(e) {}
|
||||
|
@ -2866,7 +2866,7 @@ var JappixMini = (function () {
|
|||
}
|
||||
|
||||
// Create the HTML markup
|
||||
var html = '<div class="jm_conversation jm_type_' + type + '" id="chat-' + hash + '" data-xid="' + escape(xid) + '" data-type="' + type + '" data-nick="' + escape(nick) + '" data-hash="' + hash + '" data-origin="' + escape(JappixCommon.cutResource(xid)) + '">' +
|
||||
var html = '<div class="jm_conversation jm_type_' + type + '" id="chat-' + hash + '" data-xid="' + JappixCommon.escapeQuotes(xid) + '" data-type="' + type + '" data-nick="' + JappixCommon.escapeQuotes(nick) + '" data-hash="' + hash + '" data-origin="' + JappixCommon.escapeQuotes(JappixCommon.cutResource(xid)) + '">' +
|
||||
'<div class="jm_chat-content">' +
|
||||
'<div class="jm_actions">' +
|
||||
'<span class="jm_nick">' + nick + '</span>';
|
||||
|
@ -2952,7 +2952,7 @@ var JappixMini = (function () {
|
|||
// Join the groupchat
|
||||
if(type == 'groupchat') {
|
||||
// Add nickname & init values
|
||||
jQuery(current).attr('data-nick', escape(nickname))
|
||||
jQuery(current).attr('data-nick', JappixCommon.escapeQuotes(nickname))
|
||||
.attr('data-init', 'false');
|
||||
|
||||
// Send the first groupchat presence
|
||||
|
@ -3035,7 +3035,7 @@ var JappixMini = (function () {
|
|||
// Quit the groupchat?
|
||||
if(type == 'groupchat') {
|
||||
// Send an unavailable presence
|
||||
self.presence('unavailable', '', '', '', xid + '/' + unescape(current_sel.attr('data-nick')));
|
||||
self.presence('unavailable', '', '', '', xid + '/' + JappixCommon.unescapeQuotes(current_sel.attr('data-nick')));
|
||||
|
||||
// Remove this groupchat!
|
||||
self.removeGroupchat(xid);
|
||||
|
@ -3221,7 +3221,7 @@ var JappixMini = (function () {
|
|||
|
||||
try {
|
||||
// Remove the groupchat private chats & the groupchat buddies from the roster
|
||||
jQuery('#jappix_mini div.jm_conversation[data-origin="' + escape(JappixCommon.cutResource(xid)) + '"], #jappix_mini div.jm_roster div.jm_grouped[data-xid="' + escape(xid) + '"]').remove();
|
||||
jQuery('#jappix_mini div.jm_conversation[data-origin="' + JappixCommon.escapeQuotes(JappixCommon.cutResource(xid)) + '"], #jappix_mini div.jm_roster div.jm_grouped[data-xid="' + JappixCommon.escapeQuotes(xid) + '"]').remove();
|
||||
|
||||
// Update the presence counter
|
||||
self.updateRoster();
|
||||
|
@ -3282,7 +3282,7 @@ var JappixMini = (function () {
|
|||
if(!chat_nick) {
|
||||
chat_nick = JappixCommon.getXIDNick(chat_xid);
|
||||
} else {
|
||||
chat_nick = unescape(chat_nick);
|
||||
chat_nick = JappixCommon.unescapeQuotes(chat_nick);
|
||||
}
|
||||
|
||||
// Open the current chat
|
||||
|
@ -3325,7 +3325,7 @@ var JappixMini = (function () {
|
|||
|
||||
// Group: start
|
||||
if(c != MINI_ROSTER_NOGROUP) {
|
||||
buddy_str += '<div class="jm_grouped jm_grouped_roster" data-name="' + escape(c) + '">';
|
||||
buddy_str += '<div class="jm_grouped jm_grouped_roster" data-name="' + JappixCommon.escapeQuotes(c) + '">';
|
||||
buddy_str += '<div class="jm_name">' + c.htmlEnc() + '</div>';
|
||||
}
|
||||
|
||||
|
@ -3392,23 +3392,23 @@ var JappixMini = (function () {
|
|||
|
||||
// Generate the groupchat group path
|
||||
if(groupchat) {
|
||||
path = '#jappix_mini div.jm_roster div.jm_grouped_groupchat[data-xid="' + escape(bare_xid) + '"]';
|
||||
path = '#jappix_mini div.jm_roster div.jm_grouped_groupchat[data-xid="' + JappixCommon.escapeQuotes(bare_xid) + '"]';
|
||||
|
||||
// Must add a groupchat group?
|
||||
if(!JappixCommon.exists(path)) {
|
||||
jQuery('#jappix_mini div.jm_roster div.jm_buddies').append(
|
||||
'<div class="jm_grouped jm_grouped_groupchat" data-xid="' + escape(bare_xid) + '">' +
|
||||
'<div class="jm_grouped jm_grouped_groupchat" data-xid="' + JappixCommon.escapeQuotes(bare_xid) + '">' +
|
||||
'<div class="jm_name">' + JappixCommon.getXIDNick(groupchat).htmlEnc() + '</div>' +
|
||||
'</div>'
|
||||
);
|
||||
}
|
||||
} else if(group) {
|
||||
path = '#jappix_mini div.jm_roster div.jm_grouped_roster[data-name="' + escape(group) + '"]';
|
||||
path = '#jappix_mini div.jm_roster div.jm_grouped_roster[data-name="' + JappixCommon.escapeQuotes(group) + '"]';
|
||||
|
||||
// Must add a roster group?
|
||||
if(!JappixCommon.exists(path)) {
|
||||
jQuery('#jappix_mini div.jm_roster div.jm_buddies').append(
|
||||
'<div class="jm_grouped jm_grouped_roster" data-name="' + escape(group) + '">' +
|
||||
'<div class="jm_grouped jm_grouped_roster" data-name="' + JappixCommon.escapeQuotes(group) + '">' +
|
||||
'<div class="jm_name">' + group.htmlEnc() + '</div>' +
|
||||
'</div>'
|
||||
);
|
||||
|
@ -3465,8 +3465,8 @@ var JappixMini = (function () {
|
|||
buddy_str += '<a class="jm_friend jm_offline jm_friend-' + hash;
|
||||
buddy_str += '" id="friend-' + hash;
|
||||
buddy_str += '" title="' + JappixCommon.encodeQuotes(xid) + '"';
|
||||
buddy_str += '" data-xid="' + escape(xid) + '"';
|
||||
buddy_str += '" data-nick="' + escape(nick) + '"';
|
||||
buddy_str += '" data-xid="' + JappixCommon.escapeQuotes(xid) + '"';
|
||||
buddy_str += '" data-nick="' + JappixCommon.escapeQuotes(nick) + '"';
|
||||
buddy_str += '" data-hash="' + hash + '"';
|
||||
buddy_str += ' ' + (subscription ? ' data-sub="' + subscription + '" ' : '');
|
||||
buddy_str += '>';
|
||||
|
@ -3501,7 +3501,7 @@ var JappixMini = (function () {
|
|||
jQuery('#jappix_mini a#friend-' + hash).remove();
|
||||
|
||||
// Empty group?
|
||||
var group = '#jappix_mini div.jm_roster div.jm_grouped_groupchat[data-xid="' + escape(groupchat) + '"]';
|
||||
var group = '#jappix_mini div.jm_roster div.jm_grouped_groupchat[data-xid="' + JappixCommon.escapeQuotes(groupchat) + '"]';
|
||||
|
||||
if(groupchat && !jQuery(group + ' a.jm_friend').size()) {
|
||||
jQuery(group).remove();
|
||||
|
@ -3962,8 +3962,8 @@ var JappixMini = (function () {
|
|||
jQuery('#jappix_mini').append(
|
||||
'<div id="jm_audio">' +
|
||||
'<audio preload="auto">' +
|
||||
'<source src="' + JAPPIX_STATIC + 'snd/receive-message.mp3" />' +
|
||||
'<source src="' + JAPPIX_STATIC + 'snd/receive-message.oga" />' +
|
||||
'<source src="' + JAPPIX_STATIC + 'sounds/receive-message.mp3" />' +
|
||||
'<source src="' + JAPPIX_STATIC + 'sounds/receive-message.oga" />' +
|
||||
'</audio>' +
|
||||
'</div>'
|
||||
);
|
||||
|
@ -4185,7 +4185,7 @@ var JappixMini = (function () {
|
|||
|
||||
// Append final stylesheet HTML
|
||||
for(var u in css_url) {
|
||||
css_html += '<link rel="stylesheet" href="' + JappixCommon.encodeQuotes(css_url[u]) + '" type="text/css" media="all" />';
|
||||
css_html += '<link rel="stylesheet" href="' + JappixCommon.encodeQuotes(css_url[u].replace(/&/g, '&')) + '" type="text/css" media="all" />';
|
||||
}
|
||||
|
||||
jQuery('head').append(css_html);
|
||||
|
|
|
@ -47,10 +47,8 @@ var Mobile = (function () {
|
|||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// No "@" in the XID, we should add the default domain
|
||||
else {
|
||||
} else {
|
||||
// No "@" in the XID, we should add the default domain
|
||||
username = xid;
|
||||
domain = HOST_MAIN;
|
||||
}
|
||||
|
@ -58,8 +56,9 @@ var Mobile = (function () {
|
|||
var pwd = aForm.pwd.value;
|
||||
var reg = false;
|
||||
|
||||
if(aForm.reg)
|
||||
if(aForm.reg) {
|
||||
reg = aForm.reg.checked;
|
||||
}
|
||||
|
||||
// Enough parameters
|
||||
if(username && domain && pwd) {
|
||||
|
@ -141,6 +140,30 @@ var Mobile = (function () {
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* Proceeds client initialization
|
||||
* @public
|
||||
* @return {undefined}
|
||||
*/
|
||||
self.doInitialize = function() {
|
||||
|
||||
try {
|
||||
if(typeof HTTP_AUTH === 'object' &&
|
||||
HTTP_AUTH.user && HTTP_AUTH.password && HTTP_AUTH.host) {
|
||||
var form_sel = document.forms['login-form'];
|
||||
|
||||
form_sel.elements.xid.value = (HTTP_AUTH.user + '@' + HTTP_AUTH.host);
|
||||
form_sel.elements.pwd.value = HTTP_AUTH.password;
|
||||
|
||||
self.doLogin(form_sel);
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Mobile.doInitialize', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Shows target element
|
||||
* @public
|
||||
|
@ -308,8 +331,9 @@ var Mobile = (function () {
|
|||
var nick = self.getNick(xid, hash);
|
||||
|
||||
// No nickname?
|
||||
if(!nick)
|
||||
if(!nick) {
|
||||
nick = xid;
|
||||
}
|
||||
|
||||
// Create the chat if it does not exist
|
||||
self.chat(xid, nick);
|
||||
|
@ -340,10 +364,8 @@ var Mobile = (function () {
|
|||
var type = pre.getType();
|
||||
var show = pre.getShow();
|
||||
|
||||
// Online buddy: show it!
|
||||
// Online buddy
|
||||
if(!type) {
|
||||
self.showThis('buddy-' + hash);
|
||||
|
||||
// Display the correct presence
|
||||
switch(show) {
|
||||
case 'chat':
|
||||
|
@ -366,8 +388,6 @@ var Mobile = (function () {
|
|||
self.displayPresence(hash, 'available');
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
self.hideThis('buddy-' + hash);
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Mobile.handlePresence', e);
|
||||
|
@ -538,7 +558,9 @@ var Mobile = (function () {
|
|||
return self.sendPresence('', 'available', 1);
|
||||
|
||||
// Define some pre-vars
|
||||
var current, xid, nick, oneBuddy, oneID, hash;
|
||||
var current, xid, nick, oneBuddy, oneID, hash, cur_buddy;
|
||||
var roster_buddies = [];
|
||||
|
||||
var roster = document.getElementById('roster');
|
||||
|
||||
// Get roster items
|
||||
|
@ -554,18 +576,30 @@ var Mobile = (function () {
|
|||
hash = hex_md5(xid);
|
||||
|
||||
// No defined nick?
|
||||
if(!nick)
|
||||
if(!nick) {
|
||||
nick = self.getDirectNick(xid);
|
||||
|
||||
// Display the values
|
||||
oneBuddy = document.createElement('a');
|
||||
oneID = 'buddy-' + hash;
|
||||
oneBuddy.setAttribute('href', '#');
|
||||
oneBuddy.setAttribute('id', oneID);
|
||||
oneBuddy.setAttribute('class', 'one-buddy');
|
||||
oneBuddy.setAttribute('onclick', 'return Mobile.chat(\'' + self.encodeOnclick(xid) + '\', \'' + self.encodeOnclick(nick) + '\');');
|
||||
oneBuddy.innerHTML = nick.htmlEnc();
|
||||
roster.appendChild(oneBuddy);
|
||||
}
|
||||
|
||||
roster_buddies.push({
|
||||
'xid': xid,
|
||||
'hash': hash,
|
||||
'nick': nick
|
||||
});
|
||||
}
|
||||
|
||||
// Sort the values
|
||||
self.sortRoster(roster_buddies);
|
||||
|
||||
// Display the values
|
||||
for(var j = 0; j < roster_buddies.length; j++) {
|
||||
cur_buddy = roster_buddies[j];
|
||||
|
||||
self.displayRoster(
|
||||
roster,
|
||||
cur_buddy.xid,
|
||||
cur_buddy.hash,
|
||||
cur_buddy.nick
|
||||
);
|
||||
}
|
||||
|
||||
// Start handling buddies presence
|
||||
|
@ -721,10 +755,11 @@ var Mobile = (function () {
|
|||
|
||||
// We split if necessary the string
|
||||
if(index !== -1) {
|
||||
if(i === 0)
|
||||
if(i === 0) {
|
||||
toStr = toStr.substr(0, index);
|
||||
else
|
||||
} else {
|
||||
toStr = toStr.substr(index + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// We return the value
|
||||
|
@ -831,10 +866,11 @@ var Mobile = (function () {
|
|||
// Display the message
|
||||
html = '<span><b';
|
||||
|
||||
if(nick == 'me')
|
||||
if(nick == 'me') {
|
||||
html += ' class="me">' + self._e("You");
|
||||
else
|
||||
} else {
|
||||
html += ' class="him">' + nick;
|
||||
}
|
||||
|
||||
html += '</b> ' + self.filter(body) + '</span>';
|
||||
|
||||
|
@ -849,6 +885,61 @@ var Mobile = (function () {
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* Displays a roster buddy
|
||||
* @public
|
||||
* @param {object} roster
|
||||
* @param {string} xid
|
||||
* @param {string} hash
|
||||
* @param {string} nick
|
||||
* @return {undefined}
|
||||
*/
|
||||
self.displayRoster = function(roster, xid, hash, nick) {
|
||||
|
||||
try {
|
||||
oneBuddy = document.createElement('a');
|
||||
oneID = 'buddy-' + hash;
|
||||
|
||||
oneBuddy.setAttribute('href', '#');
|
||||
oneBuddy.setAttribute('id', oneID);
|
||||
oneBuddy.setAttribute('class', 'one-buddy');
|
||||
oneBuddy.setAttribute('onclick', 'return Mobile.chat(\'' + self.encodeOnclick(xid) + '\', \'' + self.encodeOnclick(nick) + '\');');
|
||||
oneBuddy.innerHTML = nick.htmlEnc();
|
||||
|
||||
roster.appendChild(oneBuddy);
|
||||
} catch(e) {
|
||||
Console.error('Mobile.displayRoster', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sorts the roster buddies by nickname
|
||||
* @public
|
||||
* @param {object} roster_buddies
|
||||
* @return {object}
|
||||
*/
|
||||
self.sortRoster = function(roster_buddies) {
|
||||
|
||||
try {
|
||||
var one_nick, two_nick;
|
||||
|
||||
roster_buddies.sort(function(one, two) {
|
||||
one_nick = (one.nick + '').toLowerCase();
|
||||
two_nick = (two.nick + '').toLowerCase();
|
||||
|
||||
return one_nick < two_nick ? -1 : (one_nick > two_nick ? 1 : 0);
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Mobile.sortRoster', e);
|
||||
} finally {
|
||||
return roster_buddies;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Goes back to roster view
|
||||
* @public
|
||||
|
@ -885,8 +976,9 @@ var Mobile = (function () {
|
|||
var divs = document.getElementsByTagName('div');
|
||||
|
||||
for(var i = 0; i < divs.length; i++) {
|
||||
if(divs.item(i).getAttribute('class') == 'one-chat')
|
||||
if(divs.item(i).getAttribute('class') == 'one-chat') {
|
||||
divs.item(i).style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
// Show the chat
|
||||
|
@ -941,8 +1033,9 @@ var Mobile = (function () {
|
|||
// If the chat was not yet opened
|
||||
if(!self.exists('chat-' + hash)) {
|
||||
// No nick?
|
||||
if(!nick)
|
||||
if(!nick) {
|
||||
nick = self.getNick(xid, hash);
|
||||
}
|
||||
|
||||
// Create the chat
|
||||
self.createChat(xid, nick, hash);
|
||||
|
@ -990,6 +1083,7 @@ var Mobile = (function () {
|
|||
|
||||
try {
|
||||
onbeforeunload = self.doLogout;
|
||||
onload = self.doInitialize;
|
||||
} catch(e) {
|
||||
Console.error('Mobile.launch', e);
|
||||
}
|
||||
|
|
|
@ -154,6 +154,7 @@ var MUCAdmin = (function () {
|
|||
self.query(xid, 'owner');
|
||||
self.query(xid, 'admin');
|
||||
self.query(xid, 'outcast');
|
||||
|
||||
// We query the room to edit
|
||||
DataForm.go(xid, 'muc', '', '', 'mucadmin');
|
||||
} else if(aff == 'admin') {
|
||||
|
@ -434,8 +435,9 @@ var MUCAdmin = (function () {
|
|||
Board.openThisInfo(5);
|
||||
|
||||
// We remove the user's favorite
|
||||
if(DataStore.existDB('favorites', room))
|
||||
if(DataStore.existDB(Connection.desktop_hash, 'favorites', room)) {
|
||||
Favorites.removeThis(room, Common.explodeThis('@', room, 0));
|
||||
}
|
||||
|
||||
Console.info('MUC admin destroyed: ' + room);
|
||||
}
|
||||
|
@ -555,10 +557,13 @@ var MUCAdmin = (function () {
|
|||
try {
|
||||
// Click events
|
||||
$('#mucadmin .bottom .finish').click(function() {
|
||||
if($(this).is('.cancel'))
|
||||
if($(this).is('.cancel')) {
|
||||
return self.close();
|
||||
if($(this).is('.save'))
|
||||
}
|
||||
|
||||
if($(this).is('.save')) {
|
||||
return self.save();
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('MUCAdmin.instance', e);
|
||||
|
|
1824
source/app/javascripts/muji.js
Normal file
|
@ -63,34 +63,30 @@ var Music = (function () {
|
|||
if(!Common.exists(path_type)) {
|
||||
var code = '<div class="' + type + '"></div>';
|
||||
|
||||
if(type == 'local')
|
||||
if(type == 'local') {
|
||||
$(content).prepend(code);
|
||||
else
|
||||
} else {
|
||||
$(content).append(code);
|
||||
}
|
||||
}
|
||||
|
||||
// Fill the results
|
||||
$(xml).find('track').each(function() {
|
||||
// Parse the XML
|
||||
var id = $(this).find('id').text();
|
||||
var title = $(this).find('name').text();
|
||||
var artist = $(this).find('artist').text();
|
||||
var source = $(this).find('source').text();
|
||||
var duration = $(this).find('duration').text();
|
||||
var uri = $(this).find('url').text();
|
||||
var mime = $(this).find('type').text();
|
||||
|
||||
// No ID?
|
||||
if(!id)
|
||||
id = hex_md5(uri);
|
||||
|
||||
// No MIME?
|
||||
if(!mime)
|
||||
mime = 'audio/ogg';
|
||||
var this_sel = $(this);
|
||||
|
||||
var id = this_sel.find('id').text() || hex_md5(uri);
|
||||
var title = this_sel.find('name').text();
|
||||
var artist = this_sel.find('artist').text();
|
||||
var source = this_sel.find('source').text();
|
||||
var duration = this_sel.find('duration').text();
|
||||
var uri = this_sel.find('url').text();
|
||||
var mime = this_sel.find('type').text() || 'audio/ogg';
|
||||
|
||||
// Local URL?
|
||||
if(type == 'local')
|
||||
if(type == 'local') {
|
||||
uri = Utils.generateURL(uri);
|
||||
}
|
||||
|
||||
// Append the HTML code
|
||||
$(path_type).append('<a href="#" class="song" data-id="' + id + '">' + title + '</a>');
|
||||
|
@ -98,8 +94,9 @@ var Music = (function () {
|
|||
// Current playing song?
|
||||
var current_song = $(path_type + ' a[data-id="' + id + '"]');
|
||||
|
||||
if(Common.exists('.music-audio[data-id="' + id + '"]'))
|
||||
if(Common.exists('.music-audio[data-id="' + id + '"]')) {
|
||||
current_song.addClass('playing');
|
||||
}
|
||||
|
||||
// Click event
|
||||
current_song.click(function() {
|
||||
|
@ -117,12 +114,14 @@ var Music = (function () {
|
|||
$(path + 'input').val('').removeAttr('disabled');
|
||||
|
||||
// No result
|
||||
if(!jamendo && !local)
|
||||
if(!jamendo && !local) {
|
||||
$(path + '.no-results').show();
|
||||
}
|
||||
|
||||
// We must put a separator between the categories
|
||||
if(jamendo && local)
|
||||
if(jamendo && local) {
|
||||
$(content + ' .local').addClass('special');
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Music.parse', e);
|
||||
|
@ -157,7 +156,10 @@ var Music = (function () {
|
|||
});
|
||||
|
||||
// Get the local results
|
||||
$.get('./server/music-search.php', {searchquery: string, location: JAPPIX_LOCATION}, function(data) {
|
||||
$.get('./server/music-search.php', {
|
||||
searchquery: string,
|
||||
location: JAPPIX_LOCATION
|
||||
}, function(data) {
|
||||
self.parse(data, 'local');
|
||||
});
|
||||
} catch(e) {
|
||||
|
@ -177,33 +179,35 @@ var Music = (function () {
|
|||
|
||||
try {
|
||||
// Initialize
|
||||
var playThis = document.getElementById('top-content').getElementsByTagName('audio')[0];
|
||||
var audio_sel = document.getElementById('top-content').getElementsByTagName('audio')[0];
|
||||
|
||||
// Nothing to play, exit
|
||||
if(!playThis)
|
||||
if(!audio_sel) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var stopButton = $('#top-content a.stop');
|
||||
|
||||
// User play a song
|
||||
if(action == 'play') {
|
||||
stopButton.show();
|
||||
playThis.load();
|
||||
playThis.play();
|
||||
playThis.addEventListener('ended', function() {
|
||||
audio_sel.load();
|
||||
audio_sel.play();
|
||||
|
||||
audio_sel.addEventListener('ended', function() {
|
||||
self.action('stop');
|
||||
}, true);
|
||||
|
||||
Console.log('Music is now playing.');
|
||||
}
|
||||
|
||||
// User stop the song or the song came to its end
|
||||
else if(action == 'stop') {
|
||||
} else if(action == 'stop') {
|
||||
// User stop the song / end of song
|
||||
stopButton.hide();
|
||||
playThis.pause();
|
||||
audio_sel.pause();
|
||||
|
||||
$('#top-content .music').removeClass('actived');
|
||||
$('.music-content .list a').removeClass('playing');
|
||||
$('.music-audio').remove();
|
||||
|
||||
self.publish();
|
||||
|
||||
Console.log('Music is now stopped.');
|
||||
|
@ -245,27 +249,24 @@ var Music = (function () {
|
|||
|
||||
// Enough data?
|
||||
if(title || artist || source || uri) {
|
||||
// Data array
|
||||
var nodes = new Array(
|
||||
'title',
|
||||
'artist',
|
||||
'source',
|
||||
'length',
|
||||
'uri'
|
||||
);
|
||||
|
||||
var values = new Array(
|
||||
title,
|
||||
artist,
|
||||
source,
|
||||
length,
|
||||
uri
|
||||
);
|
||||
var music_data = {
|
||||
'title': title,
|
||||
'artist': artist,
|
||||
'source': source,
|
||||
'length': length,
|
||||
'uri': uri
|
||||
};
|
||||
|
||||
// Create the children nodes
|
||||
for(var i in nodes) {
|
||||
if(values[i]) {
|
||||
tune.appendChild(iq.buildNode(nodes[i], {'xmlns': NS_TUNE}, values[i]));
|
||||
var cur_value;
|
||||
|
||||
for(var cur_name in music_data) {
|
||||
cur_value = music_data[cur_name];
|
||||
|
||||
if(cur_value) {
|
||||
tune.appendChild(iq.buildNode(cur_name, {
|
||||
'xmlns': NS_TUNE
|
||||
}, cur_value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -298,16 +299,18 @@ var Music = (function () {
|
|||
|
||||
try {
|
||||
var path = '.music-content ';
|
||||
var music_audio_sel = $('.music-audio');
|
||||
|
||||
// We remove & create a new audio tag
|
||||
$('.music-audio').remove();
|
||||
music_audio_sel.remove();
|
||||
$(path + '.player').prepend('<audio class="music-audio" type="' + mime + '" data-id="' + id + '" />');
|
||||
|
||||
// We apply the new source to the player
|
||||
if(type == 'jamendo')
|
||||
$('.music-audio').attr('src', 'http://api.jamendo.com/get2/stream/track/redirect/?id=' + id + '&streamencoding=ogg2');
|
||||
else
|
||||
$('.music-audio').attr('src', uri);
|
||||
if(type == 'jamendo') {
|
||||
music_audio_sel.attr('src', 'http://api.jamendo.com/get2/stream/track/redirect/?id=' + id + '&streamencoding=ogg2');
|
||||
} else {
|
||||
music_audio_sel.attr('src', uri);
|
||||
}
|
||||
|
||||
// We play the target sound
|
||||
self.action('play');
|
||||
|
|
|
@ -53,8 +53,9 @@ var Name = (function () {
|
|||
|
||||
try {
|
||||
// Was it an obsolete request?
|
||||
if(!Common.exists('.add-contact-name-get[data-for="' + escape(Common.bareXID(Common.getStanzaFrom(iq))) + '"]'))
|
||||
if(!Common.exists('.add-contact-name-get[data-for="' + escape(Common.bareXID(Common.getStanzaFrom(iq))) + '"]')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Reset the waiting item
|
||||
$('.add-contact-name-get').hide().removeAttr('data-for');
|
||||
|
@ -63,8 +64,9 @@ var Name = (function () {
|
|||
if(iq.getType() == 'result') {
|
||||
var full_name = self.generateBuddy(iq)[0];
|
||||
|
||||
if(full_name)
|
||||
if(full_name) {
|
||||
$('.add-contact-name').val(full_name);
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Name.handleAddUser', e);
|
||||
|
@ -85,16 +87,16 @@ var Name = (function () {
|
|||
|
||||
try {
|
||||
// Get the IQ content
|
||||
var xml = $(iq.getNode()).find('vCard');
|
||||
var vcard_sel = $(iq.getNode()).find('vCard');
|
||||
|
||||
// Get the full name & the nickname
|
||||
var pFull = xml.find('FN:first').text();
|
||||
var pNick = xml.find('NICKNAME:first').text();
|
||||
var pFull = vcard_sel.find('FN:first').text();
|
||||
var pNick = vcard_sel.find('NICKNAME:first').text();
|
||||
|
||||
// No full name?
|
||||
if(!pFull) {
|
||||
// Get the given name
|
||||
var pN = xml.find('N:first');
|
||||
var pN = vcard_sel.find('N:first');
|
||||
var pGiven = pN.find('GIVEN:first').text();
|
||||
|
||||
if(pGiven) {
|
||||
|
@ -103,8 +105,9 @@ var Name = (function () {
|
|||
// Get the family name (optional)
|
||||
var pFamily = pN.find('FAMILY:first').text();
|
||||
|
||||
if(pFamily)
|
||||
if(pFamily) {
|
||||
pFull += ' ' + pFamily;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -132,22 +135,22 @@ var Name = (function () {
|
|||
xid = Common.bareXID(xid);
|
||||
|
||||
// This is me?
|
||||
if(Utils.isAnonymous() && !xid)
|
||||
if(Utils.isAnonymous() && !xid) {
|
||||
bname = Common._e("You");
|
||||
else if(xid == Common.getXID())
|
||||
} else if(xid == Common.getXID()) {
|
||||
bname = self.get();
|
||||
}
|
||||
|
||||
// Not me!
|
||||
else {
|
||||
cname = $('#roster .buddy[data-xid="' + escape(xid) + '"]:first .buddy-name').html();
|
||||
|
||||
// If the complete name exists
|
||||
if(cname)
|
||||
// Complete name exists?
|
||||
if(cname) {
|
||||
bname = cname.revertHtmlEnc();
|
||||
|
||||
// Else, we just get the nickname of the buddy
|
||||
else
|
||||
} else {
|
||||
bname = Common.getXIDNick(xid);
|
||||
}
|
||||
}
|
||||
|
||||
return bname;
|
||||
|
@ -170,8 +173,9 @@ var Name = (function () {
|
|||
var nick = DataStore.getDB(Connection.desktop_hash, 'profile', 'nick');
|
||||
|
||||
// No nick?
|
||||
if(!nick)
|
||||
if(!nick) {
|
||||
nick = con.username;
|
||||
}
|
||||
|
||||
return nick;
|
||||
} catch(e) {
|
||||
|
@ -192,9 +196,10 @@ var Name = (function () {
|
|||
// Try to read the user name
|
||||
var name = DataStore.getDB(Connection.desktop_hash, 'profile', 'name');
|
||||
|
||||
// No name? Use the nickname instead!
|
||||
if(!name)
|
||||
// No name? Use the nickname instead
|
||||
if(!name) {
|
||||
name = self.getNick();
|
||||
}
|
||||
|
||||
return name;
|
||||
} catch(e) {
|
||||
|
|
|
@ -62,10 +62,7 @@ var Notification = (function () {
|
|||
$(notif).prepend('<div class="notify one-counter" data-counter="' + number + '">' + number + '</div>');
|
||||
$(nothing).hide();
|
||||
$(empty).show();
|
||||
}
|
||||
|
||||
// No notification!
|
||||
else {
|
||||
} else {
|
||||
$(empty).hide();
|
||||
$(nothing).show();
|
||||
|
||||
|
@ -96,8 +93,9 @@ var Notification = (function () {
|
|||
self.create = function(type, from, data, body, id, inverse) {
|
||||
|
||||
try {
|
||||
if(!type || !from)
|
||||
if(!type || !from) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Generate an ID hash
|
||||
if(!id) {
|
||||
|
@ -229,8 +227,9 @@ var Notification = (function () {
|
|||
}
|
||||
|
||||
// No text?
|
||||
if(!text)
|
||||
if(!text) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Action links?
|
||||
switch(type) {
|
||||
|
@ -248,8 +247,9 @@ var Notification = (function () {
|
|||
action = '<a href="#" class="no">' + Common._e("Hide") + '</a>';
|
||||
|
||||
// Any parent link?
|
||||
if((type == 'comment') && data[2])
|
||||
if((type == 'comment') && data[2]) {
|
||||
action = '<a href="#" class="yes">' + Common._e("Show") + '</a>' + action;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
@ -284,10 +284,11 @@ var Notification = (function () {
|
|||
'</div>';
|
||||
|
||||
// Add the HTML code
|
||||
if(inverse)
|
||||
if(inverse) {
|
||||
$('.notifications-content .nothing').before(code);
|
||||
else
|
||||
} else {
|
||||
$('.notifications-content .empty').after(code);
|
||||
}
|
||||
|
||||
// Play a sound to alert the user
|
||||
Audio.play('notification');
|
||||
|
@ -296,8 +297,9 @@ var Notification = (function () {
|
|||
$('.' + id + ' a.yes').click(function() {
|
||||
self.action(type, data, 'yes', id);
|
||||
|
||||
if(($(this).attr('href') == '#') && ($(this).attr('target') != '_blank'))
|
||||
if(($(this).attr('href') == '#') && ($(this).attr('target') != '_blank')) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// The no click function
|
||||
|
@ -334,28 +336,23 @@ var Notification = (function () {
|
|||
|
||||
try {
|
||||
// We launch a function depending of the type
|
||||
if((type == 'subscribe') && (value == 'yes'))
|
||||
if((type == 'subscribe') && (value == 'yes')) {
|
||||
Presence.acceptSubscribe(data[0], data[1]);
|
||||
|
||||
else if((type == 'subscribe') && (value == 'no'))
|
||||
} else if((type == 'subscribe') && (value == 'no')) {
|
||||
Presence.sendSubscribe(data[0], 'unsubscribed');
|
||||
|
||||
else if((type == 'invite_room') && (value == 'yes'))
|
||||
} else if((type == 'invite_room') && (value == 'yes')) {
|
||||
Chat.checkCreate(data[0], 'groupchat');
|
||||
|
||||
else if(type == 'request')
|
||||
} else if(type == 'request') {
|
||||
HTTPReply.go(value, data[0]);
|
||||
}
|
||||
|
||||
if((type == 'send') && (value == 'yes'))
|
||||
if((type == 'send') && (value == 'yes')) {
|
||||
OOB.reply(data[0], data[3], 'accept', data[2], data[4]);
|
||||
|
||||
else if((type == 'send') && (value == 'no'))
|
||||
} else if((type == 'send') && (value == 'no')) {
|
||||
OOB.reply(data[0], data[3], 'reject', data[2], data[4]);
|
||||
|
||||
else if((type == 'rosterx') && (value == 'yes'))
|
||||
} else if((type == 'rosterx') && (value == 'yes')) {
|
||||
RosterX.open(data[0]);
|
||||
|
||||
else if((type == 'comment') || (type == 'like') || (type == 'quote') || (type == 'wall') || (type == 'photo') || (type == 'video')) {
|
||||
} else if((type == 'comment') || (type == 'like') || (type == 'quote') || (type == 'wall') || (type == 'photo') || (type == 'video')) {
|
||||
if(value == 'yes') {
|
||||
// Get the microblog item
|
||||
Microblog.fromInfos(data[2]);
|
||||
|
@ -452,25 +449,29 @@ var Notification = (function () {
|
|||
// Should we inverse?
|
||||
var inverse = true;
|
||||
|
||||
if(items.size() == 1)
|
||||
if(items.size() == 1) {
|
||||
inverse = false;
|
||||
}
|
||||
|
||||
// Parse notifications
|
||||
items.each(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// Parse the current item
|
||||
var current_item = $(this).attr('id');
|
||||
var current_type = $(this).find('link[rel="via"]:first').attr('title');
|
||||
var current_href = $(this).find('link[rel="via"]:first').attr('href');
|
||||
var current_parent_href = $(this).find('link[rel="related"]:first').attr('href');
|
||||
var current_xid = Common.explodeThis(':', $(this).find('author uri').text(), 1);
|
||||
var current_name = $(this).find('author name').text();
|
||||
var current_text = $(this).find('content[type="text"]:first').text();
|
||||
var current_item = this_sel.attr('id');
|
||||
var current_type = this_sel.find('link[rel="via"]:first').attr('title');
|
||||
var current_href = this_sel.find('link[rel="via"]:first').attr('href');
|
||||
var current_parent_href = this_sel.find('link[rel="related"]:first').attr('href');
|
||||
var current_xid = Common.explodeThis(':', this_sel.find('author uri').text(), 1);
|
||||
var current_name = this_sel.find('author name').text();
|
||||
var current_text = this_sel.find('content[type="text"]:first').text();
|
||||
var current_bname = Name.getBuddy(current_xid);
|
||||
var current_id = hex_md5(current_type + current_xid + current_href + current_text);
|
||||
|
||||
// Choose the good name!
|
||||
if(!current_name || (current_bname != Common.getXIDNick(current_xid)))
|
||||
if(!current_name || (current_bname != Common.getXIDNick(current_xid))) {
|
||||
current_name = current_bname;
|
||||
}
|
||||
|
||||
// Create it!
|
||||
self.create(current_type, current_xid, [current_name, current_href, current_parent_href, current_item], current_text, current_id, inverse);
|
||||
|
|
|
@ -39,8 +39,9 @@ var OOB = (function () {
|
|||
to = Caps.getFeatureResource(to, NS_IQOOB);
|
||||
|
||||
// IQs cannot be sent to offline users
|
||||
if(!to)
|
||||
if(!to) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Register the ID
|
||||
DataStore.setDB(Connection.desktop_hash, 'send/url', id, url);
|
||||
|
@ -92,19 +93,15 @@ var OOB = (function () {
|
|||
self.handle = function(from, id, type, node) {
|
||||
|
||||
try {
|
||||
var xid = '';
|
||||
var url = '';
|
||||
var desc = '';
|
||||
var xid = '', url = '', desc = '';
|
||||
|
||||
// IQ stanza?
|
||||
if(type == 'iq') {
|
||||
// IQ stanza
|
||||
xid = Common.fullXID(from);
|
||||
url = $(node).find('url').text();
|
||||
desc = $(node).find('desc').text();
|
||||
}
|
||||
|
||||
// Message stanza?
|
||||
else {
|
||||
} else {
|
||||
// Message stanza
|
||||
xid = Common.bareXID(from);
|
||||
url = $(node).find('url').text();
|
||||
desc = $(node).find('body').text();
|
||||
|
@ -140,8 +137,9 @@ var OOB = (function () {
|
|||
|
||||
try {
|
||||
// Not IQ type?
|
||||
if(type != 'iq')
|
||||
if(type != 'iq') {
|
||||
return;
|
||||
}
|
||||
|
||||
// New IQ
|
||||
var aIQ = new JSJaCIQ();
|
||||
|
@ -160,11 +158,17 @@ var OOB = (function () {
|
|||
aIQ.setType('error');
|
||||
|
||||
// Append stanza content
|
||||
for(var i = 0; i < node.childNodes.length; i++)
|
||||
for(var i = 0; i < node.childNodes.length; i++) {
|
||||
aIQ.getNode().appendChild(node.childNodes.item(i).cloneNode(true));
|
||||
}
|
||||
|
||||
// Append error content
|
||||
var aError = aIQ.appendNode('error', {'xmlns': NS_CLIENT, 'code': '406', 'type': 'modify'});
|
||||
var aError = aIQ.appendNode('error', {
|
||||
'xmlns': NS_CLIENT,
|
||||
'code': '406',
|
||||
'type': 'modify'
|
||||
});
|
||||
|
||||
aError.appendChild(aIQ.buildNode('not-acceptable', {'xmlns': NS_STANZAS}));
|
||||
|
||||
Console.info('Rejected file request from: ' + to);
|
||||
|
@ -187,11 +191,16 @@ var OOB = (function () {
|
|||
|
||||
try {
|
||||
// Append the wait icon
|
||||
$('#page-engine .chat-tools-file:not(.mini) .tooltip-subitem *').hide();
|
||||
$('#page-engine .chat-tools-file:not(.mini) .tooltip-subitem').append('<div class="wait wait-medium"></div>');
|
||||
var chat_tools_file_sel = page_engine_sel.find('.chat-tools-file:not(.mini)');
|
||||
var subitem_sel = chat_tools_file_sel.find('.tooltip-subitem');
|
||||
|
||||
subitem_sel.find('*').hide();
|
||||
subitem_sel.append(
|
||||
'<div class="wait wait-medium"></div>'
|
||||
);
|
||||
|
||||
// Lock the bubble
|
||||
$('#page-engine .chat-tools-file:not(.mini)').addClass('mini');
|
||||
chat_tools_file_sel.addClass('mini');
|
||||
} catch(e) {
|
||||
Console.error('OOB.waitUpload', e);
|
||||
}
|
||||
|
@ -208,6 +217,8 @@ var OOB = (function () {
|
|||
self.handleUpload = function(responseXML) {
|
||||
|
||||
try {
|
||||
var page_engine_sel = $('#page-engine');
|
||||
|
||||
// Data selector
|
||||
var dData = $(responseXML).find('jappix');
|
||||
|
||||
|
@ -220,25 +231,27 @@ var OOB = (function () {
|
|||
var oob_has;
|
||||
|
||||
// No ID provided?
|
||||
if(!fID)
|
||||
if(!fID) {
|
||||
oob_has = ':has(.wait)';
|
||||
else
|
||||
} else {
|
||||
oob_has = ':has(#oob-upload input[value="' + fID + '"])';
|
||||
}
|
||||
|
||||
var xid = $('#page-engine .page-engine-chan' + oob_has).attr('data-xid');
|
||||
var oob_type = $('#page-engine .chat-tools-file' + oob_has).attr('data-oob');
|
||||
var xid = page_engine_sel.find('.page-engine-chan' + oob_has).attr('data-xid');
|
||||
var oob_type = page_engine_sel.find('.chat-tools-file' + oob_has).attr('data-oob');
|
||||
|
||||
// Reset the file send tool
|
||||
$('#page-engine .chat-tools-file' + oob_has).removeClass('mini');
|
||||
$('#page-engine .bubble-file' + oob_has).remove();
|
||||
page_engine_sel.find('.chat-tools-file' + oob_has).removeClass('mini');
|
||||
page_engine_sel.find('.bubble-file' + oob_has).remove();
|
||||
|
||||
// Not available?
|
||||
if($('#page-engine .chat-tools-file' + oob_has).is(':hidden') && (oob_type == 'iq')) {
|
||||
if(page_engine_sel.find('.chat-tools-file' + oob_has).is(':hidden') && (oob_type == 'iq')) {
|
||||
Board.openThisError(4);
|
||||
|
||||
// Remove the file we sent
|
||||
if(fURL)
|
||||
if(fURL) {
|
||||
$.get(fURL + '&action=remove');
|
||||
}
|
||||
}
|
||||
|
||||
// Everything okay?
|
||||
|
@ -250,10 +263,7 @@ var OOB = (function () {
|
|||
Notification.create('send_pending', xid, [xid, fURL, oob_type, '', ''], fDesc, hex_md5(fURL + fDesc + fID));
|
||||
|
||||
Console.info('File request sent.');
|
||||
}
|
||||
|
||||
// Upload error?
|
||||
else {
|
||||
} else {
|
||||
Board.openThisError(4);
|
||||
|
||||
Console.error('Error while sending the file', dData.find('error').text());
|
||||
|
|
|
@ -275,11 +275,13 @@ var Options = (function () {
|
|||
self.switchTab = function(id) {
|
||||
|
||||
try {
|
||||
$('#options .one-lap').hide();
|
||||
$('#options #conf' + id).show();
|
||||
$('#options .tab a').removeClass('tab-active');
|
||||
$('#options .tab a[data-key="' + id + '"]').addClass('tab-active');
|
||||
$('#options .sub-ask .sub-ask-close').click();
|
||||
var options_sel = $('#options');
|
||||
|
||||
options_sel.find('.one-lap').hide();
|
||||
options_sel.find('#conf' + id).show();
|
||||
options_sel.find('.tab a').removeClass('tab-active');
|
||||
options_sel.find('.tab a[data-key="' + id + '"]').addClass('tab-active');
|
||||
options_sel.find('.sub-ask .sub-ask-close').click();
|
||||
} catch(e) {
|
||||
Console.error('Options.switchTab', e);
|
||||
} finally {
|
||||
|
@ -298,15 +300,16 @@ var Options = (function () {
|
|||
self.wait = function(id) {
|
||||
|
||||
try {
|
||||
var sOptions = $('#options .content');
|
||||
var options_sel = $('#options');
|
||||
var content_sel = options_sel.find('.content');
|
||||
|
||||
// Remove the current item class
|
||||
sOptions.removeClass(id);
|
||||
content_sel.removeClass(id);
|
||||
|
||||
// Hide the waiting items if all was received
|
||||
if(!sOptions.hasClass('microblog') && !sOptions.hasClass('mam')) {
|
||||
$('#options .wait').hide();
|
||||
$('#options .finish:first').removeClass('disabled');
|
||||
if(!content_sel.hasClass('microblog') && !content_sel.hasClass('mam')) {
|
||||
options_sel.find('.wait').hide();
|
||||
options_sel.find('.finish:first').removeClass('disabled');
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Options.wait', e);
|
||||
|
@ -533,22 +536,26 @@ var Options = (function () {
|
|||
$('.sub-ask-pass input').each(function() {
|
||||
var select = $(this);
|
||||
|
||||
if(!select.val())
|
||||
if(!select.val()) {
|
||||
$(document).oneTime(10, function() {
|
||||
select.addClass('please-complete').focus();
|
||||
});
|
||||
else
|
||||
} else {
|
||||
select.removeClass('please-complete');
|
||||
}
|
||||
});
|
||||
|
||||
if(password0 != Utils.getPassword())
|
||||
if(password0 != Utils.getPassword()) {
|
||||
$(document).oneTime(10, function() {
|
||||
$('#options .old').addClass('please-complete').focus();
|
||||
});
|
||||
if(password1 != password2)
|
||||
}
|
||||
|
||||
if(password1 != password2) {
|
||||
$(document).oneTime(10, function() {
|
||||
$('#options .new1, #options .new2').addClass('please-complete').focus();
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Options.sendNewPassword', e);
|
||||
|
@ -612,12 +619,13 @@ var Options = (function () {
|
|||
} else {
|
||||
var selector = $('#options .check-mam');
|
||||
|
||||
if(password != Utils.getPassword())
|
||||
if(password != Utils.getPassword()) {
|
||||
$(document).oneTime(10, function() {
|
||||
selector.addClass('please-complete').focus();
|
||||
});
|
||||
else
|
||||
} else {
|
||||
selector.removeClass('please-complete');
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Options.purgeMyArchives', e);
|
||||
|
@ -659,12 +667,13 @@ var Options = (function () {
|
|||
} else {
|
||||
var selector = $('#options .check-empty');
|
||||
|
||||
if(password != Utils.getPassword())
|
||||
if(password != Utils.getPassword()) {
|
||||
$(document).oneTime(10, function() {
|
||||
selector.addClass('please-complete').focus();
|
||||
});
|
||||
else
|
||||
} else {
|
||||
selector.removeClass('please-complete');
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Options.purgeMyMicroblog', e);
|
||||
|
@ -726,17 +735,16 @@ var Options = (function () {
|
|||
con.send(iq, self.handleAccDeletion);
|
||||
|
||||
Console.info('Delete account sent.');
|
||||
}
|
||||
|
||||
else {
|
||||
} else {
|
||||
var selector = $('#options .check-password');
|
||||
|
||||
if(password != Utils.getPassword())
|
||||
if(password != Utils.getPassword()) {
|
||||
$(document).oneTime(10, function() {
|
||||
selector.addClass('please-complete').focus();
|
||||
});
|
||||
else
|
||||
} else {
|
||||
selector.removeClass('please-complete');
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Options.deleteMyAccount', e);
|
||||
|
@ -781,50 +789,58 @@ var Options = (function () {
|
|||
}
|
||||
|
||||
// We show the "privacy" form if something is visible into it
|
||||
if(enabled_mam || enabled_pep)
|
||||
if(enabled_mam || enabled_pep) {
|
||||
$('#options fieldset.privacy').show();
|
||||
}
|
||||
|
||||
// We get the values of the forms for the sounds
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'sounds') == '0')
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'sounds') == '0') {
|
||||
$('#sounds').attr('checked', false);
|
||||
else
|
||||
} else {
|
||||
$('#sounds').attr('checked', true);
|
||||
}
|
||||
|
||||
// We get the values of the forms for the geolocation
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'geolocation') == '1')
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'geolocation') == '1') {
|
||||
$('#geolocation').attr('checked', true);
|
||||
else
|
||||
} else {
|
||||
$('#geolocation').attr('checked', false);
|
||||
}
|
||||
|
||||
// We get the values of the forms for the roster show all
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'roster-showall') == '1')
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'roster-showall') == '1') {
|
||||
$('#showall').attr('checked', true);
|
||||
else
|
||||
} else {
|
||||
$('#showall').attr('checked', false);
|
||||
}
|
||||
|
||||
// We get the values of the forms for the XHTML-IM images filter
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'no-xhtml-images') == '1')
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'no-xhtml-images') == '1') {
|
||||
$('#noxhtmlimg').attr('checked', true);
|
||||
else
|
||||
} else {
|
||||
$('#noxhtmlimg').attr('checked', false);
|
||||
}
|
||||
|
||||
// We get the values of the forms for the integratemedias
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'integratemedias') == '0')
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'integratemedias') == '0') {
|
||||
$('#integratemedias').attr('checked', false);
|
||||
else
|
||||
} else {
|
||||
$('#integratemedias').attr('checked', true);
|
||||
}
|
||||
|
||||
// We get the values of the forms for the groupchatpresence
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'groupchatpresence') == '0')
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'groupchatpresence') == '0') {
|
||||
$('#groupchatpresence').attr('checked', false);
|
||||
else
|
||||
} else {
|
||||
$('#groupchatpresence').attr('checked', true);
|
||||
}
|
||||
|
||||
// We get the values of the forms for the localarchives
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'localarchives') == '0')
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'localarchives') == '0') {
|
||||
$('#localarchives').attr('checked', false);
|
||||
else
|
||||
} else {
|
||||
$('#localarchives').attr('checked', true);
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Options.load', e);
|
||||
}
|
||||
|
@ -939,10 +955,13 @@ var Options = (function () {
|
|||
});
|
||||
|
||||
$('#options .bottom .finish').click(function() {
|
||||
if($(this).is('.save') && !$(this).hasClass('disabled'))
|
||||
if($(this).is('.save') && !$(this).hasClass('disabled')) {
|
||||
return self.save();
|
||||
if($(this).is('.cancel'))
|
||||
}
|
||||
|
||||
if($(this).is('.cancel')) {
|
||||
return self.close();
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
@ -951,20 +970,24 @@ var Options = (function () {
|
|||
$('#options .sub-ask input').keyup(function(e) {
|
||||
if(e.keyCode == 13) {
|
||||
// Archives purge
|
||||
if($(this).is('.purge-archives'))
|
||||
if($(this).is('.purge-archives')) {
|
||||
return self.purgeMyArchives();
|
||||
}
|
||||
|
||||
// Microblog purge
|
||||
else if($(this).is('.purge-microblog'))
|
||||
else if($(this).is('.purge-microblog')) {
|
||||
return self.purgeMyMicroblog();
|
||||
}
|
||||
|
||||
// Password change
|
||||
else if($(this).is('.password-change'))
|
||||
else if($(this).is('.password-change')) {
|
||||
return self.sendNewPassword();
|
||||
}
|
||||
|
||||
// Account deletion
|
||||
else if($(this).is('.delete-account'))
|
||||
else if($(this).is('.delete-account')) {
|
||||
return self.deleteMyAccount();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -215,16 +215,18 @@ var Privacy = (function () {
|
|||
// Any block list?
|
||||
if($(iqQuery).find('list[name="block"]').size()) {
|
||||
// Not the default one?
|
||||
if(!$(iqQuery).find('default[name="block"]').size())
|
||||
if(!$(iqQuery).find('default[name="block"]').size()) {
|
||||
self.change('block', 'default');
|
||||
else
|
||||
} else {
|
||||
DataStore.setDB(Connection.desktop_hash, 'privacy-marker', 'default', 'block');
|
||||
}
|
||||
|
||||
// Not the active one?
|
||||
if(!$(iqQuery).find('active[name="block"]').size())
|
||||
if(!$(iqQuery).find('active[name="block"]').size()) {
|
||||
self.change('block', 'active');
|
||||
else
|
||||
} else {
|
||||
DataStore.setDB(Connection.desktop_hash, 'privacy-marker', 'active', 'block');
|
||||
}
|
||||
|
||||
// Get the block list rules
|
||||
self.get('block');
|
||||
|
@ -381,10 +383,11 @@ var Privacy = (function () {
|
|||
}
|
||||
|
||||
con.send(iq, function(iq) {
|
||||
if(iq.getType() == 'result')
|
||||
if(iq.getType() == 'result') {
|
||||
Console.log('Sent privacy list.');
|
||||
else
|
||||
} else {
|
||||
Console.error('Error sending privacy list.');
|
||||
}
|
||||
});
|
||||
|
||||
Console.log('Sending privacy list: ' + list);
|
||||
|
@ -455,8 +458,9 @@ var Privacy = (function () {
|
|||
if(!c_order)
|
||||
c_order = '';
|
||||
|
||||
if(!isNaN(c_order) && parseInt(c_order) > highest_order)
|
||||
if(!isNaN(c_order) && parseInt(c_order) > highest_order) {
|
||||
highest_order = parseInt(c_order);
|
||||
}
|
||||
|
||||
type.push(c_type);
|
||||
value.push(c_value);
|
||||
|
@ -464,25 +468,29 @@ var Privacy = (function () {
|
|||
order.push(c_order);
|
||||
|
||||
// Child elements
|
||||
if($(this).find('presence-in').size())
|
||||
if($(this).find('presence-in').size()) {
|
||||
presence_in.push(true);
|
||||
else
|
||||
} else {
|
||||
presence_in.push(false);
|
||||
}
|
||||
|
||||
if($(this).find('presence-out').size())
|
||||
if($(this).find('presence-out').size()) {
|
||||
presence_out.push(true);
|
||||
else
|
||||
} else {
|
||||
presence_out.push(false);
|
||||
}
|
||||
|
||||
if($(this).find('message').size())
|
||||
if($(this).find('message').size()) {
|
||||
msg.push(true);
|
||||
else
|
||||
} else {
|
||||
msg.push(false);
|
||||
}
|
||||
|
||||
if($(this).find('iq').size())
|
||||
if($(this).find('iq').size()) {
|
||||
iq_p.push(true);
|
||||
else
|
||||
} else {
|
||||
iq_p.push(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -508,8 +516,9 @@ var Privacy = (function () {
|
|||
|
||||
try {
|
||||
// Yet sent?
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'privacy-marker', status) == list)
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'privacy-marker', status) == list) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Write a marker
|
||||
DataStore.setDB(Connection.desktop_hash, 'privacy-marker', status, list);
|
||||
|
@ -523,8 +532,9 @@ var Privacy = (function () {
|
|||
var iqStatus = iqQuery.appendChild(iq.buildNode(status, {'xmlns': NS_PRIVACY}));
|
||||
|
||||
// Can add a "name" attribute?
|
||||
if(list)
|
||||
if(list) {
|
||||
iqStatus.setAttribute('name', list);
|
||||
}
|
||||
|
||||
con.send(iq);
|
||||
|
||||
|
@ -596,18 +606,20 @@ var Privacy = (function () {
|
|||
$(data).find('list').each(function() {
|
||||
var list_name = $(this).attr('name');
|
||||
|
||||
if(list_name)
|
||||
if(list_name) {
|
||||
code += '<option value="' + Common.encodeQuotes(list_name) + '">' + list_name.htmlEnc() + '</option>';
|
||||
}
|
||||
});
|
||||
|
||||
// Apply HTML code
|
||||
select.html(code);
|
||||
|
||||
// Not empty?
|
||||
if(code)
|
||||
if(code) {
|
||||
select.removeAttr('disabled');
|
||||
else
|
||||
} else {
|
||||
select.attr('disabled', true);
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Privacy.displayLists', e);
|
||||
} finally {
|
||||
|
@ -638,8 +650,9 @@ var Privacy = (function () {
|
|||
select.html('');
|
||||
|
||||
// No list?
|
||||
if(!list)
|
||||
if(!list) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Reset the list status
|
||||
$('#privacy .privacy-active input[type="checkbox"]').removeAttr('checked');
|
||||
|
@ -648,8 +661,9 @@ var Privacy = (function () {
|
|||
var status = ['active', 'default'];
|
||||
|
||||
for(var s in status) {
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'privacy-marker', status[s]) == list)
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'privacy-marker', status[s]) == list) {
|
||||
$('#privacy .privacy-active input[name=' + status[s] + ']').attr('checked', true);
|
||||
}
|
||||
}
|
||||
|
||||
// Try to read the stored items
|
||||
|
@ -660,10 +674,9 @@ var Privacy = (function () {
|
|||
select.attr('disabled', true);
|
||||
|
||||
return self.get(list);
|
||||
}
|
||||
|
||||
else
|
||||
} else {
|
||||
select.removeAttr('disabled');
|
||||
}
|
||||
|
||||
// Parse the XML data!
|
||||
$(items).find('item').each(function() {
|
||||
|
@ -814,8 +827,9 @@ var Privacy = (function () {
|
|||
$(type_check).attr('checked', true);
|
||||
|
||||
// Can apply a value?
|
||||
if(value_input)
|
||||
if(value_input) {
|
||||
$(value_input).val(value);
|
||||
}
|
||||
|
||||
// Apply the things to do
|
||||
var privacy_do = '#privacy .privacy-third input[type="checkbox"]';
|
||||
|
@ -924,8 +938,9 @@ var Privacy = (function () {
|
|||
var list = $('#privacy .privacy-head .list-left select').val();
|
||||
|
||||
// No value?
|
||||
if(!list)
|
||||
if(!list) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove it from popup
|
||||
$('#privacy .privacy-head .list-left select option[value="' + list + '"]').remove();
|
||||
|
@ -941,8 +956,9 @@ var Privacy = (function () {
|
|||
var status = ['active', 'default'];
|
||||
|
||||
for(var s in status) {
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'privacy-marker', status[s]) == list)
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'privacy-marker', status[s]) == list) {
|
||||
self.change('', status[s]);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove from server
|
||||
|
@ -957,8 +973,9 @@ var Privacy = (function () {
|
|||
|
||||
$('#privacy .privacy-head .list-right input').keyup(function(e) {
|
||||
// Not enter?
|
||||
if(e.keyCode != 13)
|
||||
if(e.keyCode != 13) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get list name
|
||||
var list = $('#privacy .privacy-head .list-right input').val();
|
||||
|
@ -1002,21 +1019,22 @@ var Privacy = (function () {
|
|||
|
||||
// Display the data!
|
||||
self.displayForm(
|
||||
item.attr('data-type'),
|
||||
item.attr('data-value'),
|
||||
item.attr('data-action'),
|
||||
item.attr('data-order'),
|
||||
item.attr('data-presence_in'),
|
||||
item.attr('data-presence_out'),
|
||||
item.attr('data-message'),
|
||||
item.attr('data-iq')
|
||||
);
|
||||
item.attr('data-type'),
|
||||
item.attr('data-value'),
|
||||
item.attr('data-action'),
|
||||
item.attr('data-order'),
|
||||
item.attr('data-presence_in'),
|
||||
item.attr('data-presence_out'),
|
||||
item.attr('data-message'),
|
||||
item.attr('data-iq')
|
||||
);
|
||||
});
|
||||
|
||||
$('#privacy .privacy-item a.item-add').click(function() {
|
||||
// Cannot add anything?
|
||||
if(!Common.exists('#privacy .privacy-head .list-left select option:selected'))
|
||||
if(!Common.exists('#privacy .privacy-head .list-left select option:selected')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Disable item select
|
||||
$('#privacy .privacy-item select').attr('disabled', true);
|
||||
|
@ -1034,8 +1052,9 @@ var Privacy = (function () {
|
|||
|
||||
$('#privacy .privacy-item a.item-remove').click(function() {
|
||||
// Cannot add anything?
|
||||
if(!Common.exists('#privacy .privacy-head .list-left select option:selected'))
|
||||
if(!Common.exists('#privacy .privacy-head .list-left select option:selected')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get values
|
||||
var list = $('#privacy .privacy-head .list-left select').val();
|
||||
|
@ -1055,15 +1074,17 @@ var Privacy = (function () {
|
|||
$('#privacy .privacy-head .list-left select option[value="' + list + '"]').remove();
|
||||
|
||||
// No more privacy lists?
|
||||
if(!Common.exists('#privacy .privacy-head .list-left select option'))
|
||||
if(!Common.exists('#privacy .privacy-head .list-left select option')) {
|
||||
$('#privacy .privacy-head .list-left select').attr('disabled', true);
|
||||
}
|
||||
|
||||
// Disable this list before removing it
|
||||
var status = ['active', 'default'];
|
||||
|
||||
for(var s in status) {
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'privacy-marker', status[s]) == list)
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'privacy-marker', status[s]) == list) {
|
||||
self.change('', status[s]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1079,14 +1100,16 @@ var Privacy = (function () {
|
|||
|
||||
$('#privacy .privacy-item a.item-save').click(function() {
|
||||
// Canot push item?
|
||||
if(Common.exists('#privacy .privacy-form input:disabled'))
|
||||
if(Common.exists('#privacy .privacy-form input:disabled')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the hash
|
||||
var item_hash = '';
|
||||
|
||||
if(!$('#privacy .privacy-item select').is(':disabled'))
|
||||
if(!$('#privacy .privacy-item select').is(':disabled')) {
|
||||
item_hash = $('#privacy .privacy-item select option:selected').attr('data-hash');
|
||||
}
|
||||
|
||||
// Read the form
|
||||
var privacy_second = '#privacy .privacy-second';
|
||||
|
@ -1142,17 +1165,17 @@ var Privacy = (function () {
|
|||
|
||||
// Push item to the server!
|
||||
self.push(
|
||||
item_list,
|
||||
[item_type],
|
||||
[item_value],
|
||||
[item_action],
|
||||
[item_order],
|
||||
[item_prin],
|
||||
[item_prout],
|
||||
[item_msg],
|
||||
[item_iq],
|
||||
item_hash
|
||||
);
|
||||
item_list,
|
||||
[item_type],
|
||||
[item_value],
|
||||
[item_action],
|
||||
[item_order],
|
||||
[item_prin],
|
||||
[item_prout],
|
||||
[item_msg],
|
||||
[item_iq],
|
||||
item_hash
|
||||
);
|
||||
|
||||
return false;
|
||||
});
|
||||
|
@ -1170,16 +1193,19 @@ var Privacy = (function () {
|
|||
var target = '#privacy .privacy-third input[type="checkbox"]';
|
||||
|
||||
// Must tick "everything" checkbox?
|
||||
if(!$(target).filter(':checked').size())
|
||||
if(!$(target).filter(':checked').size()) {
|
||||
$(target + '[name="everything"]').attr('checked', true);
|
||||
}
|
||||
|
||||
// Must untick the other checkboxes?
|
||||
else if($(this).is('[name="everything"]'))
|
||||
else if($(this).is('[name="everything"]')) {
|
||||
$(target + ':not([name="everything"])').removeAttr('checked');
|
||||
}
|
||||
|
||||
// Must untick "everything" checkbox?
|
||||
else
|
||||
else {
|
||||
$(target + '[name="everything"]').removeAttr('checked');
|
||||
}
|
||||
});
|
||||
|
||||
$('#privacy .privacy-active input[name="order"]').keyup(function() {
|
||||
|
@ -1187,14 +1213,16 @@ var Privacy = (function () {
|
|||
var value = $(this).val();
|
||||
|
||||
// No value?
|
||||
if(!value)
|
||||
if(!value) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Not a number?
|
||||
if(isNaN(value))
|
||||
if(isNaN(value)) {
|
||||
value = 1;
|
||||
else
|
||||
} else {
|
||||
value = parseInt(value);
|
||||
}
|
||||
|
||||
// Negative?
|
||||
if(value < 0)
|
||||
|
@ -1206,8 +1234,9 @@ var Privacy = (function () {
|
|||
|
||||
.blur(function() {
|
||||
// No value?
|
||||
if(!$(this).val())
|
||||
if(!$(this).val()) {
|
||||
$(this).val('1');
|
||||
}
|
||||
});
|
||||
|
||||
$('#privacy .privacy-active .privacy-active-elements input').change(function() {
|
||||
|
@ -1216,14 +1245,16 @@ var Privacy = (function () {
|
|||
var state_name = $(this).attr('name');
|
||||
|
||||
// Cannot continue?
|
||||
if(!list_name || !state_name)
|
||||
if(!list_name || !state_name) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Change the current list status
|
||||
if($(this).filter(':checked').size())
|
||||
if($(this).filter(':checked').size()) {
|
||||
self.change(list_name, state_name);
|
||||
else
|
||||
} else {
|
||||
self.change('', state_name);
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Privacy.instance', e);
|
||||
|
|
|
@ -108,8 +108,9 @@ var Receipts = (function () {
|
|||
aMsg.setID(id);
|
||||
|
||||
// Any type?
|
||||
if(type)
|
||||
if(type) {
|
||||
aMsg.setType(type);
|
||||
}
|
||||
|
||||
// Append the received node
|
||||
aMsg.appendNode('received', {'xmlns': NS_URN_RECEIPTS, 'id': id});
|
||||
|
@ -147,7 +148,7 @@ var Receipts = (function () {
|
|||
// Remove the group marker
|
||||
if(!group.find('.one-line[data-lost]').size()) {
|
||||
group.find('b.name').removeClass('talk-images')
|
||||
.removeAttr('title');
|
||||
.removeAttr('title');
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Receipts.messageReceived', e);
|
||||
|
@ -170,14 +171,19 @@ var Receipts = (function () {
|
|||
try {
|
||||
// Fire a check 10 seconds later
|
||||
$('#' + hash + ' .one-line[data-id="' + id + '"]').oneTime('10s', function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// Not received?
|
||||
if($(this).attr('data-received') != 'true') {
|
||||
if(this_sel.attr('data-received') != 'true') {
|
||||
// Add a "lost" marker
|
||||
$(this).attr('data-lost', 'true');
|
||||
this_sel.attr('data-lost', 'true');
|
||||
|
||||
// Add a warn on the buddy-name
|
||||
$(this).parent().find('b.name').addClass('talk-images')
|
||||
.attr('title', Common._e("Your friend seems not to have received your message(s)!"));
|
||||
this_sel.parent().find('b.name').addClass('talk-images')
|
||||
.attr(
|
||||
'title',
|
||||
Common._e("Your friend seems not to have received your message(s)!")
|
||||
);
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
|
|
|
@ -57,12 +57,12 @@ var Roster = (function () {
|
|||
// Parse the roster xml
|
||||
$(iq.getQuery()).find('item').each(function() {
|
||||
// Get user data
|
||||
var _this = $(this);
|
||||
var user_xid = _this.attr('jid');
|
||||
var user_subscription = _this.attr('subscription');
|
||||
var this_sel = $(this);
|
||||
var user_xid = this_sel.attr('jid');
|
||||
var user_subscription = this_sel.attr('subscription');
|
||||
|
||||
// Parse roster data & display user
|
||||
self.parse($(this), 'load');
|
||||
self.parse(this_sel, 'load');
|
||||
|
||||
// Request user microblog (populates channel)
|
||||
if(user_xid && ((user_subscription == 'both') || (user_subscription == 'to'))) {
|
||||
|
@ -106,17 +106,20 @@ var Roster = (function () {
|
|||
current.find('group').each(function() {
|
||||
var group_text = $(this).text();
|
||||
|
||||
if(group_text)
|
||||
if(group_text) {
|
||||
groups.push(group_text);
|
||||
}
|
||||
});
|
||||
|
||||
// No group?
|
||||
if(!groups.length)
|
||||
if(!groups.length) {
|
||||
groups.push(Common._e("Unclassified"));
|
||||
}
|
||||
|
||||
// If no name is defined, we get the default nick of the buddy
|
||||
if(!dName)
|
||||
if(!dName) {
|
||||
dName = Common.getXIDNick(xid);
|
||||
}
|
||||
|
||||
self.display(xid, xidHash, dName, subscription, groups, mode);
|
||||
} catch(e) {
|
||||
|
@ -135,23 +138,28 @@ var Roster = (function () {
|
|||
|
||||
try {
|
||||
$('#roster .one-group').each(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// Current values
|
||||
var check = $(this).find('.buddy').size();
|
||||
var hidden = $(this).find('.buddy:not(.hidden-buddy:hidden)').size();
|
||||
var check = this_sel.find('.buddy').size();
|
||||
var hidden = this_sel.find('.buddy:not(.hidden-buddy:hidden)').size();
|
||||
|
||||
// Special case: the filtering tool
|
||||
if(Search.search_filtered)
|
||||
hidden = $(this).find('.buddy:visible').size();
|
||||
if(Search.search_filtered) {
|
||||
hidden = this_sel.find('.buddy:visible').size();
|
||||
}
|
||||
|
||||
// If the group is empty
|
||||
if(!check)
|
||||
$(this).remove();
|
||||
if(!check) {
|
||||
this_sel.remove();
|
||||
}
|
||||
|
||||
// If the group contains no online buddy (and is not just hidden)
|
||||
if(!hidden && $(this).find('a.group').hasClass('minus'))
|
||||
$(this).hide();
|
||||
else
|
||||
$(this).show();
|
||||
if(!hidden && this_sel.find('a.group').hasClass('minus')) {
|
||||
this_sel.hide();
|
||||
} else {
|
||||
this_sel.show();
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Roster.updateGroups', e);
|
||||
|
@ -202,8 +210,9 @@ var Roster = (function () {
|
|||
var privacy_class = '';
|
||||
var privacy_state = Privacy.status('block', dXID);
|
||||
|
||||
if(privacy_state == 'deny')
|
||||
if(privacy_state == 'deny') {
|
||||
privacy_class = ' blocked';
|
||||
}
|
||||
|
||||
// For each group this buddy has
|
||||
$.each(dGroup, function(i, cGroup) {
|
||||
|
@ -214,8 +223,9 @@ var Roster = (function () {
|
|||
var groupBuddies = groupContent + ' .group-buddies';
|
||||
|
||||
// Is this group blocked?
|
||||
if((Privacy.status('block', cGroup) == 'deny') && (privacy_state != 'allow'))
|
||||
if((Privacy.status('block', cGroup) == 'deny') && (privacy_state != 'allow')) {
|
||||
privacy_class = ' blocked';
|
||||
}
|
||||
|
||||
// Group not yet displayed
|
||||
if(!Common.exists(groupContent)) {
|
||||
|
@ -272,13 +282,13 @@ var Roster = (function () {
|
|||
html += '<div class="name">';
|
||||
|
||||
// Special gateway code
|
||||
if(is_gateway)
|
||||
if(is_gateway) {
|
||||
html += presence_code +
|
||||
name_code;
|
||||
|
||||
else
|
||||
} else {
|
||||
html += name_code +
|
||||
presence_code;
|
||||
}
|
||||
|
||||
html += '</div></div></div>';
|
||||
|
||||
|
@ -374,8 +384,9 @@ var Roster = (function () {
|
|||
});
|
||||
|
||||
// Create a new checked checkbox
|
||||
if(!group_exists)
|
||||
if(!group_exists) {
|
||||
$(bm_choose).prepend('<label><input type="checkbox" data-group="' + escaped_value + '" /><span>' + this_value.htmlEnc() + '</span></label>');
|
||||
}
|
||||
|
||||
// Check the checkbox
|
||||
$(bm_choose + ' input[data-group="' + escaped_value + '"]').attr('checked', true);
|
||||
|
@ -423,8 +434,9 @@ var Roster = (function () {
|
|||
Bubble.close();
|
||||
|
||||
// First unregister if gateway
|
||||
if(Common.isGateway(xid))
|
||||
if(Common.isGateway(xid)) {
|
||||
self.unregisterGateway(xid);
|
||||
}
|
||||
|
||||
// Then send roster removal query
|
||||
self.send(xid, 'remove');
|
||||
|
@ -462,8 +474,9 @@ var Roster = (function () {
|
|||
|
||||
// If the pointer is on a stored presence
|
||||
if(current.match(db_regex)) {
|
||||
if(Common.bareXID(RegExp.$1) == xid)
|
||||
if(Common.bareXID(RegExp.$1) == xid) {
|
||||
DataStore.storageDB.removeItem(current);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -510,13 +523,15 @@ var Roster = (function () {
|
|||
// Apply the hover event
|
||||
$(bPath).hover(function() {
|
||||
// Another bubble exist
|
||||
if(Common.exists('#roster .buddy-infos'))
|
||||
if(Common.exists('#roster .buddy-infos')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$(bPath).oneTime(200, function() {
|
||||
// Another bubble exist
|
||||
if(Common.exists('#roster .buddy-infos'))
|
||||
if(Common.exists('#roster .buddy-infos')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add this bubble!
|
||||
Bubble.show(iPath);
|
||||
|
@ -552,36 +567,45 @@ var Roster = (function () {
|
|||
|
||||
// Click events
|
||||
$(bPath + ' .bi-view a').click(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// Renitialize the buddy infos
|
||||
Bubble.close();
|
||||
|
||||
// Profile
|
||||
if($(this).is('.profile'))
|
||||
if(this_sel.is('.profile')) {
|
||||
UserInfos.open(xid);
|
||||
}
|
||||
|
||||
// Channel
|
||||
else if($(this).is('.channel'))
|
||||
else if(this_sel.is('.channel')) {
|
||||
Microblog.fromInfos(xid, hash);
|
||||
}
|
||||
|
||||
// Command
|
||||
else if($(this).is('.commands'))
|
||||
else if(this_sel.is('.commands')) {
|
||||
AdHoc.retrieve(xid);
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
// Jingle events
|
||||
$(bPath + ' .bi-jingle a').click(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// Renitialize the buddy infos
|
||||
Bubble.close();
|
||||
|
||||
// Audio call?
|
||||
if($(this).is('.audio'))
|
||||
if(this_sel.is('.audio')) {
|
||||
Jingle.start(xid, 'audio');
|
||||
}
|
||||
|
||||
// Video call?
|
||||
else if($(this).is('.video'))
|
||||
else if(this_sel.is('.video')) {
|
||||
Jingle.start(xid, 'video');
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
@ -593,8 +617,9 @@ var Roster = (function () {
|
|||
});
|
||||
});
|
||||
}, function() {
|
||||
if(!Common.exists(iPath + ' .manage-infos'))
|
||||
if(!Common.exists(iPath + ' .manage-infos')) {
|
||||
Bubble.close();
|
||||
}
|
||||
|
||||
$(bPath).stopTime();
|
||||
});
|
||||
|
@ -623,8 +648,9 @@ var Roster = (function () {
|
|||
// Get the offset to define
|
||||
var offset = 3;
|
||||
|
||||
if(Common.isGateway(xid))
|
||||
if(Common.isGateway(xid)) {
|
||||
offset = -8;
|
||||
}
|
||||
|
||||
// Process the position
|
||||
var v_position = $(buddy).position().top + offset;
|
||||
|
@ -634,10 +660,11 @@ var Roster = (function () {
|
|||
$(buddy_infos).css('top', v_position);
|
||||
|
||||
// Apply the left/right position
|
||||
if($('html').attr('dir') == 'rtl')
|
||||
if($('html').attr('dir') == 'rtl') {
|
||||
$(buddy_infos).css('right', h_position);
|
||||
else
|
||||
} else {
|
||||
$(buddy_infos).css('left', h_position);
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Roster.buddyInfosPosition', e);
|
||||
}
|
||||
|
@ -659,14 +686,17 @@ var Roster = (function () {
|
|||
|
||||
// Each checked checkboxes
|
||||
$(path + 'div.bm-choose input[type="checkbox"]').filter(':checked').each(function() {
|
||||
array.push(unescape($(this).attr('data-group')));
|
||||
array.push(
|
||||
unescape($(this).attr('data-group'))
|
||||
);
|
||||
});
|
||||
|
||||
// Entered input value (and not yet in the array)
|
||||
var value = $.trim($(path + 'p.bm-group input').val());
|
||||
|
||||
if(value && !Utils.existArrayValue(array, value))
|
||||
if(value && !Utils.existArrayValue(array, value)) {
|
||||
array.push(value);
|
||||
}
|
||||
|
||||
return array;
|
||||
} catch(e) {
|
||||
|
@ -719,10 +749,13 @@ var Roster = (function () {
|
|||
var groups = [];
|
||||
|
||||
$('#roster .one-group').each(function() {
|
||||
var current = unescape($(this).attr('data-group'));
|
||||
var current = unescape(
|
||||
$(this).attr('data-group')
|
||||
);
|
||||
|
||||
if((current != Common._e("Unclassified")) && (current != Common._e("Gateways")))
|
||||
if((current != Common._e("Unclassified")) && (current != Common._e("Gateways"))) {
|
||||
groups.push(current);
|
||||
}
|
||||
});
|
||||
|
||||
return groups.sort();
|
||||
|
@ -757,8 +790,9 @@ var Roster = (function () {
|
|||
|
||||
// Get the group privacy state
|
||||
for(var g in groups) {
|
||||
if((Privacy.status('block', groups[g]) == 'deny') && (privacy_state != 'allow'))
|
||||
if((Privacy.status('block', groups[g]) == 'deny') && (privacy_state != 'allow')) {
|
||||
privacy_state = 'deny';
|
||||
}
|
||||
}
|
||||
|
||||
// The subscription with this buddy is not full
|
||||
|
@ -767,21 +801,24 @@ var Roster = (function () {
|
|||
html += '<p class="bm-authorize talk-images">';
|
||||
|
||||
// Link to allow to see our status
|
||||
if((subscription == 'to') || (subscription == 'none'))
|
||||
if((subscription == 'to') || (subscription == 'none')) {
|
||||
authorize_links += '<a href="#" class="to">' + Common._e("Authorize") + '</a>';
|
||||
}
|
||||
|
||||
// Link to ask to see his/her status
|
||||
if((subscription == 'from') || (subscription == 'none')) {
|
||||
if(authorize_links)
|
||||
if(authorize_links) {
|
||||
authorize_links += ' / ';
|
||||
}
|
||||
|
||||
authorize_links += '<a href="#" class="from">' + Common._e("Ask for authorization") + '</a>';
|
||||
}
|
||||
|
||||
// Link to unblock this buddy
|
||||
if((privacy_state == 'deny') && privacy_active) {
|
||||
if(authorize_links)
|
||||
if(authorize_links) {
|
||||
authorize_links += ' / ';
|
||||
}
|
||||
|
||||
html += '<a href="#" class="unblock">' + Common._e("Unblock") + '</a>';
|
||||
}
|
||||
|
@ -795,13 +832,15 @@ var Roster = (function () {
|
|||
remove_links = '<a href="#" class="remove">' + Common._e("Remove") + '</a>';
|
||||
|
||||
// This buddy is allowed to see our presence, we can show a "prohibit" link
|
||||
if((subscription == 'both') || (subscription == 'from'))
|
||||
if((subscription == 'both') || (subscription == 'from')) {
|
||||
remove_links += ' / <a href="#" class="prohibit">' + Common._e("Prohibit") + '</a>';
|
||||
}
|
||||
|
||||
// Complete the HTML code
|
||||
if((privacy_state != 'deny') && privacy_active) {
|
||||
if(remove_links)
|
||||
if(remove_links) {
|
||||
remove_links += ' / ';
|
||||
}
|
||||
|
||||
remove_links += '<a href="#" class="block">' + Common._e("Block") + '</a>';
|
||||
}
|
||||
|
@ -812,11 +851,12 @@ var Roster = (function () {
|
|||
'<p class="bm-rename talk-images"><label>' + Common._e("Rename") + '</label> <input type="text" value="' + Common.encodeQuotes(nick) + '" /></p>';
|
||||
|
||||
// Only show group tool if not a gateway
|
||||
if(!Common.isGateway(xid))
|
||||
if(!Common.isGateway(xid)) {
|
||||
html += '<p class="bm-group talk-images"><label>' + Common._e("Groups") + '</label> <input type="text" /></p>' +
|
||||
'<div class="bm-choose">' +
|
||||
'<div></div>' +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
// Close the DOM element
|
||||
html += '<a href="#" class="save">' + Common._e("Save") + '</a>' +
|
||||
|
@ -836,8 +876,9 @@ var Roster = (function () {
|
|||
// Is the current group checked?
|
||||
var checked = '';
|
||||
|
||||
if(Utils.existArrayValue(groups, all_groups_current))
|
||||
if(Utils.existArrayValue(groups, all_groups_current)) {
|
||||
checked = ' checked="true"';
|
||||
}
|
||||
|
||||
// Add the current group HTML
|
||||
all_groups_dom += '<label><input type="checkbox" data-group="' + escape(all_groups_current) + '"' + checked + ' /><span>' + all_groups_current.htmlEnc() + '</span></label>';
|
||||
|
@ -901,17 +942,20 @@ var Roster = (function () {
|
|||
var item = iqQuery.appendChild(iq.buildNode('item', {'xmlns': NS_ROSTER, 'jid': xid}));
|
||||
|
||||
// Any subscription?
|
||||
if(subscription)
|
||||
if(subscription) {
|
||||
item.setAttribute('subscription', subscription);
|
||||
}
|
||||
|
||||
// Any name?
|
||||
if(name)
|
||||
if(name) {
|
||||
item.setAttribute('name', name);
|
||||
}
|
||||
|
||||
// Any group?
|
||||
if(group && group.length) {
|
||||
for(var i in group)
|
||||
for(var i in group) {
|
||||
item.appendChild(iq.buildNode('group', {'xmlns': NS_ROSTER}, group[i]));
|
||||
}
|
||||
}
|
||||
|
||||
con.send(iq);
|
||||
|
@ -936,8 +980,9 @@ var Roster = (function () {
|
|||
var new_height = $('#left-content').height() - $('#my-infos').height() - 97;
|
||||
|
||||
// New height too small
|
||||
if(new_height < 211)
|
||||
if(new_height < 211) {
|
||||
new_height = 211;
|
||||
}
|
||||
|
||||
// Apply the new height
|
||||
$('#roster .content').css('height', new_height);
|
||||
|
@ -1034,10 +1079,11 @@ var Roster = (function () {
|
|||
|
||||
.blur(function() {
|
||||
// Nothing is entered, put the placeholder instead
|
||||
if(!$.trim($(this).val()))
|
||||
if(!$.trim($(this).val())) {
|
||||
aFilter.hide();
|
||||
else
|
||||
} else {
|
||||
aFilter.show();
|
||||
}
|
||||
})
|
||||
|
||||
.keyup(function(e) {
|
||||
|
@ -1062,8 +1108,9 @@ var Roster = (function () {
|
|||
// When the user click on the add button, show the contact adding tool
|
||||
$('#roster .foot .add').click(function() {
|
||||
// Yet displayed?
|
||||
if(Common.exists('#buddy-conf-add'))
|
||||
if(Common.exists('#buddy-conf-add')) {
|
||||
return Bubble.close();
|
||||
}
|
||||
|
||||
// Add the bubble
|
||||
Bubble.show('#buddy-conf-add');
|
||||
|
@ -1137,25 +1184,28 @@ var Roster = (function () {
|
|||
var gateway = unescape($('.add-contact-gateway').val());
|
||||
|
||||
// Generate the XID to add
|
||||
if((gateway != 'none') && xid)
|
||||
if((gateway != 'none') && xid) {
|
||||
xid = xid.replace(/@/g, '%') + '@' + gateway;
|
||||
else
|
||||
} else {
|
||||
xid = Common.generateXID(xid, 'chat');
|
||||
}
|
||||
|
||||
// Submit the form
|
||||
if(xid && Common.getXIDNick(xid) && (xid != Common.getXID()))
|
||||
if(xid && Common.getXIDNick(xid) && (xid != Common.getXID())) {
|
||||
self.addThisContact(xid, name);
|
||||
else
|
||||
} else {
|
||||
$(document).oneTime(10, function() {
|
||||
$('.add-contact-jid').addClass('please-complete').focus();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Escape : quit
|
||||
if(e.keyCode == 27)
|
||||
if(e.keyCode == 27) {
|
||||
Bubble.close();
|
||||
}
|
||||
});
|
||||
|
||||
// Click event on search link
|
||||
|
@ -1175,8 +1225,9 @@ var Roster = (function () {
|
|||
// When the user click on the join button, show the chat joining tool
|
||||
$('#roster .foot .join').click(function() {
|
||||
// Yet displayed?
|
||||
if(Common.exists('#buddy-conf-join'))
|
||||
if(Common.exists('#buddy-conf-join')) {
|
||||
return Bubble.close();
|
||||
}
|
||||
|
||||
// Add the bubble
|
||||
Bubble.show('#buddy-conf-join');
|
||||
|
@ -1209,10 +1260,7 @@ var Roster = (function () {
|
|||
// Select something from the search
|
||||
if(Common.exists(dHovered)) {
|
||||
Search.addBuddy(destination, $(dHovered).attr('data-xid'));
|
||||
}
|
||||
|
||||
// Join something
|
||||
else {
|
||||
} else {
|
||||
var xid = $.trim($('.join-jid').val());
|
||||
var type = $('.buddy-conf-join-select').val();
|
||||
|
||||
|
@ -1228,14 +1276,10 @@ var Roster = (function () {
|
|||
|
||||
// Create a new chat
|
||||
Chat.checkCreate(xid, type);
|
||||
}
|
||||
|
||||
else {
|
||||
} else {
|
||||
$('.join-jid').addClass('please-complete');
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
} else {
|
||||
$('.join-jid').addClass('please-complete');
|
||||
}
|
||||
}
|
||||
|
@ -1250,8 +1294,9 @@ var Roster = (function () {
|
|||
// Buddy search?
|
||||
else if($('.buddy-conf-join-select').val() == 'chat') {
|
||||
// New buddy search
|
||||
if((e.keyCode != 40) && (e.keyCode != 38))
|
||||
if((e.keyCode != 40) && (e.keyCode != 38)) {
|
||||
Search.createBuddy(destination);
|
||||
}
|
||||
|
||||
// Navigating with keyboard in the results
|
||||
Search.arrowsBuddy(e, destination);
|
||||
|
@ -1282,8 +1327,9 @@ var Roster = (function () {
|
|||
// When the user click on the groupchat button, show the groupchat menu
|
||||
$('#roster .foot .groupchat').click(function() {
|
||||
// Yet displayed?
|
||||
if(Common.exists('#buddy-conf-groupchat'))
|
||||
if(Common.exists('#buddy-conf-groupchat')) {
|
||||
return Bubble.close();
|
||||
}
|
||||
|
||||
// Add the bubble
|
||||
Bubble.show('#buddy-conf-groupchat');
|
||||
|
@ -1334,12 +1380,61 @@ var Roster = (function () {
|
|||
|
||||
return false;
|
||||
});
|
||||
|
||||
// When the user click on the muji button, show the muji menu
|
||||
$('#roster .foot .muji').click(function() {
|
||||
// Yet displayed?
|
||||
if(Common.exists('#buddy-conf-muji') || Call.is_ongoing()) {
|
||||
return Bubble.close();
|
||||
}
|
||||
|
||||
// Add the bubble
|
||||
Bubble.show('#buddy-conf-muji');
|
||||
|
||||
// Append the content
|
||||
$('#roster .roster-muji').append(
|
||||
'<div id="buddy-conf-muji" class="buddy-conf-item bubble removable">' +
|
||||
'<div class="buddy-conf-subarrow talk-images"></div>' +
|
||||
|
||||
'<div class="buddy-conf-subitem">' +
|
||||
'<p class="buddy-conf-p">' + Common._e("Launch a group call") + '</p>' +
|
||||
|
||||
'<p class="buddy-conf-text">' +
|
||||
'- <a href="#" class="buddy-conf-muji-conference" data-media="audio">' + Common._e("Audio conference") + '</a>' +
|
||||
'</p>' +
|
||||
|
||||
'<p class="buddy-conf-text">' +
|
||||
'- <a href="#" class="buddy-conf-muji-conference" data-media="video">' + Common._e("Video conference") + '</a>' +
|
||||
'</p>' +
|
||||
'</div>' +
|
||||
'</div>'
|
||||
);
|
||||
|
||||
// When the user wants to launch
|
||||
$('.buddy-conf-muji-conference').click(function() {
|
||||
var media = $(this).attr('data-media');
|
||||
|
||||
var room_name = hex_md5(media + DateUtils.getTimeStamp() + Math.random());
|
||||
var room = Common.generateXID(room_name, 'groupchat');
|
||||
|
||||
if(media && room && room_name) {
|
||||
Muji.start(room, media);
|
||||
}
|
||||
|
||||
Bubble.close();
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
// When the user click on the more button, show the more menu
|
||||
$('#roster .foot .more').click(function() {
|
||||
// Yet displayed?
|
||||
if(Common.exists('#buddy-conf-more'))
|
||||
if(Common.exists('#buddy-conf-more')) {
|
||||
return Bubble.close();
|
||||
}
|
||||
|
||||
// Add the bubble
|
||||
Bubble.show('#buddy-conf-more');
|
||||
|
@ -1410,11 +1505,13 @@ var Roster = (function () {
|
|||
$('.buddy-conf-more-display-available').show();
|
||||
}
|
||||
|
||||
if(Features.enabledCommands())
|
||||
if(Features.enabledCommands()) {
|
||||
$('.buddy-conf-more-commands').parent().show();
|
||||
}
|
||||
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'privacy-marker', 'available'))
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'privacy-marker', 'available')) {
|
||||
$('.buddy-conf-more-privacy').parent().show();
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
|
|
@ -97,34 +97,44 @@ var RosterX = (function () {
|
|||
|
||||
// Parse data
|
||||
x.find('item').each(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// Generate group XML
|
||||
var group = '';
|
||||
|
||||
$(this).find('group').each(function() {
|
||||
group += '<group>' + $(this).text().htmlEnc() + '</group>';
|
||||
this_sel.find('group').each(function() {
|
||||
group += '<group>' + this_sel.text().htmlEnc() + '</group>';
|
||||
});
|
||||
|
||||
if(group)
|
||||
if(group) {
|
||||
group = '<groups>' + group + '</groups>';
|
||||
}
|
||||
|
||||
// Display it!
|
||||
self.display($(this).attr('jid'), $(this).attr('name'), group, $(this).attr('action'));
|
||||
self.display(
|
||||
this_sel.attr('jid'),
|
||||
this_sel.attr('name'),
|
||||
group,
|
||||
this_sel.attr('action')
|
||||
);
|
||||
});
|
||||
|
||||
// Click to check/uncheck
|
||||
$('#rosterx .oneresult').click(function(evt) {
|
||||
// No need to apply when click on input
|
||||
if($(evt.target).is('input[type="checkbox"]'))
|
||||
if($(evt.target).is('input[type="checkbox"]')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Input selector
|
||||
var checkbox = $(this).find('input[type="checkbox"]');
|
||||
|
||||
// Check or uncheck?
|
||||
if(checkbox.filter(':checked').size())
|
||||
if(checkbox.filter(':checked').size()) {
|
||||
checkbox.removeAttr('checked');
|
||||
else
|
||||
} else {
|
||||
checkbox.attr('checked', true);
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('RosterX.parse', e);
|
||||
|
@ -146,16 +156,19 @@ var RosterX = (function () {
|
|||
|
||||
try {
|
||||
// End if no XID
|
||||
if(!xid)
|
||||
if(!xid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set up a default action if no one
|
||||
if(!action || (action != 'modify') || (action != 'delete'))
|
||||
if(!action || (action != 'modify') || (action != 'delete')) {
|
||||
action = 'add';
|
||||
}
|
||||
|
||||
// Override "undefined" for nickname
|
||||
if(!nick)
|
||||
if(!nick) {
|
||||
nick = '';
|
||||
}
|
||||
|
||||
// Display it
|
||||
$('#rosterx .results').append(
|
||||
|
@ -178,25 +191,27 @@ var RosterX = (function () {
|
|||
/**
|
||||
* Saves the rosterx settings
|
||||
* @public
|
||||
* @return {undefined}
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.save = function() {
|
||||
|
||||
try {
|
||||
// Send the requests
|
||||
$('#rosterx .results input[type="checkbox"]').filter(':checked').each(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// Read the attributes
|
||||
var nick = $(this).attr('data-name');
|
||||
var xid = $(this).attr('data-xid');
|
||||
var action = $(this).attr('data-action');
|
||||
var group = $(this).attr('data-group');
|
||||
var nick = this_sel.attr('data-name');
|
||||
var xid = this_sel.attr('data-xid');
|
||||
var action = this_sel.attr('data-action');
|
||||
var group = this_sel.attr('data-group');
|
||||
|
||||
// Parse groups XML
|
||||
var group_arr = [];
|
||||
|
||||
if(group) {
|
||||
$(group).find('group').each(function() {
|
||||
group_arr.push($(this).text().revertHtmlEnc());
|
||||
group_arr.push(this_sel.text().revertHtmlEnc());
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -233,6 +248,8 @@ var RosterX = (function () {
|
|||
self.close();
|
||||
} catch(e) {
|
||||
Console.error('RosterX.save', e);
|
||||
} finally {
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -248,17 +265,25 @@ var RosterX = (function () {
|
|||
try {
|
||||
// Click events
|
||||
$('#rosterx .bottom .finish').click(function() {
|
||||
if($(this).is('.save'))
|
||||
var this_sel = $(this);
|
||||
|
||||
if(this_sel.is('.save')) {
|
||||
return self.save();
|
||||
if($(this).is('.cancel'))
|
||||
}
|
||||
|
||||
if(this_sel.is('.cancel')) {
|
||||
return self.close();
|
||||
}
|
||||
});
|
||||
|
||||
$('#rosterx .rosterx-head a').click(function() {
|
||||
if($(this).is('.check'))
|
||||
var this_sel = $(this);
|
||||
|
||||
if(this_sel.is('.check')) {
|
||||
$('#rosterx .results input[type="checkbox"]').attr('checked', true);
|
||||
else if($(this).is('.uncheck'))
|
||||
} else if(this_sel.is('.uncheck')) {
|
||||
$('#rosterx .results input[type="checkbox"]').removeAttr('checked');
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
|
|
@ -112,8 +112,9 @@ var Search = (function () {
|
|||
// Get the old value (if there's another value)
|
||||
var old = '';
|
||||
|
||||
if(value.match(/(^(.+)(,)(\s)?)(\w+)$/))
|
||||
if(value.match(/(^(.+)(,)(\s)?)(\w+)$/)) {
|
||||
old = RegExp.$1;
|
||||
}
|
||||
|
||||
// Add the XID to the "to" input and focus on it
|
||||
$(document).oneTime(10, function() {
|
||||
|
@ -144,8 +145,9 @@ var Search = (function () {
|
|||
var value = $(destination + ' input').val();
|
||||
|
||||
// Separation with a comma?
|
||||
if(value.match(/^(.+)((,)(\s)?)(\w+)$/))
|
||||
if(value.match(/^(.+)((,)(\s)?)(\w+)$/)) {
|
||||
value = RegExp.$5;
|
||||
}
|
||||
|
||||
// Get the result array
|
||||
var entered = self.processBuddy(value);
|
||||
|
@ -217,8 +219,9 @@ var Search = (function () {
|
|||
var code = evt.keyCode;
|
||||
|
||||
// Not the key we want here
|
||||
if((code != 40) && (code != 38))
|
||||
if((code != 40) && (code != 38)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove the eventual mouse hover marker
|
||||
$(destination + ' ul').removeAttr('mouse-hover');
|
||||
|
@ -234,25 +237,25 @@ var Search = (function () {
|
|||
if(Common.exists(path + '.hovered')) {
|
||||
var index = $(path).attr('data-hovered');
|
||||
|
||||
if(index)
|
||||
if(index) {
|
||||
i = parseInt(index);
|
||||
}
|
||||
|
||||
if(code == 40)
|
||||
if(code == 40) {
|
||||
i++;
|
||||
else
|
||||
} else {
|
||||
i--;
|
||||
}
|
||||
} else if(code == 38) {
|
||||
i = pSize - 1;
|
||||
}
|
||||
|
||||
else if(code == 38)
|
||||
i = pSize - 1;
|
||||
|
||||
// We must not override the maximum i limit
|
||||
if(i >= pSize)
|
||||
if(i >= pSize) {
|
||||
i = 0;
|
||||
|
||||
// We must not have negative i
|
||||
else if(i < 0)
|
||||
} else if(i < 0) {
|
||||
i = pSize - 1;
|
||||
}
|
||||
|
||||
// Modify the list
|
||||
$(path + '.hovered').removeClass('hovered');
|
||||
|
@ -289,11 +292,13 @@ var Search = (function () {
|
|||
|
||||
// Only show the buddies which match the search
|
||||
if(!Roster.blist_all) {
|
||||
for(var i in rFilter)
|
||||
for(var i in rFilter) {
|
||||
$('#roster .buddy[data-xid="' + escape(rFilter[i]) + '"]:not(.hidden-buddy)').show();
|
||||
}
|
||||
} else {
|
||||
for(var j in rFilter)
|
||||
for(var j in rFilter) {
|
||||
$('#roster .buddy[data-xid="' + escape(rFilter[j]) + '"]').show();
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Search.goFilterBuddy', e);
|
||||
|
@ -317,8 +322,9 @@ var Search = (function () {
|
|||
$('#roster .buddy').show();
|
||||
|
||||
// Only show available buddies
|
||||
if(!Roster.blist_all)
|
||||
if(!Roster.blist_all) {
|
||||
$('#roster .buddy.hidden-buddy').hide();
|
||||
}
|
||||
|
||||
// Update the groups
|
||||
Roster.updateGroups();
|
||||
|
@ -349,15 +355,13 @@ var Search = (function () {
|
|||
|
||||
// Nothing is entered, or escape pressed
|
||||
if(!value || (keycode == 27)) {
|
||||
if(keycode == 27)
|
||||
if(keycode == 27) {
|
||||
input.val('');
|
||||
}
|
||||
|
||||
self.resetFilterBuddy();
|
||||
cancel.hide();
|
||||
}
|
||||
|
||||
// Process the filtering
|
||||
else {
|
||||
} else {
|
||||
cancel.show();
|
||||
self.goFilterBuddy(value);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,51 @@ var Smileys = (function () {
|
|||
var self = {};
|
||||
|
||||
|
||||
/* Constants */
|
||||
self.emote_list = {
|
||||
'biggrin': ':-D',
|
||||
'devil': ']:->',
|
||||
'coolglasses': '8-)',
|
||||
'tongue': ':-P',
|
||||
'smile': ':-)',
|
||||
'wink': ';-)',
|
||||
'blush': ':-$',
|
||||
'stare': ':-|',
|
||||
'frowning': ':-/',
|
||||
'oh': '=-O',
|
||||
'unhappy': ':-(',
|
||||
'cry': ':\'-(',
|
||||
'angry': ':-@',
|
||||
'puke': ':-!',
|
||||
'hugright': '({)',
|
||||
'hugleft': '(})',
|
||||
'lion': ':3',
|
||||
'pussy': '(@)',
|
||||
'bat': ':-[',
|
||||
'kiss': ':-{}',
|
||||
'heart': '<3',
|
||||
'brheart': '</3',
|
||||
'flower': '@}->--',
|
||||
'brflower': '(W)',
|
||||
'thumbup': '(Y)',
|
||||
'thumbdown': '(N)',
|
||||
'lamp': '(I)',
|
||||
'coffee': '(C)',
|
||||
'drink': '(D)',
|
||||
'beer': '(B)',
|
||||
'boy': '(Z)',
|
||||
'girl': '(X)',
|
||||
'photo': '(P)',
|
||||
'phone': '(T)',
|
||||
'music': '(8)',
|
||||
'cuffs': '(%)',
|
||||
'mail': '(E)',
|
||||
'rainbow': '(R)',
|
||||
'star': '(*)',
|
||||
'moon': '(S)'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Generates the correct HTML code for an emoticon insertion tool
|
||||
* @public
|
||||
|
@ -43,101 +88,19 @@ var Smileys = (function () {
|
|||
* Emoticon links arrays
|
||||
* @public
|
||||
* @param {string} hash
|
||||
* @return {object}
|
||||
* @return {string}
|
||||
*/
|
||||
self.links = function(hash) {
|
||||
|
||||
try {
|
||||
var links = '';
|
||||
|
||||
var sArray = [
|
||||
':-D',
|
||||
']:->',
|
||||
'8-)',
|
||||
':-P',
|
||||
':-)',
|
||||
';-)',
|
||||
':-$',
|
||||
':-|',
|
||||
':-/',
|
||||
'=-O',
|
||||
':-(',
|
||||
':\'-(',
|
||||
':-@',
|
||||
':-!',
|
||||
'({)',
|
||||
'(})',
|
||||
':3',
|
||||
'(@)',
|
||||
':-[',
|
||||
':-{}',
|
||||
'<3',
|
||||
'</3',
|
||||
'@}->--',
|
||||
'(W)',
|
||||
'(Y)',
|
||||
'(N)',
|
||||
'(I)',
|
||||
'(C)',
|
||||
'(D)',
|
||||
'(B)',
|
||||
'(Z)',
|
||||
'(X)',
|
||||
'(P)',
|
||||
'(T)',
|
||||
'(8)',
|
||||
'(%)',
|
||||
'(E)',
|
||||
'(R)',
|
||||
'(*)',
|
||||
'(S)'
|
||||
];
|
||||
|
||||
var cArray = [
|
||||
'biggrin',
|
||||
'devil',
|
||||
'coolglasses',
|
||||
'tongue',
|
||||
'smile',
|
||||
'wink',
|
||||
'blush',
|
||||
'stare',
|
||||
'frowning',
|
||||
'oh',
|
||||
'unhappy',
|
||||
'cry',
|
||||
'angry',
|
||||
'puke',
|
||||
'hugright',
|
||||
'hugleft',
|
||||
'lion',
|
||||
'pussy',
|
||||
'bat',
|
||||
'kiss',
|
||||
'heart',
|
||||
'brheart',
|
||||
'flower',
|
||||
'brflower',
|
||||
'thumbup',
|
||||
'thumbdown',
|
||||
'lamp',
|
||||
'coffee',
|
||||
'drink',
|
||||
'beer',
|
||||
'boy',
|
||||
'girl',
|
||||
'photo',
|
||||
'phone',
|
||||
'music',
|
||||
'cuffs',
|
||||
'mail',
|
||||
'rainbow',
|
||||
'star',
|
||||
'moon'
|
||||
];
|
||||
|
||||
for(var i in sArray) {
|
||||
links += self.emoteLink(sArray[i], cArray[i], hash);
|
||||
|
||||
for(var cur_emote in self.emote_list) {
|
||||
links += self.emoteLink(
|
||||
self.emote_list[cur_emote],
|
||||
cur_emote,
|
||||
hash
|
||||
);
|
||||
}
|
||||
|
||||
return links;
|
||||
|
|
|
@ -70,44 +70,51 @@ var Storage = (function () {
|
|||
|
||||
// Parse the options xml
|
||||
options.find('option').each(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// We retrieve the informations
|
||||
var type = $(this).attr('type');
|
||||
var value = $(this).text();
|
||||
var type = this_sel.attr('type');
|
||||
var value = this_sel.text();
|
||||
|
||||
// We display the storage
|
||||
DataStore.setDB(Connection.desktop_hash, 'options', type, value);
|
||||
|
||||
// If this is the buddy list show status
|
||||
if((type == 'roster-showall') && (value == '1'))
|
||||
if((type == 'roster-showall') && (value == '1')) {
|
||||
Interface.showAllBuddies('storage');
|
||||
}
|
||||
});
|
||||
|
||||
// Parse the inbox xml
|
||||
inbox.find('message').each(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
Inbox.storeMessage(
|
||||
$(this).attr('from'),
|
||||
$(this).attr('subject'),
|
||||
$(this).text(),
|
||||
$(this).attr('status'),
|
||||
$(this).attr('id'),
|
||||
$(this).attr('date'),
|
||||
[
|
||||
$(this).attr('file_title'),
|
||||
$(this).attr('file_href'),
|
||||
$(this).attr('file_type'),
|
||||
$(this).attr('file_length')
|
||||
]
|
||||
);
|
||||
this_sel.attr('from'),
|
||||
this_sel.attr('subject'),
|
||||
this_sel.text(),
|
||||
this_sel.attr('status'),
|
||||
this_sel.attr('id'),
|
||||
this_sel.attr('date'),
|
||||
[
|
||||
this_sel.attr('file_title'),
|
||||
this_sel.attr('file_href'),
|
||||
this_sel.attr('file_type'),
|
||||
this_sel.attr('file_length')
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
// Parse the bookmarks xml
|
||||
bookmarks.find('conference').each(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// We retrieve the informations
|
||||
var xid = $(this).attr('jid');
|
||||
var name = $(this).attr('name');
|
||||
var autojoin = $(this).attr('autojoin');
|
||||
var password = $(this).find('password').text();
|
||||
var nick = $(this).find('nick').text();
|
||||
var xid = this_sel.attr('jid');
|
||||
var name = this_sel.attr('name');
|
||||
var autojoin = this_sel.attr('autojoin');
|
||||
var password = this_sel.find('password').text();
|
||||
var nick = this_sel.find('nick').text();
|
||||
|
||||
// Filter autojoin (compatibility)
|
||||
autojoin = ((autojoin == 'true') || (autojoin == '1')) ? 'true' : 'false';
|
||||
|
@ -116,13 +123,21 @@ var Storage = (function () {
|
|||
Favorites.display(xid, name, nick, autojoin, password);
|
||||
|
||||
// Join the chat if autojoin is enabled
|
||||
if(autojoin == 'true')
|
||||
if(autojoin == 'true') {
|
||||
Chat.checkCreate(xid, 'groupchat', nick, password, name);
|
||||
}
|
||||
});
|
||||
|
||||
// Parse the roster notes xml
|
||||
rosternotes.find('note').each(function() {
|
||||
DataStore.setDB(Connection.desktop_hash, 'rosternotes', $(this).attr('jid'), $(this).text());
|
||||
var this_sel = $(this);
|
||||
|
||||
DataStore.setDB(
|
||||
Connection.desktop_hash,
|
||||
'rosternotes',
|
||||
this_sel.attr('jid'),
|
||||
this_sel.text()
|
||||
);
|
||||
});
|
||||
|
||||
// Options received
|
||||
|
|
|
@ -31,14 +31,18 @@ var System = (function () {
|
|||
var url = window.location.href;
|
||||
|
||||
// If the URL has variables, remove them
|
||||
if(url.indexOf('?') != -1)
|
||||
if(url.indexOf('?') != -1) {
|
||||
url = url.split('?')[0];
|
||||
if(url.indexOf('#') != -1)
|
||||
}
|
||||
|
||||
if(url.indexOf('#') != -1) {
|
||||
url = url.split('#')[0];
|
||||
}
|
||||
|
||||
// No "/" at the end
|
||||
if(!url.match(/(.+)\/$/))
|
||||
if(!url.match(/(.+)\/$/)) {
|
||||
url += '/';
|
||||
}
|
||||
|
||||
return url;
|
||||
} catch(e) {
|
||||
|
|
|
@ -51,8 +51,9 @@ var Talk = (function () {
|
|||
|
||||
try {
|
||||
// Talkpage exists?
|
||||
if(Common.exists('#talk'))
|
||||
if(Common.exists('#talk')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Anonymous detector
|
||||
var anonymous = Utils.isAnonymous();
|
||||
|
@ -116,14 +117,14 @@ var Talk = (function () {
|
|||
|
||||
if(!anonymous) html +=
|
||||
'<div class="tools-all">' +
|
||||
'<div class="tools jingle talk-images" onclick="return Jingle.open();">' +
|
||||
'<div class="tools call talk-images" onclick="return Call.open();">' +
|
||||
'<span class="streaming-items">' +
|
||||
'<span class="counter" data-default="00:00:00">00:00:00</span>' +
|
||||
'<a class="stop" href="#" onclick="return Jingle.stop();">' + Common._e("Stop") + '</a>' +
|
||||
'<a class="stop" href="#" onclick="return Call.stop();">' + Common._e("Stop") + '</a>' +
|
||||
'</span>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="jingle-content tools-content">' +
|
||||
'<div class="call-content tools-content">' +
|
||||
'<div class="tools-content-subarrow talk-images"></div>' +
|
||||
|
||||
'<div class="tools-content-subitem"></div>' +
|
||||
|
@ -157,6 +158,10 @@ var Talk = (function () {
|
|||
'<a href="#" class="groupchat talk-images" title="' + Common._e("Your groupchats") + '"></a>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="roster-muji roster-icon muji-hidable">' +
|
||||
'<a href="#" class="muji talk-images" title="' + Common._e("Audio/video conference") + '"></a>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="roster-more roster-icon">' +
|
||||
'<a href="#" class="more talk-images" title="' + Common._e("More stuff") + '"></a>' +
|
||||
'</div>' +
|
||||
|
|
|
@ -37,8 +37,9 @@ var Tooltip = (function () {
|
|||
var path_bubble = path_tooltip + ' .bubble-' + type;
|
||||
|
||||
// Yet exists?
|
||||
if(Common.exists(path_bubble))
|
||||
if(Common.exists(path_bubble)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Generates special tooltip HTML code
|
||||
var title = '';
|
||||
|
@ -211,47 +212,52 @@ var Tooltip = (function () {
|
|||
// Click event on style bubble
|
||||
$(bubble_style).click(function() {
|
||||
// Hide font selector if opened
|
||||
if($(font_list).is(':visible'))
|
||||
if($(font_list).is(':visible')) {
|
||||
$(font_current).click();
|
||||
}
|
||||
|
||||
// Hide font-size selector if opened
|
||||
if($(fontsize_list).is(':visible'))
|
||||
if($(fontsize_list).is(':visible')) {
|
||||
$(fontsize_current).click();
|
||||
}
|
||||
|
||||
// Hide color selector if opened
|
||||
if($(color_hex).is(':visible'))
|
||||
if($(color_hex).is(':visible')) {
|
||||
$(color_more).click();
|
||||
}
|
||||
});
|
||||
|
||||
// Click event on font picker
|
||||
$(font_current).click(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// The clicked color is yet selected
|
||||
if($(font_list).is(':visible'))
|
||||
$(this).parent().removeClass('listed');
|
||||
else
|
||||
$(this).parent().addClass('listed');
|
||||
if($(font_list).is(':visible')) {
|
||||
this_sel.parent().removeClass('listed');
|
||||
} else {
|
||||
this_sel.parent().addClass('listed');
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
// Click event on a new font in the picker
|
||||
$(font_select).click(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// No font selected
|
||||
if(!$(this).attr('data-value')) {
|
||||
if(!this_sel.attr('data-value')) {
|
||||
$(font_current).removeAttr('data-font')
|
||||
.removeAttr('data-value')
|
||||
.text(Common._e("None"));
|
||||
|
||||
$(message_area).removeAttr('data-font');
|
||||
}
|
||||
|
||||
// A font is defined
|
||||
else {
|
||||
$(font_current).attr('data-font', $(this).attr('data-font'))
|
||||
.attr('data-value', $(this).attr('data-value'))
|
||||
.text($(font_list).find('a[data-value="' + $(this).attr('data-value') + '"]').text());
|
||||
} else {
|
||||
$(font_current).attr('data-font', this_sel.attr('data-font'))
|
||||
.attr('data-value', this_sel.attr('data-value'))
|
||||
.text($(font_list).find('a[data-value="' + this_sel.attr('data-value') + '"]').text());
|
||||
|
||||
$(message_area).attr('data-font', $(this).attr('data-value'));
|
||||
$(message_area).attr('data-font', this_sel.attr('data-value'));
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -259,28 +265,33 @@ var Tooltip = (function () {
|
|||
|
||||
// Click event on font-size picker
|
||||
$(fontsize_current).click(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// The clicked color is yet selected
|
||||
if($(fontsize_list).is(':visible'))
|
||||
$(this).parent().removeClass('listed');
|
||||
else
|
||||
$(this).parent().addClass('listed');
|
||||
if($(fontsize_list).is(':visible')) {
|
||||
this_sel.parent().removeClass('listed');
|
||||
} else {
|
||||
this_sel.parent().addClass('listed');
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
// Click event on a new font-size in the picker
|
||||
$(fontsize_select).click(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// No font-size selected
|
||||
if(!$(this).attr('data-value')) {
|
||||
if(!this_sel.attr('data-value')) {
|
||||
$(fontsize_current).removeAttr('data-value').text(Common._e("16"));
|
||||
$(message_area).removeAttr('data-fontsize');
|
||||
}
|
||||
|
||||
// A font-size is defined
|
||||
else {
|
||||
$(fontsize_current).attr('data-value', $(this).attr('data-value'))
|
||||
.text($(this).attr('data-value'));
|
||||
$(message_area).attr('data-fontsize', $(this).attr('data-value'));
|
||||
$(fontsize_current).attr('data-value', this_sel.attr('data-value'))
|
||||
.text(this_sel.attr('data-value'));
|
||||
$(message_area).attr('data-fontsize', this_sel.attr('data-value'));
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -288,19 +299,21 @@ var Tooltip = (function () {
|
|||
|
||||
// Click event on color picker
|
||||
$(colors).click(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// Reset the manual picker
|
||||
$(color_hex).find('input').val('');
|
||||
|
||||
// The clicked color is yet selected
|
||||
if($(this).hasClass('selected')) {
|
||||
if(this_sel.hasClass('selected')) {
|
||||
$(message_area).removeAttr('data-color');
|
||||
$(this).removeClass('selected');
|
||||
this_sel.removeClass('selected');
|
||||
}
|
||||
|
||||
else {
|
||||
$(message_area).attr('data-color', $(this).attr('data-color'));
|
||||
$(message_area).attr('data-color', this_sel.attr('data-color'));
|
||||
$(colors).removeClass('selected');
|
||||
$(this).addClass('selected');
|
||||
this_sel.addClass('selected');
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -308,12 +321,13 @@ var Tooltip = (function () {
|
|||
|
||||
// Click event on color picker
|
||||
$(color_more).click(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// The clicked color is yet selected
|
||||
if($(color_hex).is(':visible'))
|
||||
$(this).parent().removeClass('opened');
|
||||
|
||||
else {
|
||||
$(this).parent().addClass('opened');
|
||||
if($(color_hex).is(':visible')) {
|
||||
this_sel.parent().removeClass('opened');
|
||||
} else {
|
||||
this_sel.parent().addClass('opened');
|
||||
|
||||
// Focus
|
||||
$(document).oneTime(10, function() {
|
||||
|
@ -331,6 +345,8 @@ var Tooltip = (function () {
|
|||
|
||||
// Keyup event on color picker
|
||||
$(color_hex).find('input').keyup(function(e) {
|
||||
var this_sel = $(this);
|
||||
|
||||
// Submit
|
||||
if(e.keyCode == 13) {
|
||||
if($(color_hex).is(':visible')) {
|
||||
|
@ -350,32 +366,37 @@ var Tooltip = (function () {
|
|||
$(colors).removeClass('selected');
|
||||
|
||||
// Change value
|
||||
var new_value = $(this).val().replace(/([^a-z0-9]+)/gi, '');
|
||||
$(this).val(new_value);
|
||||
var new_value = this_sel.val().replace(/([^a-z0-9]+)/gi, '');
|
||||
this_sel.val(new_value);
|
||||
|
||||
if(new_value)
|
||||
if(new_value) {
|
||||
$(message_area).attr('data-color', new_value);
|
||||
}
|
||||
|
||||
// Regenerate style
|
||||
var style = Message.generateStyle(hash);
|
||||
|
||||
// Any style to apply?
|
||||
if(style)
|
||||
if(style) {
|
||||
$(message_area).attr('style', style);
|
||||
else
|
||||
} else {
|
||||
$(message_area).removeAttr('style');
|
||||
}
|
||||
}).placeholder();
|
||||
|
||||
// Change event on text style checkboxes
|
||||
$(style).change(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// Get current type
|
||||
var style_data = 'data-' + $(this).attr('class');
|
||||
var style_data = 'data-' + this_sel.attr('class');
|
||||
|
||||
// Checked checkbox?
|
||||
if($(this).filter(':checked').size())
|
||||
if(this_sel.filter(':checked').size()) {
|
||||
$(message_area).attr(style_data, true);
|
||||
else
|
||||
} else {
|
||||
$(message_area).removeAttr(style_data);
|
||||
}
|
||||
});
|
||||
|
||||
// Update the textarea style when it is changed
|
||||
|
@ -383,10 +404,11 @@ var Tooltip = (function () {
|
|||
var style = Message.generateStyle(hash);
|
||||
|
||||
// Any style to apply?
|
||||
if(style)
|
||||
if(style) {
|
||||
$(message_area).attr('style', style);
|
||||
else
|
||||
} else {
|
||||
$(message_area).removeAttr('style');
|
||||
}
|
||||
|
||||
// Focus again on the message textarea
|
||||
$(document).oneTime(10, function() {
|
||||
|
@ -410,24 +432,31 @@ var Tooltip = (function () {
|
|||
|
||||
// Upload form submit event
|
||||
$(path_tooltip + ' #oob-upload').submit(function() {
|
||||
if($(path_tooltip + ' #oob-upload input[type="file"]').val())
|
||||
$(this).ajaxSubmit(oob_upload_options);
|
||||
var this_sel = $(this);
|
||||
|
||||
if($(path_tooltip + ' #oob-upload input[type="file"]').val()) {
|
||||
this_sel.ajaxSubmit(oob_upload_options);
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
// Upload input change event
|
||||
$(path_tooltip + ' #oob-upload input[type="file"]').change(function() {
|
||||
if($(this).val())
|
||||
var this_sel = $(this);
|
||||
|
||||
if(this_sel.val()) {
|
||||
$(path_tooltip + ' #oob-upload').ajaxSubmit(oob_upload_options);
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
// Input click event
|
||||
$(path_tooltip + ' #oob-upload input[type="file"], ' + path_tooltip + ' #oob-upload input[type="submit"]').click(function() {
|
||||
if(Common.exists(path_tooltip + ' #oob-upload input[type="reset"]'))
|
||||
if(Common.exists(path_tooltip + ' #oob-upload input[type="reset"]')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Lock the bubble
|
||||
$(path_bubble).addClass('locked');
|
||||
|
@ -569,17 +598,21 @@ var Tooltip = (function () {
|
|||
|
||||
// Apply the options to the style selector
|
||||
$(bubble_style + ' input[type="checkbox"]').each(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// Current input enabled?
|
||||
if(message_area.attr('data-' + $(this).attr('class')))
|
||||
$(this).attr('checked', true);
|
||||
if(message_area.attr('data-' + this_sel.attr('class'))) {
|
||||
this_sel.attr('checked', true);
|
||||
}
|
||||
});
|
||||
|
||||
// Apply message color
|
||||
if(color) {
|
||||
if($(bubble_style + ' a.color[data-color="' + color + '"]').size())
|
||||
if($(bubble_style + ' a.color[data-color="' + color + '"]').size()) {
|
||||
$(bubble_style + ' a.color[data-color="' + color + '"]').addClass('selected');
|
||||
else
|
||||
} else {
|
||||
$(bubble_style + ' div.color-hex input.hex-value').val(color);
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Tooltip.loadStyleSelector', e);
|
||||
|
|
|
@ -298,8 +298,9 @@ var UserInfos = (function () {
|
|||
var path = '#userinfos[data-last="' + id + '"]';
|
||||
|
||||
// End if session does not exist
|
||||
if(!Common.exists(path))
|
||||
if(!Common.exists(path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(iq && (iq.getType() == 'result')) {
|
||||
// Get the values
|
||||
|
@ -313,8 +314,9 @@ var UserInfos = (function () {
|
|||
seconds = parseInt(seconds);
|
||||
|
||||
// Active user
|
||||
if(seconds <= 60)
|
||||
if(seconds <= 60) {
|
||||
last = Common._e("User currently active");
|
||||
}
|
||||
|
||||
// Inactive user
|
||||
else {
|
||||
|
@ -325,12 +327,14 @@ var UserInfos = (function () {
|
|||
var date = date_last.toLocaleString();
|
||||
|
||||
// Offline user
|
||||
if(from.indexOf('/') == -1)
|
||||
if(from.indexOf('/') == -1) {
|
||||
last = Common.printf(Common._e("Last seen: %s"), date);
|
||||
}
|
||||
|
||||
// Online user
|
||||
else
|
||||
else {
|
||||
last = Common.printf(Common._e("Inactive since: %s"), date);
|
||||
}
|
||||
}
|
||||
|
||||
// Append this text
|
||||
|
@ -363,8 +367,9 @@ var UserInfos = (function () {
|
|||
var path = '#userinfos[data-version="' + id + '"]';
|
||||
|
||||
// End if session does not exist
|
||||
if(!Common.exists(path))
|
||||
if(!Common.exists(path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Extract the reply data
|
||||
if(iq && (iq.getType() == 'result')) {
|
||||
|
@ -375,14 +380,18 @@ var UserInfos = (function () {
|
|||
var os = $(xml).find('os').text();
|
||||
|
||||
// Put the values together
|
||||
if(name && version)
|
||||
if(name && version) {
|
||||
name = name + ' ' + version;
|
||||
}
|
||||
|
||||
// Display the values
|
||||
if(name)
|
||||
if(name) {
|
||||
$(path + ' #BUDDY-CLIENT').text(name);
|
||||
if(os)
|
||||
}
|
||||
|
||||
if(os) {
|
||||
$(path + ' #BUDDY-SYSTEM').text(os);
|
||||
}
|
||||
|
||||
Console.log('Software version received: ' + Common.fullXID(Common.getStanzaFrom(iq)));
|
||||
}
|
||||
|
@ -410,8 +419,9 @@ var UserInfos = (function () {
|
|||
var path = '#userinfos[data-time="' + id + '"]';
|
||||
|
||||
// End if session does not exist
|
||||
if(!Common.exists(path))
|
||||
if(!Common.exists(path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(iq && (iq.getType() == 'result')) {
|
||||
// Get the values
|
||||
|
@ -422,8 +432,9 @@ var UserInfos = (function () {
|
|||
// Any UTC?
|
||||
if(utc) {
|
||||
// Add the TZO if there's no one
|
||||
if(tzo && utc.match(/^(.+)Z$/))
|
||||
if(tzo && utc.match(/^(.+)Z$/)) {
|
||||
utc = RegExp.$1 + tzo;
|
||||
}
|
||||
|
||||
// Get the local date string
|
||||
var local_string = Date.hrTime(utc);
|
||||
|
@ -454,8 +465,9 @@ var UserInfos = (function () {
|
|||
try {
|
||||
var selector = $('#userinfos .content');
|
||||
|
||||
if(!selector.hasClass('vcard') && !selector.hasClass('last') && !selector.hasClass('version') && !selector.hasClass('time'))
|
||||
if(!selector.hasClass('vcard') && !selector.hasClass('last') && !selector.hasClass('version') && !selector.hasClass('time')) {
|
||||
$('#userinfos .wait').hide();
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('UserInfos.wait', e);
|
||||
}
|
||||
|
@ -478,8 +490,9 @@ var UserInfos = (function () {
|
|||
// Necessary to update?
|
||||
var old_value = DataStore.getDB(Connection.desktop_hash, 'rosternotes', xid);
|
||||
|
||||
if((old_value == value) || (!old_value && !value))
|
||||
if((old_value == value) || (!old_value && !value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Update the database
|
||||
DataStore.setDB(Connection.desktop_hash, 'rosternotes', xid, value);
|
||||
|
@ -502,8 +515,9 @@ var UserInfos = (function () {
|
|||
var cur_xid = RegExp.$1;
|
||||
var cur_value = DataStore.storageDB.getItem(current);
|
||||
|
||||
if(cur_xid && cur_value)
|
||||
if(cur_xid && cur_value) {
|
||||
storage.appendChild(iq.buildNode('note', {'jid': cur_xid, 'xmlns': NS_ROSTERNOTES}, cur_value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -526,10 +540,15 @@ var UserInfos = (function () {
|
|||
self.switchTab = function(id) {
|
||||
|
||||
try {
|
||||
$('#userinfos .content .one-lap').hide();
|
||||
$('#userinfos .content .info' + id).show();
|
||||
$('#userinfos .tab a').removeClass('tab-active');
|
||||
$('#userinfos .tab a[data-key="' + id + '"]').addClass('tab-active');
|
||||
var userinfos_sel = $('#userinfos');
|
||||
var content_sel = userinfos_sel.find('.content');
|
||||
var tab_link_sel = userinfos_sel.find('.tab a');
|
||||
|
||||
content_sel.find('.one-lap').hide();
|
||||
content_sel.find('.info' + id).show();
|
||||
|
||||
tab_link_sel.removeClass('tab-active');
|
||||
tab_link_sel.filter('[data-key="' + id + '"]').addClass('tab-active');
|
||||
} catch(e) {
|
||||
Console.error('UserInfos.switchTab', e);
|
||||
} finally {
|
||||
|
@ -582,12 +601,15 @@ var UserInfos = (function () {
|
|||
try {
|
||||
// Click events
|
||||
$('#userinfos .tab a').click(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// Yet active?
|
||||
if($(this).hasClass('tab-active'))
|
||||
if(this_sel.hasClass('tab-active')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Switch to the good tab
|
||||
var key = parseInt($(this).attr('data-key'));
|
||||
var key = parseInt(this_sel.attr('data-key'));
|
||||
|
||||
return self.switchTab(key);
|
||||
});
|
||||
|
|
|
@ -52,8 +52,9 @@ var Utils = (function () {
|
|||
|
||||
try {
|
||||
// HTTPS not allowed
|
||||
if((HTTPS_STORAGE != 'on') && url.match(/^https(.+)/))
|
||||
if((HTTPS_STORAGE != 'on') && url.match(/^https(.+)/)) {
|
||||
url = 'http' + RegExp.$1;
|
||||
}
|
||||
|
||||
return url;
|
||||
} catch(e) {
|
||||
|
@ -217,28 +218,34 @@ var Utils = (function () {
|
|||
var browser_version = BrowserDetect.version;
|
||||
|
||||
// No DOM storage
|
||||
if(!DataStore.hasDB() || !DataStore.hasPersistent())
|
||||
if(!DataStore.hasDB() || !DataStore.hasPersistent()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Obsolete IE
|
||||
if((browser_name == 'Explorer') && (browser_version < 8))
|
||||
if((browser_name == 'Explorer') && (browser_version < 8)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Obsolete Chrome
|
||||
if((browser_name == 'Chrome') && (browser_version < 7))
|
||||
if((browser_name == 'Chrome') && (browser_version < 7)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Obsolete Safari
|
||||
if((browser_name == 'Safari') && (browser_version < 4))
|
||||
if((browser_name == 'Safari') && (browser_version < 4)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Obsolete Firefox
|
||||
if((browser_name == 'Firefox') && (browser_version < 3.5))
|
||||
if((browser_name == 'Firefox') && (browser_version < 3.5)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Obsolete Opera
|
||||
if((browser_name == 'Opera') && (browser_version < 9))
|
||||
if((browser_name == 'Opera') && (browser_version < 9)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
} catch(e) {
|
||||
|
@ -585,6 +592,33 @@ var Utils = (function () {
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes duplicate values from array
|
||||
* @public
|
||||
* @param {object} arr
|
||||
* @return {object}
|
||||
*/
|
||||
self.uniqueArrayValues = function(arr) {
|
||||
|
||||
try {
|
||||
var a = arr.concat();
|
||||
|
||||
for(var i = 0; i < a.length; ++i) {
|
||||
for(var j = i + 1; j < a.length; ++j) {
|
||||
if(a[i] === a[j]) {
|
||||
a.splice(j--, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return a;
|
||||
} catch(e) {
|
||||
Console.error('Utils.uniqueArrayValues', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts a string to an array
|
||||
* @public
|
||||
|
@ -603,10 +637,11 @@ var Utils = (function () {
|
|||
var string_split = string.split(',');
|
||||
|
||||
for(var i in string_split) {
|
||||
if(string_split[i])
|
||||
if(string_split[i]) {
|
||||
array.push(string_split[i]);
|
||||
else
|
||||
} else {
|
||||
array.push('');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -634,8 +669,9 @@ var Utils = (function () {
|
|||
|
||||
try {
|
||||
// Nothing?
|
||||
if(!array || !array.length)
|
||||
if(!array || !array.length) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Read the index of the value
|
||||
var index = 0;
|
||||
|
|
|
@ -272,7 +272,7 @@ var vCard = (function () {
|
|||
$('#USER-PHOTO-TYPE').val(aType);
|
||||
$('#USER-PHOTO-BINVAL').val(aBinval);
|
||||
|
||||
// We display the avatar !
|
||||
// We display the avatar!
|
||||
$('#vcard .avatar-container').replaceWith('<div class="avatar-container"><img class="avatar" src="data:' + aType + ';base64,' + aBinval + '" alt="" /></div>');
|
||||
}
|
||||
|
||||
|
@ -374,9 +374,7 @@ var vCard = (function () {
|
|||
|
||||
// Send the IQ
|
||||
con.send(iq, self.handleUser);
|
||||
}
|
||||
|
||||
else {
|
||||
} else {
|
||||
// Show the wait icon
|
||||
$('#userinfos .wait').show();
|
||||
|
||||
|
@ -456,12 +454,14 @@ var vCard = (function () {
|
|||
var values_yet = [];
|
||||
|
||||
$(iqNode).find('vCard').children().each(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// Read the current parent node name
|
||||
var tokenname = (this).nodeName.toUpperCase();
|
||||
|
||||
// Node with a parent
|
||||
if($(this).children().size()) {
|
||||
$(this).children().each(function() {
|
||||
if(this_sel.children().size()) {
|
||||
this_sel.children().each(function() {
|
||||
// Get the node values
|
||||
var currentID = tokenname + '-' + (this).nodeName.toUpperCase();
|
||||
var currentText = $(this).text();
|
||||
|
@ -473,10 +473,11 @@ var vCard = (function () {
|
|||
|
||||
// Userinfos viewer popup
|
||||
if((type == 'buddy') && currentText) {
|
||||
if(currentID == 'EMAIL-USERID')
|
||||
if(currentID == 'EMAIL-USERID') {
|
||||
$(path_userInfos + ' #BUDDY-' + currentID).html('<a href="mailto:' + currentText.htmlEnc() + '" target="_blank">' + currentText.htmlEnc() + '</a>');
|
||||
else
|
||||
} else {
|
||||
$(path_userInfos + ' #BUDDY-' + currentID).text(currentText.htmlEnc());
|
||||
}
|
||||
}
|
||||
|
||||
// Profile editor popup
|
||||
|
@ -505,8 +506,9 @@ var vCard = (function () {
|
|||
// URL modification
|
||||
if(tokenname == 'URL') {
|
||||
// No http:// or https:// prefix, we should add it
|
||||
if(!currentText.match(/^https?:\/\/(.+)/))
|
||||
if(!currentText.match(/^https?:\/\/(.+)/)) {
|
||||
currentText = 'http://' + currentText;
|
||||
}
|
||||
|
||||
currentText = '<a href="' + currentText + '" target="_blank">' + currentText.htmlEnc() + '</a>';
|
||||
}
|
||||
|
@ -525,8 +527,9 @@ var vCard = (function () {
|
|||
}
|
||||
|
||||
// Profile editor popup
|
||||
else if(type == 'user')
|
||||
else if(type == 'user') {
|
||||
$(path_vcard + ' #USER-' + tokenname).val(currentText);
|
||||
}
|
||||
|
||||
// Avoid duplicating the value
|
||||
values_yet.push(tokenname);
|
||||
|
@ -556,9 +559,7 @@ var vCard = (function () {
|
|||
aBinval = $('#USER-PHOTO-BINVAL').val();
|
||||
aType = $('#USER-PHOTO-TYPE').val();
|
||||
aContainer = path_vcard + ' .avatar-container';
|
||||
}
|
||||
|
||||
else {
|
||||
} else {
|
||||
aBinval = $(iqNode).find('BINVAL:first').text();
|
||||
aType = $(iqNode).find('TYPE:first').text();
|
||||
aContainer = path_userInfos + ' .avatar-container';
|
||||
|
@ -578,8 +579,10 @@ var vCard = (function () {
|
|||
$(path_vcard + ' .avatar').remove();
|
||||
}
|
||||
|
||||
var avatar_src = ('data:' + aType + ';base64,' + aBinval);
|
||||
|
||||
// We display the avatar we have just received
|
||||
$(aContainer).replaceWith('<div class="avatar-container"><img class="avatar" src="data:' + aType + ';base64,' + aBinval + '" alt="" /></div>');
|
||||
$(aContainer).replaceWith('<div class="avatar-container"><img class="avatar" src="' + avatar_src + '" alt="" /></div>');
|
||||
}
|
||||
|
||||
else if(type == 'buddy') {
|
||||
|
@ -668,10 +671,11 @@ var vCard = (function () {
|
|||
var tagname = Common.explodeThis('-', item_id, 0);
|
||||
var cur_node;
|
||||
|
||||
if(node.getElementsByTagName(tagname).length > 0)
|
||||
if(node.getElementsByTagName(tagname).length > 0) {
|
||||
cur_node = node.getElementsByTagName(tagname).item(0);
|
||||
else
|
||||
} else {
|
||||
cur_node = node.appendChild(stanza.buildNode(tagname, {'xmlns': namespace}));
|
||||
}
|
||||
|
||||
cur_node.appendChild(
|
||||
stanza.buildNode(
|
||||
|
@ -874,18 +878,22 @@ var vCard = (function () {
|
|||
// Keyboard events
|
||||
$('#vcard input[type="text"]').keyup(function(e) {
|
||||
// Enter pressed: send the vCard
|
||||
if((e.keyCode == 13) && !$('#vcard .finish.save').hasClass('disabled'))
|
||||
if((e.keyCode == 13) && !$('#vcard .finish.save').hasClass('disabled')) {
|
||||
return self.send();
|
||||
}
|
||||
});
|
||||
|
||||
// Click events
|
||||
$('#vcard .tab a').click(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// Yet active?
|
||||
if($(this).hasClass('tab-active'))
|
||||
if(this_sel.hasClass('tab-active')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Switch to the good tab
|
||||
var key = parseInt($(this).attr('data-key'));
|
||||
var key = parseInt(this_sel.attr('data-key'));
|
||||
|
||||
return self.switchTab(key);
|
||||
});
|
||||
|
@ -895,10 +903,15 @@ var vCard = (function () {
|
|||
});
|
||||
|
||||
$('#vcard .bottom .finish').click(function() {
|
||||
if($(this).is('.cancel'))
|
||||
var this_sel = $(this);
|
||||
|
||||
if(this_sel.is('.cancel')) {
|
||||
return self.close();
|
||||
if($(this).is('.save') && !$(this).hasClass('disabled'))
|
||||
}
|
||||
|
||||
if(this_sel.is('.save') && !this_sel.hasClass('disabled')) {
|
||||
return self.send();
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
@ -912,16 +925,22 @@ var vCard = (function () {
|
|||
|
||||
// Avatar upload form submit event
|
||||
$('#vcard-avatar').submit(function() {
|
||||
if($('#vcard .wait').is(':hidden') && $('#vcard .avatar-info.avatar-wait').is(':hidden') && $('#vcard-avatar input[type="file"]').val())
|
||||
if($('#vcard .wait').is(':hidden') &&
|
||||
$('#vcard .avatar-info.avatar-wait').is(':hidden') &&
|
||||
$('#vcard-avatar input[type="file"]').val()) {
|
||||
$(this).ajaxSubmit(avatar_options);
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
// Avatar upload input change event
|
||||
$('#vcard-avatar input[type="file"]').change(function() {
|
||||
if($('#vcard .wait').is(':hidden') && $('#vcard .avatar-info.avatar-wait').is(':hidden') && $(this).val())
|
||||
if($('#vcard .wait').is(':hidden') &&
|
||||
$('#vcard .avatar-info.avatar-wait').is(':hidden') &&
|
||||
$(this).val()) {
|
||||
$('#vcard-avatar').ajaxSubmit(avatar_options);
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
|
|
@ -203,6 +203,7 @@ var Welcome = (function () {
|
|||
// Update the "save" button if all is okay
|
||||
if(!Common.exists(tab + '.tab-missing')) {
|
||||
var finish = welcome + '.finish.';
|
||||
|
||||
$(finish + 'save').show();
|
||||
$(finish + 'next').hide();
|
||||
}
|
||||
|
@ -280,19 +281,22 @@ var Welcome = (function () {
|
|||
$('#welcome a.box').each(function() {
|
||||
var current = '0';
|
||||
|
||||
if($(this).hasClass('enabled'))
|
||||
if($(this).hasClass('enabled')) {
|
||||
current = '1';
|
||||
}
|
||||
|
||||
array.push(current);
|
||||
});
|
||||
|
||||
// If XMPP links is enabled
|
||||
if(array[2] == '1')
|
||||
if(array[2] == '1') {
|
||||
Utils.xmppLinksHandler();
|
||||
}
|
||||
|
||||
// If offline buddies showing is enabled
|
||||
if(array[4] == '1')
|
||||
if(array[4] == '1') {
|
||||
Interface.showAllBuddies('welcome');
|
||||
}
|
||||
|
||||
// If archiving is supported by the server
|
||||
if(Features.enabledMAM()) {
|
||||
|
@ -336,8 +340,9 @@ var Welcome = (function () {
|
|||
var next = 1;
|
||||
var missing = '#welcome .tab a.tab-missing';
|
||||
|
||||
if(Common.exists(missing))
|
||||
if(Common.exists(missing)) {
|
||||
next = parseInt($(missing + ':first').attr('data-step'));
|
||||
}
|
||||
|
||||
// Switch to the next step
|
||||
self.switchTab(next);
|
||||
|
@ -360,26 +365,36 @@ var Welcome = (function () {
|
|||
try {
|
||||
// Click events
|
||||
$('#welcome .tab a').click(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// Switch to the good tab
|
||||
var key = parseInt($(this).attr('data-step'));
|
||||
var key = parseInt(this_sel.attr('data-step'));
|
||||
|
||||
return self.switchTab(key);
|
||||
});
|
||||
|
||||
$('#welcome a.box:not(.share)').click(function() {
|
||||
if($(this).hasClass('enabled'))
|
||||
$(this).removeClass('enabled').attr('title', Common._e("Click to enable"));
|
||||
else
|
||||
$(this).addClass('enabled').attr('title', Common._e("Click to disable"));
|
||||
var this_sel = $(this);
|
||||
|
||||
if(this_sel.hasClass('enabled')) {
|
||||
this_sel.removeClass('enabled').attr('title', Common._e("Click to enable"));
|
||||
} else {
|
||||
this_sel.addClass('enabled').attr('title', Common._e("Click to disable"));
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#welcome .bottom .finish').click(function() {
|
||||
if($(this).is('.next'))
|
||||
var this_sel = $(this);
|
||||
|
||||
if(this_sel.is('.next')) {
|
||||
return self.next();
|
||||
if($(this).is('.save'))
|
||||
}
|
||||
|
||||
if(this_sel.is('.save')) {
|
||||
return self.save();
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
|
|
@ -35,11 +35,9 @@ var XMPPLinks = (function () {
|
|||
link = Common.explodeThis(':', link, 1);
|
||||
|
||||
// The XMPP URI has no "?"
|
||||
if(link.indexOf('?') == -1)
|
||||
if(link.indexOf('?') == -1) {
|
||||
Chat.checkCreate(link, 'chat');
|
||||
|
||||
// Parse the URI
|
||||
else {
|
||||
} else {
|
||||
var xid = Common.explodeThis('?', link, 0);
|
||||
var action = Common.explodeThis('?', link, 1);
|
||||
|
||||
|
@ -88,11 +86,13 @@ var XMPPLinks = (function () {
|
|||
* Gets the links vars (get parameters in URL)
|
||||
*/
|
||||
self.links_var = (function() {
|
||||
var hash;
|
||||
var vars = [];
|
||||
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
|
||||
|
||||
for(var i = 0; i < hashes.length; i++) {
|
||||
var hash = hashes[i].split('=');
|
||||
hash = hashes[i].split('=');
|
||||
|
||||
vars.push(hash[0]);
|
||||
vars[hash[0]] = $.trim(decodeURIComponent(hash[1]));
|
||||
}
|
||||
|
|
BIN
source/app/sounds/catch-attention.mp3
Normal file
BIN
source/app/sounds/catch-attention.oga
Normal file
254
source/app/stylesheets/call.css
Normal file
|
@ -0,0 +1,254 @@
|
|||
/*
|
||||
|
||||
Jappix - An open social platform
|
||||
This is the call CSS stylesheet for Jappix
|
||||
|
||||
-------------------------------------------------
|
||||
|
||||
License: AGPL
|
||||
Author: Valérian Saliou
|
||||
|
||||
*/
|
||||
|
||||
.videochat_box {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.videochat_box .videochat_items {
|
||||
background: #ededed;
|
||||
border: 1px solid rgb(0,0,0);
|
||||
border: 1px solid rgba(0,0,0,0.8);
|
||||
text-shadow: none;
|
||||
min-width: 550px;
|
||||
min-height: 420px;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
left: 100px;
|
||||
right: 100px;
|
||||
top: 40px;
|
||||
bottom: 40px;
|
||||
-moz-box-shadow: 0 0 12px rgba(0,0,0,0.4);
|
||||
-webkit-box-shadow: 0 0 12px rgba(0,0,0,0.4);
|
||||
box-shadow: 0 0 12px rgba(0,0,0,0.4);
|
||||
}
|
||||
|
||||
.videochat_box .videochat_items .topbar {
|
||||
background: rgb(0,0,0);
|
||||
background: rgba(0,0,0,0.5);
|
||||
border-bottom: 1px solid rgb(0,0,0);
|
||||
border-bottom: 1px solid rgba(0,0,0,0.15);
|
||||
color: #ffffff;
|
||||
text-shadow: 0 1px 1px rgb(0,0,0);
|
||||
text-shadow: 0 1px 1px rgba(0,0,0,0.5);
|
||||
height: 40px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
z-index: 4;
|
||||
-moz-box-shadow: 0 0 5px rgba(0,0,0,0.25);
|
||||
-webkit-box-shadow: 0 0 5px rgba(0,0,0,0.25);
|
||||
box-shadow: 0 0 5px rgba(0,0,0,0.25);
|
||||
}
|
||||
|
||||
.videochat_box .videochat_items .topbar .controls,
|
||||
.videochat_box .videochat_items .topbar .elapsed {
|
||||
float: left;
|
||||
}
|
||||
|
||||
html[dir="rtl"] .videochat_box .videochat_items .topbar .controls,
|
||||
html[dir="rtl"] .videochat_box .videochat_items .topbar .elapsed {
|
||||
float: right;
|
||||
}
|
||||
|
||||
html[dir="rtl"] .videochat_box .videochat_items .topbar .controls {
|
||||
margin-left: 0;
|
||||
margin-right: 50px;
|
||||
}
|
||||
|
||||
.videochat_box .videochat_items .topbar .controls a {
|
||||
margin-top: 7px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
html[dir="rtl"] .videochat_box .videochat_items .topbar .controls a {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.videochat_box .videochat_items .topbar .controls a,
|
||||
.call-content .call-notify .notification-content .reply-buttons a.reply-button {
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
font-size: 10px;
|
||||
color: #ffffff;
|
||||
text-transform: uppercase;
|
||||
text-decoration: none;
|
||||
padding: 5px 6px 6px 6px;
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.videochat_box .videochat_items .topbar .controls a:active,
|
||||
.call-content .call-notify .notification-content .reply-buttons a.reply-button:active {
|
||||
padding-top: 6px;
|
||||
padding-bottom: 5px;
|
||||
-webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.25) inset;
|
||||
-moz-box-shadow: 0 1px 3px rgba(0,0,0,0.25) inset;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.25) inset;
|
||||
}
|
||||
|
||||
.videochat_box .videochat_items .topbar .controls a .icon {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
margin: -1px 7px 0 2px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.videochat_box .videochat_items .topbar .controls a.stop,
|
||||
.videochat_box .videochat_items .topbar .controls a.leave,
|
||||
.call-content .call-notify .notification-content .reply-buttons a.reply-button.red {
|
||||
background: #cc283f;
|
||||
border-color: #5e121d;
|
||||
}
|
||||
|
||||
.videochat_box .videochat_items .topbar .controls a.stop:active,
|
||||
.videochat_box .videochat_items .topbar .controls a.leave:active,
|
||||
.call-content .call-notify .notification-content .reply-buttons a.reply-button.red:active {
|
||||
background: #a92134;
|
||||
border-color: #480e16;
|
||||
}
|
||||
|
||||
.videochat_box .videochat_items .topbar .controls a.stop .icon,
|
||||
.videochat_box .videochat_items .topbar .controls a.leave .icon {
|
||||
background-position: 0 -62px;
|
||||
}
|
||||
|
||||
.call-content .call-notify .notification-content .reply-buttons a.reply-button.green {
|
||||
background: #5ea45e;
|
||||
border-color: #1a2e1a;
|
||||
}
|
||||
|
||||
.call-content .call-notify .notification-content .reply-buttons a.reply-button.green:active {
|
||||
background: #549253;
|
||||
border-color: #0f1a0f;
|
||||
}
|
||||
|
||||
.videochat_box .videochat_items .topbar .controls a.mute,
|
||||
.videochat_box .videochat_items .topbar .controls a.unmute,
|
||||
.call-content .call-notify .notification-content .reply-buttons a.reply-button.blue {
|
||||
background: #6e8dc5;
|
||||
border-color: #303d55;
|
||||
}
|
||||
|
||||
.videochat_box .videochat_items .topbar .controls a.mute,
|
||||
.videochat_box .videochat_items .topbar .controls a.unmute {
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
html[dir="rtl"] .videochat_box .videochat_items .topbar .controls a.mute,
|
||||
html[dir="rtl"] .videochat_box .videochat_items .topbar .controls a.unmute {
|
||||
margin-left: 0;
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
.videochat_box .videochat_items .topbar .controls a.mute:active,
|
||||
.videochat_box .videochat_items .topbar .controls a.unmute:active,
|
||||
.call-content .call-notify .notification-content .reply-buttons a.reply-button.blue:active {
|
||||
background: #6480b1;
|
||||
border-color: #222b3b;
|
||||
}
|
||||
|
||||
.videochat_box .videochat_items .topbar .controls a.mute .icon {
|
||||
background-position: 0 -81px;
|
||||
}
|
||||
|
||||
.videochat_box .videochat_items .topbar .controls a.unmute {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.videochat_box .videochat_items .topbar .controls a.unmute .icon {
|
||||
background-position: 0 -100px;
|
||||
}
|
||||
|
||||
.videochat_box .videochat_items .topbar .elapsed {
|
||||
background: rgb(0,0,0);
|
||||
background: rgba(0,0,0,0.1);
|
||||
border: 1px solid rgb(255,255,255);
|
||||
border: 1px solid rgba(255,255,255,0.25);
|
||||
outline: 1px solid rgb(0,0,0);
|
||||
outline: 1px solid rgba(0,0,0,0.2);
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
letter-spacing: 2px;
|
||||
margin: 10px 0 0 46px;
|
||||
padding: 2px 6px;
|
||||
}
|
||||
|
||||
html[dir="rtl"] .videochat_box .videochat_items .topbar .elapsed {
|
||||
margin-left: 0;
|
||||
margin-right: 46px;
|
||||
}
|
||||
|
||||
.videochat_box .videochat_items .topbar .actions {
|
||||
margin: 7px 15px 0 0;
|
||||
float: right;
|
||||
}
|
||||
|
||||
html[dir="rtl"] .videochat_box .videochat_items .topbar .actions {
|
||||
margin-right: 0;
|
||||
margin-left: 15px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.videochat_box .videochat_items .topbar .actions a {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.videochat_box .videochat_items .topbar .actions a.close {
|
||||
background-position: 0 -44px;
|
||||
width: 18px;
|
||||
height: 12px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.videochat_box .videochat_items .local_video {
|
||||
background-position: 0 -56px;
|
||||
border: 1px solid rgb(0,0,0);
|
||||
border: 1px solid rgba(0,0,0,0.5);
|
||||
width: 180px;
|
||||
height: 101px;
|
||||
opacity: 0.6;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
left: 18px;
|
||||
bottom: 18px;
|
||||
z-index: 3;
|
||||
-moz-box-shadow: 0 0 8px rgba(0,0,0,0.25);
|
||||
-webkit-box-shadow: 0 0 8px rgba(0,0,0,0.25);
|
||||
box-shadow: 0 0 8px rgba(0,0,0,0.25);
|
||||
-webkit-transition: all 0.4s ease-in-out 0.2s;
|
||||
-moz-transition: all 0.4s ease-in-out 0.2s;
|
||||
-o-transition: all 0.4s ease-in-out 0.2s;
|
||||
transition: all 0.4s ease-in-out 0.2s;
|
||||
}
|
||||
|
||||
html[dir="rtl"] .videochat_box .videochat_items .local_video {
|
||||
left: auto;
|
||||
right: 18px;
|
||||
}
|
||||
|
||||
.videochat_box .videochat_items .local_video:disabled {
|
||||
opacity: 0.2 !important;
|
||||
}
|
||||
|
||||
.videochat_box .videochat_items .local_video:hover {
|
||||
width: 320px;
|
||||
height: 180px;
|
||||
opacity: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.videochat_box .videochat_items .local_video video {
|
||||
width: 100%;
|
||||
}
|
|
@ -597,7 +597,8 @@ html[dir="rtl"] #home .right .navigation a {
|
|||
background: -webkit-gradient(linear, left top, left bottom, from(#e4eef9), to(#c5e1ff));
|
||||
background: -webkit-linear-gradient(top, #e4eef9 0%, #c5e1ff 100%);
|
||||
background: -o-linear-gradient(top, #e4eef9 0%, #c5e1ff 100%);
|
||||
font-size: 13.4px;
|
||||
font-size: 11px !important;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
|
@ -693,6 +694,22 @@ html[dir="rtl"] #home .right .navigation a {
|
|||
left: 10px;
|
||||
}
|
||||
|
||||
#home .friendsview .friends .group.standard br {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#home .friendsview .friends .group.standard a {
|
||||
text-align: center;
|
||||
text-decoration: underline;
|
||||
margin-bottom: 1px;
|
||||
float: left;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
#home .friendsview .friends .group.standard a:nth-child(even) {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#home .friendsview .friends a.group.refer {
|
||||
width: 81px;
|
||||
padding-left: 10px;
|
||||
|
|
|
@ -56,8 +56,8 @@ Author: Valérian Saliou
|
|||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.jingle-images {
|
||||
background-image: url(../images/sprites/jingle.png);
|
||||
.call-images {
|
||||
background-image: url(../images/sprites/call.png);
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
|
||||
Jappix - An open social platform
|
||||
This is the discovery CSS stylesheet for Jappix
|
||||
This is the Jingle CSS stylesheet for Jappix
|
||||
|
||||
-------------------------------------------------
|
||||
|
||||
|
@ -10,47 +10,6 @@ Author: Valérian Saliou
|
|||
|
||||
*/
|
||||
|
||||
#jingle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#jingle .videobox {
|
||||
background: #ededed;
|
||||
border: 1px solid rgb(0,0,0);
|
||||
border: 1px solid rgba(0,0,0,0.8);
|
||||
text-shadow: none;
|
||||
min-width: 550px;
|
||||
min-height: 420px;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
left: 100px;
|
||||
right: 100px;
|
||||
top: 40px;
|
||||
bottom: 40px;
|
||||
-moz-box-shadow: 0 0 12px rgba(0,0,0,0.4);
|
||||
-webkit-box-shadow: 0 0 12px rgba(0,0,0,0.4);
|
||||
box-shadow: 0 0 12px rgba(0,0,0,0.4);
|
||||
}
|
||||
|
||||
#jingle .videobox .topbar {
|
||||
background: rgb(0,0,0);
|
||||
background: rgba(0,0,0,0.5);
|
||||
border-bottom: 1px solid rgb(0,0,0);
|
||||
border-bottom: 1px solid rgba(0,0,0,0.15);
|
||||
color: #ffffff;
|
||||
text-shadow: 0 1px 1px rgb(0,0,0);
|
||||
text-shadow: 0 1px 1px rgba(0,0,0,0.5);
|
||||
height: 40px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
z-index: 4;
|
||||
-moz-box-shadow: 0 0 5px rgba(0,0,0,0.25);
|
||||
-webkit-box-shadow: 0 0 5px rgba(0,0,0,0.25);
|
||||
box-shadow: 0 0 5px rgba(0,0,0,0.25);
|
||||
}
|
||||
|
||||
#jingle .videobox .topbar .card {
|
||||
margin: 4px 0 0 12px;
|
||||
}
|
||||
|
@ -62,17 +21,13 @@ html[dir="rtl"] #jingle .videobox .topbar .card {
|
|||
|
||||
#jingle .videobox .topbar .card,
|
||||
#jingle .videobox .topbar .card .avatar-container,
|
||||
#jingle .videobox .topbar .card .identity,
|
||||
#jingle .videobox .topbar .controls,
|
||||
#jingle .videobox .topbar .elapsed {
|
||||
#jingle .videobox .topbar .card .identity {
|
||||
float: left;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #jingle .videobox .topbar .card,
|
||||
html[dir="rtl"] #jingle .videobox .topbar .card .avatar-container,
|
||||
html[dir="rtl"] #jingle .videobox .topbar .card .identity,
|
||||
html[dir="rtl"] #jingle .videobox .topbar .controls,
|
||||
html[dir="rtl"] #jingle .videobox .topbar .elapsed {
|
||||
html[dir="rtl"] #jingle .videobox .topbar .card .identity {
|
||||
float: right;
|
||||
}
|
||||
|
||||
|
@ -115,192 +70,8 @@ html[dir="rtl"] #jingle .videobox .topbar .card .identity {
|
|||
margin-left: 50px;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #jingle .videobox .topbar .controls {
|
||||
margin-left: 0;
|
||||
margin-right: 50px;
|
||||
}
|
||||
|
||||
#jingle .videobox .topbar .controls a {
|
||||
margin-top: 7px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #jingle .videobox .topbar .controls a {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#jingle .videobox .topbar .controls a,
|
||||
.jingle-content .jingle-notify .notification-content .reply-buttons a.reply-button {
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
font-size: 10px;
|
||||
color: #ffffff;
|
||||
text-transform: uppercase;
|
||||
text-decoration: none;
|
||||
padding: 5px 6px 6px 6px;
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
#jingle .videobox .topbar .controls a:active,
|
||||
.jingle-content .jingle-notify .notification-content .reply-buttons a.reply-button:active {
|
||||
padding-top: 6px;
|
||||
padding-bottom: 5px;
|
||||
-webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.25) inset;
|
||||
-moz-box-shadow: 0 1px 3px rgba(0,0,0,0.25) inset;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.25) inset;
|
||||
}
|
||||
|
||||
#jingle .videobox .topbar .controls a .icon {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
margin: -1px 7px 0 2px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
#jingle .videobox .topbar .controls a.stop,
|
||||
.jingle-content .jingle-notify .notification-content .reply-buttons a.reply-button.red {
|
||||
background: #cc283f;
|
||||
border-color: #5e121d;
|
||||
}
|
||||
|
||||
#jingle .videobox .topbar .controls a.stop:active,
|
||||
.jingle-content .jingle-notify .notification-content .reply-buttons a.reply-button.red:active {
|
||||
background: #a92134;
|
||||
border-color: #480e16;
|
||||
}
|
||||
|
||||
#jingle .videobox .topbar .controls a.stop .icon {
|
||||
background-position: 0 -62px;
|
||||
}
|
||||
|
||||
.jingle-content .jingle-notify .notification-content .reply-buttons a.reply-button.green {
|
||||
background: #5ea45e;
|
||||
border-color: #1a2e1a;
|
||||
}
|
||||
|
||||
.jingle-content .jingle-notify .notification-content .reply-buttons a.reply-button.green:active {
|
||||
background: #549253;
|
||||
border-color: #0f1a0f;
|
||||
}
|
||||
|
||||
#jingle .videobox .topbar .controls a.mute,
|
||||
#jingle .videobox .topbar .controls a.unmute,
|
||||
.jingle-content .jingle-notify .notification-content .reply-buttons a.reply-button.blue {
|
||||
background: #6e8dc5;
|
||||
border-color: #303d55;
|
||||
}
|
||||
|
||||
#jingle .videobox .topbar .controls a.mute,
|
||||
#jingle .videobox .topbar .controls a.unmute {
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #jingle .videobox .topbar .controls a.mute,
|
||||
html[dir="rtl"] #jingle .videobox .topbar .controls a.unmute {
|
||||
margin-left: 0;
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
#jingle .videobox .topbar .controls a.mute:active,
|
||||
#jingle .videobox .topbar .controls a.unmute:active,
|
||||
.jingle-content .jingle-notify .notification-content .reply-buttons a.reply-button.blue:active {
|
||||
background: #6480b1;
|
||||
border-color: #222b3b;
|
||||
}
|
||||
|
||||
#jingle .videobox .topbar .controls a.mute .icon {
|
||||
background-position: 0 -81px;
|
||||
}
|
||||
|
||||
#jingle .videobox .topbar .controls a.unmute {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#jingle .videobox .topbar .controls a.unmute .icon {
|
||||
background-position: 0 -100px;
|
||||
}
|
||||
|
||||
#jingle .videobox .topbar .elapsed {
|
||||
background: rgb(0,0,0);
|
||||
background: rgba(0,0,0,0.1);
|
||||
border: 1px solid rgb(255,255,255);
|
||||
border: 1px solid rgba(255,255,255,0.25);
|
||||
outline: 1px solid rgb(0,0,0);
|
||||
outline: 1px solid rgba(0,0,0,0.2);
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
letter-spacing: 2px;
|
||||
margin: 10px 0 0 46px;
|
||||
padding: 2px 6px;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #jingle .videobox .topbar .elapsed {
|
||||
margin-left: 0;
|
||||
margin-right: 46px;
|
||||
}
|
||||
|
||||
#jingle .videobox .topbar .actions {
|
||||
margin: 7px 15px 0 0;
|
||||
float: right;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #jingle .videobox .topbar .actions {
|
||||
margin-right: 0;
|
||||
margin-left: 15px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
#jingle .videobox .topbar .actions a {
|
||||
float: left;
|
||||
}
|
||||
|
||||
#jingle .videobox .topbar .actions a.close {
|
||||
background-position: 0 -44px;
|
||||
width: 18px;
|
||||
height: 12px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
#jingle .videobox .local_video {
|
||||
background-position: 0 -56px;
|
||||
border: 1px solid rgb(0,0,0);
|
||||
border: 1px solid rgba(0,0,0,0.5);
|
||||
width: 180px;
|
||||
height: 101px;
|
||||
opacity: 0.6;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
left: 18px;
|
||||
bottom: 18px;
|
||||
z-index: 3;
|
||||
-moz-box-shadow: 0 0 8px rgba(0,0,0,0.25);
|
||||
-webkit-box-shadow: 0 0 8px rgba(0,0,0,0.25);
|
||||
box-shadow: 0 0 8px rgba(0,0,0,0.25);
|
||||
-webkit-transition: all 0.4s ease-in-out 0.2s;
|
||||
-moz-transition: all 0.4s ease-in-out 0.2s;
|
||||
-o-transition: all 0.4s ease-in-out 0.2s;
|
||||
transition: all 0.4s ease-in-out 0.2s;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #jingle .videobox .local_video {
|
||||
left: auto;
|
||||
right: 18px;
|
||||
}
|
||||
|
||||
#jingle .videobox .local_video:disabled {
|
||||
opacity: 0.2 !important;
|
||||
}
|
||||
|
||||
#jingle .videobox .local_video:hover {
|
||||
width: 320px;
|
||||
height: 180px;
|
||||
opacity: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#jingle .videobox .remote_video {
|
||||
background-color: #000000;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
|
@ -311,6 +82,11 @@ html[dir="rtl"] #jingle .videobox .local_video {
|
|||
z-index: 1;
|
||||
}
|
||||
|
||||
#jingle .videobox .remote_video video {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#jingle .videobox .branding {
|
||||
background-position: 0 0;
|
||||
width: 39px;
|
||||
|
|
|
@ -114,6 +114,19 @@ input[type="radio"] {
|
|||
border: 0 none !important;
|
||||
}
|
||||
|
||||
input.input-reset {
|
||||
background: transparent;
|
||||
border: 0 none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
-moz-border-radius: 0;
|
||||
-webkit-border-radius: 0;
|
||||
border-radius: 0;
|
||||
-moz-box-shadow: none;
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.please-complete,
|
||||
.please-complete:hover,
|
||||
.please-complete:focus {
|
||||
|
@ -129,4 +142,5 @@ input[type="radio"] {
|
|||
|
||||
.clear {
|
||||
clear: both !important;
|
||||
display: block !important;
|
||||
}
|
||||
|
|
|
@ -143,7 +143,7 @@ a {
|
|||
}
|
||||
|
||||
#talk a.one-buddy {
|
||||
display: none;
|
||||
display: block;
|
||||
background-color: #87a5ab;
|
||||
border-bottom: 1px solid #5b8088;
|
||||
text-shadow: 1px 1px 1px #5b8088;
|
||||
|
@ -154,6 +154,7 @@ a {
|
|||
}
|
||||
|
||||
#talk a.one-buddy:hover {
|
||||
background-color: #8fb0b7;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
@ -248,7 +249,7 @@ a {
|
|||
border-bottom: 1px solid #cbcbcb;
|
||||
top: 23px;
|
||||
left: 0;
|
||||
bottom: 25px;
|
||||
bottom: 37px;
|
||||
overflow: auto;
|
||||
text-align: left;
|
||||
}
|
||||
|
|
700
source/app/stylesheets/muji.css
Normal file
|
@ -0,0 +1,700 @@
|
|||
/*
|
||||
|
||||
Jappix - An open social platform
|
||||
This is the Muji CSS stylesheet for Jappix
|
||||
|
||||
-------------------------------------------------
|
||||
|
||||
License: AGPL
|
||||
Author: Valérian Saliou
|
||||
|
||||
*/
|
||||
|
||||
#muji .videochat_items {
|
||||
min-width: 600px;
|
||||
left: 60px;
|
||||
right: 60px;
|
||||
}
|
||||
|
||||
#muji .remote_container {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
/* Default video */
|
||||
#muji .remote_container .remote_video_shaper {
|
||||
overflow: hidden;
|
||||
display: none;
|
||||
float: left;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* 1 video view */
|
||||
#muji[data-count="1"] .remote_container .remote_video_shaper:nth-child(1) {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* 2 video views */
|
||||
#muji[data-count="2"] .remote_container .remote_video_shaper:nth-child(1),
|
||||
#muji[data-count="2"] .remote_container .remote_video_shaper:nth-child(2) {
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* 3 video views */
|
||||
#muji[data-count="3"] .remote_container .remote_video_shaper:nth-child(1),
|
||||
#muji[data-count="3"] .remote_container .remote_video_shaper:nth-child(2),
|
||||
#muji[data-count="3"] .remote_container .remote_video_shaper:nth-child(3) {
|
||||
height: 50%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#muji[data-count="3"] .remote_container .remote_video_shaper:nth-child(1) {
|
||||
width: 100%;
|
||||
float: none;
|
||||
}
|
||||
|
||||
#muji[data-count="3"] .remote_container .remote_video_shaper:nth-child(2),
|
||||
#muji[data-count="3"] .remote_container .remote_video_shaper:nth-child(3) {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
/* 4 video views */
|
||||
#muji[data-count="4"] .remote_container .remote_video_shaper:nth-child(1),
|
||||
#muji[data-count="4"] .remote_container .remote_video_shaper:nth-child(2),
|
||||
#muji[data-count="4"] .remote_container .remote_video_shaper:nth-child(3),
|
||||
#muji[data-count="4"] .remote_container .remote_video_shaper:nth-child(4) {
|
||||
height: 50%;
|
||||
width: 50%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* 5 video views */
|
||||
#muji[data-count="5"] .remote_container .remote_video_shaper:nth-child(1),
|
||||
#muji[data-count="5"] .remote_container .remote_video_shaper:nth-child(2),
|
||||
#muji[data-count="5"] .remote_container .remote_video_shaper:nth-child(3),
|
||||
#muji[data-count="5"] .remote_container .remote_video_shaper:nth-child(4),
|
||||
#muji[data-count="5"] .remote_container .remote_video_shaper:nth-child(5) {
|
||||
height: 50%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#muji[data-count="5"] .remote_container .remote_video_shaper:nth-child(1),
|
||||
#muji[data-count="5"] .remote_container .remote_video_shaper:nth-child(2) {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
#muji[data-count="5"] .remote_container .remote_video_shaper:nth-child(3),
|
||||
#muji[data-count="5"] .remote_container .remote_video_shaper:nth-child(4),
|
||||
#muji[data-count="5"] .remote_container .remote_video_shaper:nth-child(5) {
|
||||
width: 33.33333333%;
|
||||
}
|
||||
|
||||
/* 6 video views */
|
||||
#muji[data-count="6"] .remote_container .remote_video_shaper:nth-child(1),
|
||||
#muji[data-count="6"] .remote_container .remote_video_shaper:nth-child(2),
|
||||
#muji[data-count="6"] .remote_container .remote_video_shaper:nth-child(3),
|
||||
#muji[data-count="6"] .remote_container .remote_video_shaper:nth-child(4),
|
||||
#muji[data-count="6"] .remote_container .remote_video_shaper:nth-child(5),
|
||||
#muji[data-count="6"] .remote_container .remote_video_shaper:nth-child(6) {
|
||||
height: 50%;
|
||||
width: 33.33333333%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#muji .remote_container .remote_video_shaper .label_username {
|
||||
background: rgb(0,0,0);
|
||||
background: rgba(0,0,0,0.6);
|
||||
color: #ffffff;
|
||||
font-size: 0.75em;
|
||||
padding: 3px 6px 4px 10px;
|
||||
position: absolute;
|
||||
top: 7px;
|
||||
left: 0;
|
||||
display: none;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #muji .remote_container .remote_video_shaper .label_username {
|
||||
padding-right: 10px;
|
||||
padding-left: 6px;
|
||||
left: auto;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
#muji[data-count="1"] .remote_container .remote_video_shaper .label_username,
|
||||
#muji[data-count="2"] .remote_container .remote_video_shaper .label_username,
|
||||
#muji[data-count="3"] .remote_container .remote_video_shaper:nth-child(1) .label_username,
|
||||
#muji[data-count="4"] .remote_container .remote_video_shaper:nth-child(n+1):nth-child(-n+2) .label_username,
|
||||
#muji[data-count="5"] .remote_container .remote_video_shaper:nth-child(n+1):nth-child(-n+2) .label_username,
|
||||
#muji[data-count="6"] .remote_container .remote_video_shaper:nth-child(n+1):nth-child(-n+3) .label_username {
|
||||
top: 48px;
|
||||
}
|
||||
|
||||
#muji .remote_container .remote_video_shaper:hover .label_username {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#muji .empty_message {
|
||||
text-align: center;
|
||||
margin-top: -11px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 50%;
|
||||
}
|
||||
|
||||
#muji .empty_message .text {
|
||||
color: #ffffff;
|
||||
letter-spacing: 1px;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
#muji .videoroom,
|
||||
#muji .chatroom {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
#muji .videoroom {
|
||||
background-color: #000000;
|
||||
left: 0;
|
||||
right: 280px;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #muji .videoroom {
|
||||
right: 0;
|
||||
left: 280px;
|
||||
}
|
||||
|
||||
#muji .videoroom .topbar .controls {
|
||||
margin-left: 18px;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #muji .videoroom .topbar .controls {
|
||||
margin-right: 18px;
|
||||
}
|
||||
|
||||
#muji .videoroom .topbar .elapsed {
|
||||
margin-left: 80px;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #muji .videoroom .topbar .elapsed {
|
||||
margin-right: 80px;
|
||||
}
|
||||
|
||||
#muji .chatroom {
|
||||
background: #ffffff;
|
||||
width: 280px;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #muji .chatroom {
|
||||
right: auto;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
#muji .videoroom .local_video {
|
||||
width: 140px;
|
||||
height: 78px;
|
||||
}
|
||||
|
||||
#muji .videoroom .local_video:hover {
|
||||
width: 220px;
|
||||
height: 123px;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants {
|
||||
background: #fcfcfc;
|
||||
border-bottom: 1px solid #e1e1e1;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_default_view {
|
||||
text-align: center;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_default_view .participants_counter,
|
||||
#muji .chatroom .chatroom_participants .participants_default_view .participants_full {
|
||||
color: #444444;
|
||||
font-size: 0.9em;
|
||||
font-weight: bold;
|
||||
letter-spacing: 1px;
|
||||
margin-top: 11px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_default_view .participants_full {
|
||||
color: #5a6d7f;
|
||||
font-size: 0.8em;
|
||||
margin-left: 6px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #muji .chatroom .chatroom_participants .participants_default_view .participants_full {
|
||||
margin-left: auto;
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_default_view .participants_invite {
|
||||
background-position: 0 -287px;
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
opacity: 0.6;
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 14px;
|
||||
right: 16px;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #muji .chatroom .chatroom_participants .participants_default_view .participants_invite {
|
||||
right: auto;
|
||||
left: 16px;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_default_view .participants_invite:hover,
|
||||
#muji .chatroom .chatroom_participants .participants_default_view .participants_invite:focus {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box {
|
||||
border-top: 1px solid #e1e1e1;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_list {
|
||||
border-bottom: 1px solid #e1e1e1;
|
||||
padding: 4px 2px 2px 6px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_list .invite_one {
|
||||
background: #d7e2f4;
|
||||
border: 1px solid #aab9f4;
|
||||
font-size: 0.75em;
|
||||
margin: 0 4px 3px 0;
|
||||
padding: 2px 4px;
|
||||
display: inline-block;
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_list .invite_one.invite_unsupported {
|
||||
background: #f49d90;
|
||||
border-color: #de8780;
|
||||
color: #95443e;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_list .invite_one .invite_one_remove {
|
||||
background-position: 0 -300px;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
margin-left: 3px;
|
||||
margin-top: 1px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_list .invite_one .invite_one_remove {
|
||||
margin-left: auto;
|
||||
margin-right: 3px;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_list .invite_one.invite_unsupported .invite_one_remove {
|
||||
background-position: 0 -309px;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_list .invite_one .invite_one_remove:hover,
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_list .invite_one .invite_one_remove:focus,
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_list .invite_one .invite_one_remove:active {
|
||||
background-position: 1px -317px;
|
||||
margin-left: 2px;
|
||||
margin-right: -1px;
|
||||
margin-bottom: -1px;
|
||||
padding: 1px;
|
||||
-moz-border-radius: 1px;
|
||||
-webkit-border-radius: 1px;
|
||||
border-radius: 1px;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_list .invite_one .invite_one_remove:hover,
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_list .invite_one .invite_one_remove:focus {
|
||||
background-color: #8299ad;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_list .invite_one.invite_unsupported .invite_one_remove:hover,
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_list .invite_one.invite_unsupported .invite_one_remove:focus {
|
||||
background-color: #ad625f;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_list .invite_one .invite_one_remove:active {
|
||||
background-color: #5b6e80;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_list .invite_one.invite_unsupported .invite_one_remove:active {
|
||||
background-color: #804847;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box form.participants_invite_form {
|
||||
height: 32px;
|
||||
margin-left: 8px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #muji .chatroom .chatroom_participants .participants_invite_box form.participants_invite_form {
|
||||
margin-left: auto;
|
||||
margin-left: 0;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box form.participants_invite_form .invite_validate {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box form.participants_invite_form .invite_validate .invite_go {
|
||||
background-position: 0 -329px;
|
||||
width: 14px;
|
||||
height: 11px;
|
||||
opacity: 0.6;
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 11px;
|
||||
right: 16px;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #muji .chatroom .chatroom_participants .participants_invite_box form.participants_invite_form .invite_validate .invite_go {
|
||||
right: auto;
|
||||
left: 8px;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box form.participants_invite_form .invite_validate .invite_go:hover,
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box form.participants_invite_form .invite_validate .invite_go:active {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box form.participants_invite_form .invite_validate .invite_separator,
|
||||
#muji .chatroom form.chatroom_form .message_separator {
|
||||
background: #e9e9e9;
|
||||
width: 1px;
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
bottom: 6px;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box form.participants_invite_form .invite_validate .invite_separator {
|
||||
right: 40px;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #muji .chatroom .chatroom_participants .participants_invite_box form.participants_invite_form .invite_validate .invite_separator {
|
||||
right: auto;
|
||||
left: 32px;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box form.participants_invite_form .invite_input_container {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 41px;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #muji .chatroom .chatroom_participants .participants_invite_box form.participants_invite_form .invite_input_container {
|
||||
right: 0;
|
||||
left: 41px;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box form.participants_invite_form input.invite_xid {
|
||||
font-size: 0.8em;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_search {
|
||||
max-height: 220px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_search .participant_search_one {
|
||||
border-top: 1px solid #e1e1e1;
|
||||
height: 28px;
|
||||
display: block;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_search .participant_search_one.hover,
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_search .participant_search_one.focus {
|
||||
background: #f5f7ff;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_search .participant_search_one.active {
|
||||
background: #eef1f8;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_search .participant_search_one.participant_search_unsupported {
|
||||
background: #f6f6f6;
|
||||
color: #969696;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_search .participant_search_one.participant_search_unsupported.hover,
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_search .participant_search_one.participant_search_unsupported.focus {
|
||||
background: #f1f1f1;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_search .participant_search_one.participant_search_unsupported.active {
|
||||
background: #efefef;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_search .participant_search_one .avatar-container {
|
||||
text-align: center;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
margin: 4px 0 0 6px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_search .participant_search_one .avatar-container {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_search .participant_search_one .avatar-container .avatar {
|
||||
max-height: 20px;
|
||||
max-width: 20px;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_search .participant_search_one .details {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 40px;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_search .participant_search_one .details {
|
||||
right: 40px;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_search .participant_search_one .details .name,
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_search .participant_search_one .details .feature {
|
||||
position: absolute;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_search .participant_search_one .details .name {
|
||||
font-size: 0.8em;
|
||||
top: 6px;
|
||||
left: 0;
|
||||
right: 50px;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_search .participant_search_one .details .name {
|
||||
right: 0;
|
||||
left: 50px;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_search .participant_search_one .details .feature {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
top: 6px;
|
||||
right: 16px;
|
||||
opacity: 0.75;
|
||||
display: none;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_search .participant_search_one .details .feature {
|
||||
right: auto;
|
||||
left: 7px;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_search .participant_search_one.participant_search_has_audio .details .feature,
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_search .participant_search_one.participant_search_has_video .details .feature {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_search .participant_search_one.participant_search_has_audio .details .feature {
|
||||
background-position: 0 -340px;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_participants .participants_invite_box .participants_invite_search .participant_search_one.participant_search_has_video .details .feature {
|
||||
background-position: 0 -356px;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_view {
|
||||
padding: 4px 4px 12px 8px;
|
||||
overflow: auto;
|
||||
position: absolute;
|
||||
top: 41px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 41px;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #muji .chatroom .chatroom_view {
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_view .room_message {
|
||||
margin-top: 10px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_view .room_message.me .message_content {
|
||||
float: left;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #muji .chatroom .chatroom_view .room_message.me .message_content {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_view .room_message.him .message_content {
|
||||
margin-right: 30px;
|
||||
float: right;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #muji .chatroom .chatroom_view .room_message.him .message_content {
|
||||
margin-right: auto;
|
||||
margin-left: 30px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_view .room_message .message_content .message_bubble {
|
||||
font-size: 0.85em;
|
||||
padding: 7px 12px 8px 12px;
|
||||
display: block;
|
||||
-moz-border-radius: 6px;
|
||||
-webkit-border-radius: 6px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_view .room_message.me .message_content .message_bubble {
|
||||
background-color: #8dc2ef;
|
||||
-moz-border-radius-bottomleft: 0;
|
||||
-webkit-border-bottom-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #muji .chatroom .chatroom_view .room_message.me .message_content .message_bubble {
|
||||
-moz-border-radius-bottomleft: 6px;
|
||||
-webkit-border-bottom-left-radius: 6px;
|
||||
border-bottom-left-radius: 6px;
|
||||
-moz-border-radius-bottomright: 0;
|
||||
-webkit-border-bottom-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_view .room_message.him .message_content .message_bubble {
|
||||
background-color: #bcdf6a;
|
||||
-moz-border-radius-bottomright: 0;
|
||||
-webkit-border-bottom-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #muji .chatroom .chatroom_view .room_message.him .message_content .message_bubble {
|
||||
-moz-border-radius-bottomright: 6px;
|
||||
-webkit-border-bottom-right-radius: 6px;
|
||||
border-bottom-right-radius: 6px;
|
||||
-moz-border-radius-bottomleft: 0;
|
||||
-webkit-border-bottom-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_view .room_message .message_content .message_author {
|
||||
color: #6c6c6c;
|
||||
font-size: 0.75em;
|
||||
margin-top: 2px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_view .room_message.him .message_content .message_author {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #muji .chatroom .chatroom_view .room_message.him .message_content .message_author {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_view .room_message .message_avatar {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 16px;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #muji .chatroom .chatroom_view .room_message .message_avatar {
|
||||
right: auto;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_view .room_message .message_avatar.avatar-container {
|
||||
text-align: center;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
#muji .chatroom .chatroom_view .room_message .message_avatar.avatar-container .avatar {
|
||||
max-height: 24px;
|
||||
max-width: 24px;
|
||||
}
|
||||
|
||||
#muji .chatroom form.chatroom_form {
|
||||
background: #fcfcfc;
|
||||
border-top: 1px solid #e1e1e1;
|
||||
height: 40px;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
#muji .chatroom form.chatroom_form .message_icon {
|
||||
background-position: 0 -272px;
|
||||
width: 17px;
|
||||
height: 15px;
|
||||
position: absolute;
|
||||
top: 13px;
|
||||
left: 12px;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #muji .chatroom form.chatroom_form .message_icon {
|
||||
left: auto;
|
||||
right: 12px;
|
||||
}
|
||||
|
||||
#muji .chatroom form.chatroom_form .message_separator {
|
||||
left: 40px;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #muji .chatroom form.chatroom_form .message_separator {
|
||||
left: auto;
|
||||
right: 40px;
|
||||
}
|
||||
|
||||
#muji .chatroom form.chatroom_form .message_input_container {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 52px;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #muji .chatroom form.chatroom_form .message_input_container {
|
||||
left: auto;
|
||||
right: 52px;
|
||||
}
|
||||
|
||||
#muji .chatroom form.chatroom_form .message_input_container input.message_input {
|
||||
font-size: 0.8em;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
|
@ -108,7 +108,8 @@ html[dir="rtl"] .general-wait-content {
|
|||
.mam-hidable,
|
||||
.commands-hidable,
|
||||
.privacy-hidable,
|
||||
.xmpplinks-hidable {
|
||||
.xmpplinks-hidable,
|
||||
.muji-hidable {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
|
|
@ -327,6 +327,93 @@ html[dir="rtl"] #page-engine .list .user .user-details .avatar-container {
|
|||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#page-engine .one-line {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#page-engine .one-line.is-sending {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
#page-engine .one-line .correction-edit,
|
||||
#page-engine .one-line .correction-label,
|
||||
#page-engine .one-line.user-message[data-edited] .corrected-info,
|
||||
#page-engine .one-line .message-marker {
|
||||
font-size: 0.8em;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #page-engine .one-line .correction-edit,
|
||||
html[dir="rtl"] #page-engine .one-line .correction-label,
|
||||
html[dir="rtl"] #page-engine .one-line.user-message[data-edited] .corrected-info,
|
||||
html[dir="rtl"] #page-engine .one-line .message-marker {
|
||||
left: 0;
|
||||
right: auto;
|
||||
}
|
||||
|
||||
#page-engine .one-line .correction-edit,
|
||||
#page-engine .one-line .correction-label {
|
||||
border: 1px solid #7f7f7f;
|
||||
color: black;
|
||||
font-size: 0.8em;
|
||||
text-decoration: none;
|
||||
margin-top: -1px;
|
||||
padding: 2px 5px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
#page-engine .one-line .correction-edit {
|
||||
opacity: 0.4;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#page-engine .page-engine-chan[data-correction="true"] .one-line .correction-edit:hover,
|
||||
#page-engine .page-engine-chan[data-correction="true"] .one-line .correction-edit:focus {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
#page-engine .one-line.user-message[data-edited] .corrected-info,
|
||||
#page-engine .one-line .message-marker {
|
||||
color: #969696;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
#page-engine .one-line .message-marker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#page-engine .one-line .message-marker.message-marker-read {
|
||||
background-position: 0 -2227px;
|
||||
padding-left: 11px;
|
||||
}
|
||||
|
||||
#page-engine .page-engine-chan[data-correction="true"] .one-line.user-message[data-mode="me"]:last-child:hover .correction-edit {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#page-engine .one-line.correction-active .corrected-info,
|
||||
#page-engine .one-line.user-message[data-mode="me"]:last-child:hover .corrected-info {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#page-engine .one-line.correction-active .message-marker,
|
||||
#page-engine .one-line.user-message[data-mode="me"]:last-child:hover .message-marker {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
#page-engine .one-line .message-content {
|
||||
margin-right: 80px;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #page-engine .one-line .message-content {
|
||||
margin-right: 0;
|
||||
margin-left: 80px;
|
||||
}
|
||||
|
||||
#page-engine .one-line,
|
||||
#page-engine .one-group b.name {
|
||||
padding-left: 50px;
|
||||
|
@ -339,6 +426,10 @@ html[dir="rtl"] #page-engine .one-group b.name {
|
|||
padding-right: 50px;
|
||||
}
|
||||
|
||||
#page-engine .one-line.correction-active {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
#page-engine .one-group b.name {
|
||||
display: block;
|
||||
margin-bottom: 4px;
|
||||
|
@ -556,7 +647,9 @@ html[dir="rtl"] #page-engine .text .chat-tools-smileys {
|
|||
}
|
||||
|
||||
body.in_jingle_call #page-engine .text .tools-jingle-video,
|
||||
body.in_jingle_call #page-engine .text .tools-jingle-audio {
|
||||
body.in_jingle_call #page-engine .text .tools-jingle-audio,
|
||||
body.in_muji_call #page-engine .text .tools-jingle-video,
|
||||
body.in_muji_call #page-engine .text .tools-jingle-audio {
|
||||
opacity: 0.35;
|
||||
cursor: default;
|
||||
}
|
||||
|
@ -834,22 +927,67 @@ body.in_jingle_call #page-engine .text .tools-jingle-audio {
|
|||
}
|
||||
|
||||
#page-engine .text .compose,
|
||||
#page-engine .muc-ask {
|
||||
#page-engine .muc-ask,
|
||||
#page-engine .correction-toolbox {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
#page-engine .text .compose {
|
||||
#page-engine .text .compose,
|
||||
#page-engine .correction-toolbox {
|
||||
top: 29px;
|
||||
right: 12px;
|
||||
bottom: 12px;
|
||||
}
|
||||
|
||||
#page-engine .text .compose {
|
||||
right: 12px;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #page-engine .text .compose {
|
||||
right: 0;
|
||||
left: 12px;
|
||||
}
|
||||
|
||||
#page-engine .text.correction-active .compose {
|
||||
left: 120px;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #page-engine .text.correction-active .compose {
|
||||
right: 120px;
|
||||
}
|
||||
|
||||
#page-engine .correction-toolbox {
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #page-engine .correction-toolbox {
|
||||
right: 0;
|
||||
left: auto;
|
||||
}
|
||||
|
||||
#page-engine .correction-toolbox .correction-editing,
|
||||
#page-engine .correction-toolbox .correction-cancel {
|
||||
display: block;
|
||||
color: black;
|
||||
font-size: 0.8em;
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
margin: 7px 12px;
|
||||
padding: 2px 5px;
|
||||
}
|
||||
|
||||
#page-engine .correction-toolbox .correction-editing {
|
||||
font-weight: bold;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
#page-engine .correction-toolbox .correction-cancel {
|
||||
background: #d15e6b;
|
||||
border: 1px solid #cc273f;
|
||||
color: white;
|
||||
text-shadow: 0 1px 1px rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
#page-engine .muc-ask {
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
|
@ -872,6 +1010,21 @@ html[dir="rtl"] #page-engine .text .compose {
|
|||
border-top-left-radius: 0;
|
||||
}
|
||||
|
||||
#page-engine .text.correction-active textarea {
|
||||
-moz-border-radius-bottomleft: 0;
|
||||
-webkit-border-bottom-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
html[dir="rtl"] #page-engine .text.correction-active textarea {
|
||||
-moz-border-radius-bottomleft: 3px;
|
||||
-webkit-border-bottom-left-radius: 3px;
|
||||
border-bottom-left-radius: 3px;
|
||||
-moz-border-radius-bottomright: 0;
|
||||
-webkit-border-bottom-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
#page-engine .muc-ask {
|
||||
background-color: #e8f1f3;
|
||||
height: 64px;
|
||||
|
|
|
@ -356,7 +356,10 @@ html[dir="rtl"] .manage-infos p.bm-group input {
|
|||
background-position: 1px -2047px;
|
||||
}
|
||||
|
||||
body.in_jingle_call .call-jingle {
|
||||
body.in_jingle_call .call-jingle,
|
||||
body.in_muji_call .call-jingle,
|
||||
body.in_jingle_call .roster-muji,
|
||||
body.in_muji_call .roster-muji {
|
||||
opacity: 0.35;
|
||||
}
|
||||
|
||||
|
@ -367,7 +370,10 @@ body.in_jingle_call .call-jingle {
|
|||
display: none;
|
||||
}
|
||||
|
||||
body.in_jingle_call .call-jingle a {
|
||||
body.in_jingle_call .call-jingle a,
|
||||
body.in_muji_call .call-jingle a,
|
||||
body.in_jingle_call .roster-muji a,
|
||||
body.in_muji_call .roster-muji a {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
|
@ -455,7 +461,7 @@ html[dir="rtl"] #roster .roster-icon {
|
|||
width: 16px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
#roster .add,
|
||||
#page-engine .text .tools-add {
|
||||
background-position: 0 -1047px;
|
||||
|
@ -469,7 +475,11 @@ html[dir="rtl"] #roster .roster-icon {
|
|||
#page-switch .groupchat-default {
|
||||
background-position: 0 -1082px;
|
||||
}
|
||||
|
||||
|
||||
#roster .muji {
|
||||
background-position: 0 -2047px;
|
||||
}
|
||||
|
||||
#roster .more {
|
||||
background-position: 0 -1100px;
|
||||
}
|
||||
|
@ -520,7 +530,15 @@ html[dir="rtl"] .buddy-conf-subarrow {
|
|||
margin-right: 9px;
|
||||
float: right;
|
||||
}
|
||||
|
||||
|
||||
.buddy-conf-muji .buddy-conf-subarrow {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
html[dir="rtl"] .buddy-conf-muji .buddy-conf-subarrow {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.buddy-conf-subitem {
|
||||
background-color: rgb(0,0,0);
|
||||
background-color: rgba(0,0,0,0.8);
|
||||
|
|
|
@ -61,46 +61,51 @@ html[dir="rtl"] #top-content .tools-all {
|
|||
float: left;
|
||||
}
|
||||
|
||||
#top-content .jingle {
|
||||
#top-content .call {
|
||||
background-position: 7px -2114px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#top-content .jingle.video {
|
||||
#top-content .call .notify {
|
||||
margin-left: 0;
|
||||
left: -2px;
|
||||
}
|
||||
|
||||
#top-content .call.video {
|
||||
background-position: 7px -2205px;
|
||||
}
|
||||
|
||||
#top-content .jingle.active,
|
||||
#top-content .jingle.streaming {
|
||||
#top-content .call.active,
|
||||
#top-content .call.streaming {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#top-content .jingle.active {
|
||||
#top-content .call.active {
|
||||
-webkit-animation: tool_active 1.5s infinite ease-in-out;
|
||||
-moz-animation: tool_active 1.5s infinite ease-in-out;
|
||||
-o-animation: tool_active 1.5s infinite ease-in-out;
|
||||
animation: tool_active 1.5s infinite ease-in-out;
|
||||
}
|
||||
|
||||
#top-content .jingle.streaming {
|
||||
#top-content .call.streaming {
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
#top-content .jingle .streaming-items {
|
||||
#top-content .call .streaming-items {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#top-content .jingle.streaming .streaming-items {
|
||||
#top-content .call.streaming .streaming-items {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#top-content .jingle.streaming .streaming-items .counter {
|
||||
#top-content .call.streaming .streaming-items .counter {
|
||||
font-size: 11px;
|
||||
font-style: italic;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#top-content .jingle.streaming .streaming-items a.stop {
|
||||
#top-content .call.streaming .streaming-items a.stop {
|
||||
background: #cc283f;
|
||||
border-left: 1px solid #a12032;
|
||||
color: #ffffff;
|
||||
|
@ -116,7 +121,7 @@ html[dir="rtl"] #top-content .tools-all {
|
|||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
|
||||
#top-content .jingle.streaming .streaming-items a.stop:active {
|
||||
#top-content .call.streaming .streaming-items a.stop:active {
|
||||
background: #a92134;
|
||||
padding-top: 6px;
|
||||
padding-bottom: 6px;
|
||||
|
@ -135,23 +140,27 @@ html[dir="rtl"] #top-content .tools-all {
|
|||
|
||||
#top-content .notifications:hover,
|
||||
#top-content .music:hover,
|
||||
#top-content .jingle.streaming.video:hover {
|
||||
#top-content .call.streaming.video:hover,
|
||||
.in_muji_call #top-content .call.streaming.audio:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#top-content .music:hover,
|
||||
#top-content .notifications:hover,
|
||||
#top-content .jingle.streaming.video:hover,
|
||||
#top-content .call.streaming.video:hover,
|
||||
.in_muji_call #top-content .call.streaming.audio:hover,
|
||||
#top-content .music:focus,
|
||||
#top-content .notifications:focus,
|
||||
#top-content .jingle.streaming.video:focus {
|
||||
#top-content .call.streaming.video:focus,
|
||||
.in_muji_call #top-content .call.streaming.audio:focus {
|
||||
background-color: rgb(232,241,243);
|
||||
background-color: rgba(232,241,243,0.7);
|
||||
}
|
||||
|
||||
#top-content .music:active,
|
||||
#top-content .notifications:active,
|
||||
#top-content .jingle.streaming.video:active {
|
||||
#top-content .call.streaming.video:active,
|
||||
.in_muji_call #top-content .call.streaming.audio:active {
|
||||
background-color: rgb(232,241,243);
|
||||
background-color: rgba(232,241,243,0.8);
|
||||
}
|
||||
|
@ -485,25 +494,25 @@ html[dir="rtl"] .music-content .list {
|
|||
height: 15px;
|
||||
}
|
||||
|
||||
.jingle-content {
|
||||
.call-content {
|
||||
text-shadow: none;
|
||||
width: 230px;
|
||||
right: -102px;
|
||||
}
|
||||
|
||||
html[dir="rtl"] .jingle-content {
|
||||
html[dir="rtl"] .call-content {
|
||||
left: -102px;
|
||||
}
|
||||
|
||||
.jingle-content .tools-content-subitem {
|
||||
.call-content .tools-content-subitem {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.jingle-content .jingle-notify {
|
||||
.call-content .call-notify {
|
||||
height: 90px;
|
||||
}
|
||||
|
||||
.jingle-content .jingle-notify .avatar-pane {
|
||||
.call-content .call-notify .avatar-pane {
|
||||
width: 100px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
|
@ -517,12 +526,12 @@ html[dir="rtl"] .jingle-content {
|
|||
border-top-left-radius: 4px;
|
||||
}
|
||||
|
||||
html[dir="rtl"] .jingle-content .jingle-notify .avatar-pane {
|
||||
html[dir="rtl"] .call-content .call-notify .avatar-pane {
|
||||
left: auto;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.jingle-content .jingle-notify .avatar-pane .avatar-container {
|
||||
.call-content .call-notify .avatar-pane .avatar-container {
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
|
@ -531,7 +540,7 @@ html[dir="rtl"] .jingle-content .jingle-notify .avatar-pane {
|
|||
top: 0;
|
||||
}
|
||||
|
||||
.jingle-content .jingle-notify .avatar-pane .avatar-container .avatar {
|
||||
.call-content .call-notify .avatar-pane .avatar-container .avatar {
|
||||
min-height: 100%;
|
||||
max-height: 100%;
|
||||
min-width: 100%;
|
||||
|
@ -543,7 +552,7 @@ html[dir="rtl"] .jingle-content .jingle-notify .avatar-pane {
|
|||
border-bottom-left-radius: 5px;
|
||||
}
|
||||
|
||||
html[dir="rtl"] .jingle-content .jingle-notify .avatar-pane .avatar-container .avatar {
|
||||
html[dir="rtl"] .call-content .call-notify .avatar-pane .avatar-container .avatar {
|
||||
-moz-border-radius: 0;
|
||||
-webkit-border-radius: 0;
|
||||
border-radius: 0;
|
||||
|
@ -555,45 +564,45 @@ html[dir="rtl"] .jingle-content .jingle-notify .avatar-pane .avatar-container .a
|
|||
border-bottom-right-radius: 5px;
|
||||
}
|
||||
|
||||
.jingle-content .jingle-notify .avatar-pane .icon {
|
||||
.call-content .call-notify .avatar-pane .icon {
|
||||
opacity: 0.75;
|
||||
position: absolute;
|
||||
left: 8px;
|
||||
bottom: 8px;
|
||||
}
|
||||
|
||||
.jingle-content .jingle-notify.notify-call_audio .avatar-pane .icon {
|
||||
.call-content .call-notify.notify-call_audio .avatar-pane .icon {
|
||||
background-position: 0 -120px;
|
||||
width: 33px;
|
||||
height: 33px;
|
||||
}
|
||||
|
||||
.jingle-content .jingle-notify.notify-call_video .avatar-pane .icon {
|
||||
.call-content .call-notify.notify-call_video .avatar-pane .icon {
|
||||
background-position: 0 -154px;
|
||||
width: 33px;
|
||||
height: 22px;
|
||||
}
|
||||
|
||||
.jingle-content .jingle-notify.notify-connecting .avatar-pane .icon {
|
||||
.call-content .call-notify.notify-connecting .avatar-pane .icon {
|
||||
background-position: 0 -175px;
|
||||
width: 33px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.jingle-content .jingle-notify.notify-error .avatar-pane .icon {
|
||||
.call-content .call-notify.notify-error .avatar-pane .icon {
|
||||
background-position: 0 -207px;
|
||||
width: 33px;
|
||||
height: 31px;
|
||||
}
|
||||
|
||||
.jingle-content .jingle-notify.notify-local_ended .avatar-pane .icon,
|
||||
.jingle-content .jingle-notify.notify-remote_ended .avatar-pane .icon {
|
||||
.call-content .call-notify.notify-local_ended .avatar-pane .icon,
|
||||
.call-content .call-notify.notify-remote_ended .avatar-pane .icon {
|
||||
background-position: 0 -238px;
|
||||
width: 33px;
|
||||
height: 34px;
|
||||
}
|
||||
|
||||
.jingle-content .jingle-notify .notification-content {
|
||||
.call-content .call-notify .notification-content {
|
||||
color: #ffffff;
|
||||
text-align: left;
|
||||
text-shadow: 0 1px 1px rgb(0,0,0);
|
||||
|
@ -606,28 +615,28 @@ html[dir="rtl"] .jingle-content .jingle-notify .avatar-pane .avatar-container .a
|
|||
left: 100px;
|
||||
}
|
||||
|
||||
html[dir="rtl"] .jingle-content .jingle-notify .notification-content {
|
||||
html[dir="rtl"] .call-content .call-notify .notification-content {
|
||||
text-align: right;
|
||||
right: 100px;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.jingle-content .jingle-notify .notification-content .fullname,
|
||||
.jingle-content .jingle-notify .notification-content .text {
|
||||
.call-content .call-notify .notification-content .fullname,
|
||||
.call-content .call-notify .notification-content .text {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.jingle-content .jingle-notify .notification-content .fullname {
|
||||
.call-content .call-notify .notification-content .fullname {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.jingle-content .jingle-notify .notification-content .text {
|
||||
.call-content .call-notify .notification-content .text {
|
||||
font-size: 12px;
|
||||
text-transform: lowercase;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.jingle-content .jingle-notify .notification-content .reply-buttons {
|
||||
.call-content .call-notify .notification-content .reply-buttons {
|
||||
text-align: center;
|
||||
padding-left: 10px;
|
||||
position: absolute;
|
||||
|
@ -636,31 +645,31 @@ html[dir="rtl"] .jingle-content .jingle-notify .notification-content {
|
|||
bottom: 20px;
|
||||
}
|
||||
|
||||
html[dir="rtl"] .jingle-content .jingle-notify .notification-content .reply-buttons {
|
||||
html[dir="rtl"] .call-content .call-notify .notification-content .reply-buttons {
|
||||
padding-left: 0;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.jingle-content .jingle-notify .notification-content .reply-buttons a.reply-button {
|
||||
.call-content .call-notify .notification-content .reply-buttons a.reply-button {
|
||||
margin-left: 4px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
html[dir="rtl"] .jingle-content .jingle-notify .notification-content .reply-buttons a.reply-button {
|
||||
html[dir="rtl"] .call-content .call-notify .notification-content .reply-buttons a.reply-button {
|
||||
margin-left: 0;
|
||||
margin-right: 4px;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.jingle-content .jingle-notify .notification-content .reply-buttons a.reply-button:active {
|
||||
.call-content .call-notify .notification-content .reply-buttons a.reply-button:active {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.jingle-content .jingle-notify .notification-content .reply-buttons a.reply-button.first {
|
||||
.call-content .call-notify .notification-content .reply-buttons a.reply-button.first {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
html[dir="rtl"] .jingle-content .jingle-notify .notification-content .reply-buttons a.reply-button.first {
|
||||
html[dir="rtl"] .call-content .call-notify .notification-content .reply-buttons a.reply-button.first {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
|
|