1
0
Fork 0
mirror of https://github.com/YunoHost-Apps/jappix_ynh.git synced 2024-09-03 19:26:19 +02:00

Update sources to Jappix 1.1.0

This commit is contained in:
mbugeia 2014-11-25 20:12:58 +01:00
parent 3f6874b78a
commit cd9dd26e14
688 changed files with 56044 additions and 180105 deletions

11
source/.gitignore vendored Normal file
View file

@ -0,0 +1,11 @@
mini/
store/
tmp/cache/
tmp/jingle/
tmp/avatar/
tmp/archives/
tmp/send/
log/
test/node_modules/
.DS_Store
*.esproj

View file

@ -4,6 +4,57 @@ Jappix Changelog
Here's the log of what has changed over the Jappix releases. 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) One, v1.0.3 (March 2014)
------------------------ ------------------------

View file

@ -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 * 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-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-0060: Publish-Subscribe *v1.13*
* XEP-0124: Bidirectional-streams Over Synchronous HTTP (BOSH) *v1.10* * XEP-0066: Out of Band Data *v1.5*
* XEP-0115: Entity Capabilities *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-0107: User Mood *v1.2*
* XEP-0108: User Activity *v1.3* * XEP-0108: User Activity *v1.3*
* XEP-0115: Entity Capabilities *v1.5*
* XEP-0118: User Tune *v1.2* * XEP-0118: User Tune *v1.2*
* XEP-0080: User Location *v1.7* * XEP-0124: Bidirectional-streams Over Synchronous HTTP (BOSH) *v1.10*
* 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-0144: Roster Item Exchange *v1.0* * XEP-0144: Roster Item Exchange *v1.0*
* XEP-0072: SOAP Over XMPP *v1.0* * XEP-0152: Reachability Addresses *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-0166: Jingle *v1.1* * XEP-0166: Jingle *v1.1*
* XEP-0167: Jingle RTP Sessions *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-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-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-0262: Use of ZRTP in Jingle RTP Sessions *v1.0*
* XEP-0266: Codecs for Jingle Audio *v1.0* * XEP-0266: Codecs for Jingle Audio *v1.0*
* XEP-0269: Jingle Early Media *v0.1* * 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-0293: Jingle RTP Feedback Negotiation *v0.1*
* XEP-0294: Jingle RTP Header Extensions Negotiation *v0.1* * XEP-0294: Jingle RTP Header Extensions Negotiation *v0.1*
* XEP-0299: Codecs for Jingle Video *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-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-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 # Others

View file

@ -32,9 +32,9 @@ Start translating on https://www.transifex.com/projects/p/jappix/ (new translato
Links Links
----- -----
* Jappix project website: http://jappix.org/ * Jappix project website: https://jappix.org/
* Jappix project dev panel: https://github.com/jappix/jappix * 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 main service: https://jappix.com/
* Jappix commercial support: https://jappix.pro/ * Jappix commercial support: https://jappix.pro/

View file

@ -1 +1 @@
One [1.0.3] Primo [1.1.0]

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<jappix xmlns="jappix:file:get"> <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> <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~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> <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> </jappix>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

View file

@ -142,9 +142,7 @@ var AdHoc = (function () {
try { try {
// Click event // Click event
$('#adhoc .bottom .finish').click( $('#adhoc .bottom .finish').click(self.close);
self.close()
);
} catch(e) { } catch(e) {
Console.error('AdHoc.launch', e); Console.error('AdHoc.launch', e);
} }

View file

@ -20,6 +20,28 @@ var Anonymous = (function () {
var self = {}; 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 * Connected to an anonymous session
* @public * @public
@ -115,12 +137,7 @@ var Anonymous = (function () {
} }
// And we handle everything that happen // And we handle everything that happen
con.registerHandler('message', Message.handle); self._registerHandlers(con);
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);
// We set the anonymous connection parameters // We set the anonymous connection parameters
oArgs = {}; oArgs = {};
@ -165,10 +182,13 @@ var Anonymous = (function () {
Interface.showGeneralWait(); Interface.showGeneralWait();
// Get the vars // Get the vars
if(XMPPLinks.links_var.r) if(XMPPLinks.links_var.r) {
ANONYMOUS_ROOM = 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; ANONYMOUS_NICK = XMPPLinks.links_var.n;
}
// Fire the login action // Fire the login action
self.login(HOST_ANONYMOUS); self.login(HOST_ANONYMOUS);

View 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;
})();

View file

@ -29,7 +29,7 @@ var Audio = (function () {
* @private * @private
* @return {boolean} * @return {boolean}
*/ */
self._is_supported = function() { self._isSupported = function() {
is_supported = true; is_supported = true;
@ -38,7 +38,7 @@ var Audio = (function () {
is_supported = false; is_supported = false;
} }
} catch(e) { } catch(e) {
Console.error('Audio._is_supported', e); Console.error('Audio._isSupported', e);
} finally { } finally {
return is_supported; 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 * Plays the given sound ID
* @public * @public
@ -58,43 +109,13 @@ var Audio = (function () {
repeat = (typeof repeat === 'boolean') ? repeat : false; repeat = (typeof repeat === 'boolean') ? repeat : false;
// Not supported? // Not supported?
if(!self._is_supported()) { if(!self._isSupported()) {
return false; return false;
} }
// If the sounds are enabled // If the sounds are enabled
if(DataStore.getDB(Connection.desktop_hash, 'options', 'sounds') === '1') { if(DataStore.getDB(Connection.desktop_hash, 'options', 'sounds') === '1') {
// If the audio elements aren't yet in the DOM self._appendDOM();
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>'
);
}
// We play the target sound // We play the target sound
var audio_raw_sel = $('#audio audio').filter('#' + name); var audio_raw_sel = $('#audio audio').filter('#' + name);
@ -146,7 +167,7 @@ var Audio = (function () {
try { try {
// Not supported? // Not supported?
if(!self._is_supported()) { if(!self._isSupported()) {
return false; return false;
} }

View file

@ -32,14 +32,17 @@ var Autocompletion = (function () {
try { try {
// Put the two strings into lower case // Put the two strings into lower case
var sA = a[0].toLowerCase(); var sort_a = a[0].toLowerCase();
var sB = b[0].toLowerCase(); var sort_b = b[0].toLowerCase();
// Process the sort // Process the sort
if(sA > sB) if(sort_a > sort_b) {
return 1; return 1;
if(sA < sB) }
if(sort_a < sort_b) {
return -1; return -1;
}
} catch(e) { } catch(e) {
Console.error('Autocompletion.caseInsensitiveSort', 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 * Split a query into its subqueries ready to be used in autocompletion
* The function return an array containing two others : the first with subqueries * @public
* 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 ", ""]
* @param {string} query * @param {string} query
* @return {Array} * @return {object}
*/ */
self.getSubQueries = function(query) { self.getSubQueries = function(query) {
var subqueries = []; var result = [];
var remnants = [];
var queryLastCharPos = query.length - 1; try {
var spaceCounter = 0; var subqueries = [];
for (var i=queryLastCharPos; i>=0; i--) { var remnants = [];
// Search from the end of the query
var iChar = query.charAt(i); var query_last_char_pos = query.length - 1;
if (spaceCounter === 0 && iChar.search(/\s/) === 0) { var space_counter = 0;
// the first "local" space was found var cur_char;
// add the subquery and its remnant to results
subqueries.push(query.slice(i+1)); for(var i = query_last_char_pos; i >= 0; i--) {
remnants.push(query.slice(0, i+1)); // Search from the end of the query
spaceCounter++; cur_char = query.charAt(i);
} else {
spaceCounter = 0; 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(space_counter === 0) {
// If the first char of the query is not a space, add the full query to results // If the first char of the query is not a space, add the full query to results
subqueries.push(query); subqueries.push(query);
remnants.push(""); 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 { try {
// Replace forbidden characters in regex // Replace forbidden characters in regex
query = Common.escapeRegex(query); query = Common.escapeRegex(query);
// Build an array of regex to use // Build an array of regex to use
var queryRegExp = []; var query_reg_exp = [];
for (i = 0; i<query.length; i++) {
if (query[i] !== null) { for(i = 0; i < query.length; i++) {
queryRegExp.push(new RegExp('(^)' + query[i], 'gi')); if(query[i] !== null) {
query_reg_exp.push(
new RegExp('(^)' + query[i], 'gi')
);
} }
} }
// Search in the roster // Search in the roster
var nick, regex;
$('#' + id + ' .user').each(function() { $('#' + id + ' .user').each(function() {
var nick = $(this).find('.name').text(); nick = $(this).find('.name').text();
for (i = 0; i<queryRegExp.length; i++) {
var regex = queryRegExp[i]; for(i = 0; i < query_reg_exp.length; i++) {
regex = query_reg_exp[i];
if(nick.match(regex)) { if(nick.match(regex)) {
results.push([nick, i]); results.push([nick, i]);
} }
} }
}); });
// Sort the array // Sort the array
results = results.sort(self.caseInsensitiveSort); results = results.sort(
self.caseInsensitiveSort
);
} catch(e) { } catch(e) {
Console.error('Autocompletion.process', e); Console.error('Autocompletion.process', e);
} finally { } finally {
@ -139,7 +165,8 @@ var Autocompletion = (function () {
self.reset = function(hash) { self.reset = function(hash) {
try { 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) { } catch(e) {
Console.error('Autocompletion.reset', e); Console.error('Autocompletion.reset', e);
} }
@ -157,36 +184,34 @@ var Autocompletion = (function () {
try { try {
// Initialize // Initialize
var vSelector = $('#' + hash + ' .message-area'); var message_area_sel = $('#' + hash + ' .message-area');
var value = vSelector.val(); var value = message_area_sel.val();
if(!value) { if(!value) {
self.reset(hash); self.reset(hash);
} }
var query = vSelector.attr('data-autocompletion-query'); var query = message_area_sel.attr('data-autocompletion-query');
if(query === undefined) { if(query === undefined) {
// The autocompletion has not been yet launched // The autocompletion has not been yet launched
query = self.getSubQueries(value); query = self.getSubQueries(value);
vSelector.attr('data-autocompletion-query', JSON.stringify(query)); message_area_sel.attr('data-autocompletion-query', JSON.stringify(query));
} else { } else {
// The autocompletion has already stored a query // The autocompletion has already stored a query
query = JSON.parse(query); query = JSON.parse(query);
} }
// Get the pointer // Get the pointer
var pointer = vSelector.attr('data-autocompletion-pointer'); var pointer = message_area_sel.attr('data-autocompletion-pointer');
var i = 0; var i = pointer ? parseInt(pointer, 10) : 0;
if(pointer)
i = parseInt(pointer);
// We get the nickname // We get the nickname
var nickResult = self.process(query[0], hash)[i]; var nick_result = self.process(query[0], hash)[i];
var nick; var nick;
if (nickResult !== undefined) {
nick = nickResult[0]; if(nick_result !== undefined) {
nick = nick_result[0];
} }
// Shit, this is my nick! // Shit, this is my nick!
@ -195,21 +220,26 @@ var Autocompletion = (function () {
i++; i++;
// Get the next nick // Get the next nick
nickResult = self.process(query[0], hash)[i]; nick_result = self.process(query[0], hash)[i];
if (nickResult !== undefined) {
nick = nickResult[0]; if (nick_result !== undefined) {
nick = nick_result[0];
} }
} }
// We quote the nick // We quote the nick
if((nickResult !== undefined) && (nick !== undefined)) { if((nick_result !== undefined) && (nick !== undefined)) {
// Increment // Increment
i++; i++;
var message = query[1][nickResult[1]];
Utils.quoteMyNick(hash, nick, message); Utils.quoteMyNick(
hash,
nick,
query[1][nick_result[1]]
);
// Put a pointer // Put a pointer
vSelector.attr('data-autocompletion-pointer', i); message_area_sel.attr('data-autocompletion-pointer', i);
} }
} catch(e) { } catch(e) {
Console.error('Autocompletion.create', e); Console.error('Autocompletion.create', e);

View file

@ -39,8 +39,9 @@ var Avatar = (function () {
try { try {
// No need to get the avatar, another process is yet running // 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; return false;
}
// Initialize: XML data is in one SQL entry, because some browser are sloooow with SQL requests // Initialize: XML data is in one SQL entry, because some browser are sloooow with SQL requests
var xml = Common.XMLFromString( var xml = Common.XMLFromString(
@ -49,8 +50,9 @@ var Avatar = (function () {
var forced = false; var forced = false;
// Retrieving forced? // Retrieving forced?
if($(xml).find('forced').text() == 'true') if($(xml).find('forced').text() == 'true') {
forced = true; forced = true;
}
// No avatar in presence // No avatar in presence
if(!photo && !forced && enabled == 'true') { if(!photo && !forced && enabled == 'true') {
@ -72,8 +74,9 @@ var Avatar = (function () {
var updated = false; var updated = false;
// Process the checksum of the avatar // Process the checksum of the avatar
if(checksum == photo || photo == 'forget' || forced) if(checksum == photo || photo == 'forget' || forced) {
updated = true; updated = true;
}
// If the avatar is yet stored and a new retrieving is not needed // If the avatar is yet stored and a new retrieving is not needed
if(mode == 'cache' && type && binval && checksum && updated) { if(mode == 'cache' && type && binval && checksum && updated) {
@ -141,8 +144,9 @@ var Avatar = (function () {
oChecksum = DataStore.getDB(Connection.desktop_hash, 'checksum', 1); oChecksum = DataStore.getDB(Connection.desktop_hash, 'checksum', 1);
// Avoid the "null" value // Avoid the "null" value
if(!oChecksum) if(!oChecksum) {
oChecksum = ''; oChecksum = '';
}
} }
// vCard not empty? // vCard not empty?
@ -151,10 +155,12 @@ var Avatar = (function () {
if(handleFrom == Common.getXID()) { if(handleFrom == Common.getXID()) {
// Get the names // Get the names
var names = Name.generateBuddy(iq); var names = Name.generateBuddy(iq);
var phone_number = find.find('TEL:has(NUMBER):first NUMBER:first').text();
// Write the values to the database // Write the values to the database
DataStore.setDB(Connection.desktop_hash, 'profile', 'name', names[0]); DataStore.setDB(Connection.desktop_hash, 'profile', 'name', names[0]);
DataStore.setDB(Connection.desktop_hash, 'profile', 'nick', names[1]); DataStore.setDB(Connection.desktop_hash, 'profile', 'nick', names[1]);
DataStore.setDB(Connection.desktop_hash, 'profile', 'phone', phone_number);
} }
// We get the avatar // We get the avatar
@ -170,12 +176,11 @@ var Avatar = (function () {
// Enough data // Enough data
else { else {
// No type? // No type?
if(!aType) if(!aType) {
aType = 'image/png'; aType = 'image/png';
} else {
// Process the checksum
else
aChecksum = hex_sha1(Base64.decode(aBinval)); aChecksum = hex_sha1(Base64.decode(aBinval));
}
} }
// We display the user avatar // We display the user avatar
@ -197,17 +202,19 @@ var Avatar = (function () {
// Define a proper checksum // Define a proper checksum
var pChecksum = aChecksum; var pChecksum = aChecksum;
if(pChecksum == 'none') if(pChecksum == 'none') {
pChecksum = ''; pChecksum = '';
}
// Update our temp. checksum // Update our temp. checksum
DataStore.setDB(Connection.desktop_hash, 'checksum', 1, pChecksum); DataStore.setDB(Connection.desktop_hash, 'checksum', 1, pChecksum);
// Send the stanza // Send the stanza
if(!Presence.first_sent) if(!Presence.first_sent) {
Storage.get(NS_OPTIONS); Storage.get(NS_OPTIONS);
else if(DataStore.hasPersistent()) } else if(DataStore.hasPersistent()) {
Presence.sendActions(pChecksum); Presence.sendActions(pChecksum);
}
} }
} catch(e) { } catch(e) {
Console.error('Avatar.handle', e); Console.error('Avatar.handle', e);
@ -255,10 +262,11 @@ var Avatar = (function () {
var code = '<img class="avatar" src="'; var code = '<img class="avatar" src="';
// If the avatar exists // If the avatar exists
if((type != 'none') && (binval != 'none')) if((type != 'none') && (binval != 'none')) {
code += 'data:' + type + ';base64,' + binval; code += 'data:' + type + ';base64,' + binval;
else } else {
code += './images/others/default-avatar.png'; code += './images/others/default-avatar.png';
}
code += '" alt="" />'; code += '" alt="" />';

View file

@ -20,6 +20,137 @@ var Board = (function () {
var self = {}; 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> &raquo; <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 * Creates a board panel
* @public * @public
@ -35,93 +166,25 @@ var Board = (function () {
// Info // Info
if(type == 'info') { if(type == 'info') {
switch(id) { text = self._generateBoardInfo(id);
// Password change } else {
case 1: text = self._generateBoardError(id);
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> &raquo; <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;
}
} }
// No text? // No text?
if(!text) if(!text) {
return false; return false;
}
// Append the content // 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) // Events (click and auto-hide)
$('#board .one-board.' + type + '[data-id="' + id + '"]') self._attachEvents(
$('#board .one-board.' + type + '[data-id="' + id + '"]')
.click(function() { );
self.closeThis(this);
})
.oneTime('5s', function() {
self.closeThis(this);
})
.slideDown();
return true; return true;
} catch(e) { } catch(e) {
@ -235,7 +298,7 @@ var Board = (function () {
try { try {
// Cannot process? // Cannot process?
if(Common.isFocused() || !content || !(window.webkitNotifications || window.Notification)) { if(Common.isFocused() || !content || !self.NOTIFICATION) {
return; return;
} }
@ -248,11 +311,13 @@ var Board = (function () {
var avatar_xml = Common.XMLFromString( var avatar_xml = Common.XMLFromString(
DataStore.getPersistent('global', 'avatar', xid) DataStore.getPersistent('global', 'avatar', xid)
); );
var avatar_type = $(avatar_xml).find('type').text() || 'image/png'; var avatar_type = $(avatar_xml).find('type').text() || 'image/png';
var avatar_binval = $(avatar_xml).find('binval').text(); 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; icon = 'data:' + avatar_type + ';base64,' + avatar_binval;
}
} }
} }
@ -261,8 +326,17 @@ var Board = (function () {
title = Common._e("New event!"); title = Common._e("New event!");
} }
// Click callback // Create notification
var cb_click_fn = function() { var notification = new self.NOTIFICATION(title, {
dir: 'auto',
lang: '',
body: content,
tag: type,
icon: icon
});
// Click event
notification.onclick = function() {
// Click action? // Click action?
switch(type) { switch(type) {
case 'chat': case 'chat':
@ -281,53 +355,17 @@ var Board = (function () {
window.focus(); window.focus();
// Remove notification // 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() { return notification;
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;
} catch(e) { } catch(e) {
Console.error('Board.quick', e); Console.error('Board.quick', e);
} }
@ -343,21 +381,7 @@ var Board = (function () {
self.quickPermission = function() { self.quickPermission = function() {
try { try {
try { self.NOTIFICATION.requestPermission();
// 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();
}
} catch(e) { } catch(e) {
Console.error('Board.quickPermission', e); Console.error('Board.quickPermission', e);
} }
@ -376,8 +400,9 @@ var Board = (function () {
// Fires quickPermission() on document click // Fires quickPermission() on document click
$(document).click(function() { $(document).click(function() {
// Ask for permission to use quick boards // Ask for permission to use quick boards
if((typeof con != 'undefined') && con.connected()) if((typeof con != 'undefined') && con.connected()) {
self.quickPermission(); self.quickPermission();
}
}); });
} catch(e) { } catch(e) {
Console.error('Board.launch', e); Console.error('Board.launch', e);

View file

@ -31,6 +31,7 @@ var Bubble = (function () {
// Destroy all the elements // Destroy all the elements
$('.bubble.hidable:visible').hide(); $('.bubble.hidable:visible').hide();
$('.bubble.removable').remove(); $('.bubble.removable').remove();
$('body').off('click'); $('body').off('click');
} catch(e) { } catch(e) {
Console.error('Bubble.close', e); Console.error('Bubble.close', e);
@ -53,8 +54,9 @@ var Bubble = (function () {
// Hidable bubbles special things // Hidable bubbles special things
if($(selector).is('.hidable')) { if($(selector).is('.hidable')) {
// This bubble is yet displayed? So abort! // This bubble is yet displayed? So abort!
if($(selector).is(':visible')) if($(selector).is(':visible')) {
return self.close(); return self.close();
}
// Close all the bubbles // Close all the bubbles
self.close(); self.close();
@ -66,8 +68,9 @@ var Bubble = (function () {
// Removable bubbles special things // Removable bubbles special things
else { else {
// This bubble is yet added? So abort! // This bubble is yet added? So abort!
if(Common.exists(selector)) if(Common.exists(selector)) {
return self.close(); return self.close();
}
// Close all the bubbles // Close all the bubbles
self.close(); self.close();
@ -78,8 +81,9 @@ var Bubble = (function () {
var target = evt.target; var target = evt.target;
// If this is a click away from a bubble // If this is a click away from a bubble
if(!$(target).parents('.ibubble').size()) if(!$(target).parents('.ibubble').size()) {
self.close(); self.close();
}
}); });
} catch(e) { } catch(e) {
Console.error('Bubble.show', e); Console.error('Bubble.show', e);

View 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;
})();

View file

@ -20,6 +20,444 @@ var Caps = (function () {
var self = {}; 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 * Reads a stored Caps
* @public * @public
@ -47,62 +485,12 @@ var Caps = (function () {
self.myDiscoInfos = function() { self.myDiscoInfos = function() {
try { try {
var disco_base = [ var disco_base = self.disco_infos.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
];
var disco_jingle = JSJaCJingle_disco(); var disco_jingle = JSJaCJingle.disco();
var disco_all = disco_base.concat(disco_jingle); var disco_all = disco_base.concat(disco_jingle);
return disco_all; return Utils.uniqueArrayValues(disco_all);
} catch(e) { } catch(e) {
Console.error('Caps.myDiscoInfos', e); Console.error('Caps.myDiscoInfos', e);
} }
@ -169,103 +557,17 @@ var Caps = (function () {
self.handleDiscoInfos = function(iq) { self.handleDiscoInfos = function(iq) {
try { try {
if(!iq || (iq.getType() == 'error')) if(!iq || (iq.getType() == 'error')) {
return; return;
}
// IQ received, get some values
var from = Common.fullXID(Common.getStanzaFrom(iq)); var from = Common.fullXID(Common.getStanzaFrom(iq));
var query = iq.getQuery(); var query = iq.getQuery();
// Generate the CAPS-processing values // Parse values
var identities = []; var identities = self._parseDiscoIdentities(query);
var features = []; var features = self._parseDiscoFeatures(query);
var data_forms = []; var data_forms = self._parseDiscoDataForms(query);
// 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);
}
});
// Process the CAPS // Process the CAPS
var caps = self.process(identities, features, data_forms); var caps = self.process(identities, features, data_forms);
@ -309,8 +611,9 @@ var Caps = (function () {
var xid = Common.bareXID(from); var xid = Common.bareXID(from);
// This comes from a private groupchat chat? // This comes from a private groupchat chat?
if(Utils.isPrivate(xid)) if(Utils.isPrivate(xid)) {
xid = from; xid = from;
}
hash = hex_md5(xid); hash = hex_md5(xid);
@ -326,96 +629,20 @@ var Caps = (function () {
}); });
// Paths // Paths
var path = $('#' + hash); var path_sel = $('#' + hash);
var roster_path = $('#roster .buddy.' + hash); var roster_sel = $('#roster .buddy.' + hash);
var roster_jingle_path = roster_path.find('.buddy-infos .call-jingle'); var message_area_sel = path_sel.find('.message-area');
var style_sel = path_sel.find('.chat-tools-style');
var message_area = path.find('.message-area'); var file_sel = path_sel.find('.chat-tools-file');
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');
// Apply xHTML-IM // Apply Features
if(NS_XHTML_IM in features) { self._applyDiscoXHTMLIM(xid, features, style_sel, message_area_sel);
style.show(); self._applyDiscoJingle(xid, path_sel, roster_sel);
} else { self._applyDiscoOOB(xid, features, file_sel);
// Remove the tooltip elements self._applyDiscoReceipts(xid, features, message_area_sel);
style.hide(); self._applyDiscoCorrection(xid, features, path_sel);
style.find('.bubble-style').remove(); self._applyDiscoMarkers(xid, features, path_sel);
self._applyDiscoAttention(xid, features, path_sel);
// 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');
}
} catch(e) { } catch(e) {
Console.error('Caps.displayDiscoInfos', e); Console.error('Caps.displayDiscoInfos', e);
} }
@ -426,39 +653,39 @@ var Caps = (function () {
/** /**
* Generates the CAPS hash * Generates the CAPS hash
* @public * @public
* @param {object} cIdentities * @param {object} identities
* @param {object} cFeatures * @param {object} features
* @param {object} cDataForms * @param {object} dataforms
* @return {string} * @return {string}
*/ */
self.process = function(cIdentities, cFeatures, cDataForms) { self.process = function(identities, features, dataforms) {
try { try {
// Initialize // Initialize
var cString = ''; var caps_str = '';
// Sort the arrays // Sort the arrays
cIdentities = cIdentities.sort(); identities = identities.sort();
cFeatures = cFeatures.sort(); features = features.sort();
cDataForms = cDataForms.sort(); dataforms = dataforms.sort();
// Process the sorted identity string // Process the sorted identity string
for(var a in cIdentities) { for(var a in identities) {
cString += cIdentities[a] + '<'; caps_str += identities[a] + '<';
} }
// Process the sorted feature string // Process the sorted feature string
for(var b in cFeatures) { for(var b in features) {
cString += cFeatures[b] + '<'; caps_str += features[b] + '<';
} }
// Process the sorted data-form string // Process the sorted data-form string
for(var c in cDataForms) { for(var c in dataforms) {
cString += cDataForms[c] + '<'; caps_str += dataforms[c] + '<';
} }
// Process the SHA-1 hash // Process the SHA-1 hash
var cHash = b64_sha1(cString); var cHash = b64_sha1(caps_str);
return cHash; return cHash;
} catch(e) { } catch(e) {
@ -477,7 +704,12 @@ var Caps = (function () {
try { try {
return self.process( return self.process(
['client/web//Jappix'], [
self.disco_infos.identity.category + '/' +
self.disco_infos.identity.type + '//' +
self.disco_infos.identity.name
],
self.myDiscoInfos(), self.myDiscoInfos(),
[] []
); );
@ -507,8 +739,14 @@ var Caps = (function () {
var max_priority = null; var max_priority = null;
var cur_xid_full, cur_presence_sel, cur_caps, cur_features, cur_priority; var cur_xid_full, cur_presence_sel, cur_caps, cur_features, cur_priority;
for(var cur_resource in Presence.resources(xid)) { var resources_obj = Presence.resources(xid);
cur_xid_full = xid + '/' + cur_resource; 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_presence_sel = $(Presence.readStanza(cur_xid_full));
cur_priority = parseInt((cur_presence_sel.find('priority').text() || 0), 10); cur_priority = parseInt((cur_presence_sel.find('priority').text() || 0), 10);
@ -523,6 +761,14 @@ var Caps = (function () {
selected_xid = cur_xid_full; 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) { } catch(e) {
Console.error('Caps.getFeatureResource', e); Console.error('Caps.getFeatureResource', e);
@ -538,4 +784,4 @@ var Caps = (function () {
*/ */
return self; return self;
})(); })();

View file

@ -22,7 +22,7 @@ var Carbons = (function () {
/** /**
* Configures Message Carbons options * Configures Message Carbons options
* @public * @private
* @param {string} type * @param {string} type
* @return {undefined} * @return {undefined}
*/ */
@ -50,7 +50,7 @@ var Carbons = (function () {
/** /**
* Configures Message Carbons options * Configures Message Carbons options
* @public * @private
* @param {object} iq * @param {object} iq
* @param {string} type * @param {string} type
* @return {undefined} * @return {undefined}
@ -193,6 +193,9 @@ var Carbons = (function () {
} else { } else {
Console.debug('Got a sent message from another resource to: ' + (to || 'none') + ', was ignored because body empty'); 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 { } else {
Console.debug('Got a sent message from another resource to: ' + (to || 'none') + ', was ignored because chat not open'); Console.debug('Got a sent message from another resource to: ' + (to || 'none') + ', was ignored because chat not open');
} }

View file

@ -20,6 +20,289 @@ var Chat = (function () {
var self = {}; 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 * Correctly opens a new chat
* @public * @public
@ -34,38 +317,40 @@ var Chat = (function () {
try { try {
// No XID? // No XID?
if(!xid) if(!xid) {
return false; return false;
}
// We generate some stuffs // We generate some stuffs
var hash = hex_md5(xid); var hash = hex_md5(xid);
var name; var name;
// Gets the name of the user/title of the room // Gets the name of the user/title of the room
if(title) if(title) {
name = title; name = title;
} else {
else {
// Private groupchat chat // Private groupchat chat
if(type == 'private') if(type == 'private') {
name = Common.thisResource(xid); name = Common.thisResource(xid);
}
// XMPP-ID // XMPP-ID
else if(xid.indexOf('@') != -1) else if(xid.indexOf('@') != -1) {
name = Name.getBuddy(xid); name = Name.getBuddy(xid);
}
// Gateway // Gateway
else else {
name = xid; name = xid;
}
} }
// If the target div does not exist // If the target div does not exist
if(!Common.exists('#' + hash)) { if(!Common.exists('#' + hash)) {
// We check the type of the chat to open // 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); self.create(hash, xid, name, type);
} else if(type == 'groupchat') {
else if(type == 'groupchat') {
// Try to read the room stored configuration // Try to read the room stored configuration
if(!Utils.isAnonymous() && (!nickname || !password || !title)) { if(!Utils.isAnonymous() && (!nickname || !password || !title)) {
// Catch the room data // Catch the room data
@ -115,71 +400,21 @@ var Chat = (function () {
var escaped_xid = escape(xid); var escaped_xid = escape(xid);
// Special code // Special code
var specialAttributes, specialAvatar, specialName, specialCode, specialLink, specialDisabled, specialStyle, specialMAM; var chat_args = self._generateChatCode(type, id);
// 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 = '';
// Append the chat HTML code // Append the chat HTML code
$('#page-engine').append( $('#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 + '">' + '<div class="top ' + id + '">' +
specialAvatar + chat_args.avatar +
'<div class="name">' + '<div class="name">' +
'<p class="bc-name bc-name-nick">' + nick.htmlEnc() + '</p>' + '<p class="bc-name bc-name-nick">' + nick.htmlEnc() + '</p>' +
specialName + chat_args.name +
'</div>' + '</div>' +
'</div>' + '</div>' +
specialCode + chat_args.code +
'<div class="text">' + '<div class="text">' +
'<div class="footer">' + '<div class="footer">' +
@ -187,7 +422,7 @@ var Chat = (function () {
'<a href="#" class="tools-smileys tools-tooltip talk-images"></a>' + '<a href="#" class="tools-smileys tools-tooltip talk-images"></a>' +
'</div>' + '</div>' +
specialStylePicker + chat_args.style_picker +
'<div class="chat-tools-content chat-tools-file">' + '<div class="chat-tools-content chat-tools-file">' +
'<a href="#" class="tools-file tools-tooltip talk-images"></a>' + '<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>' + '<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>' +
'<div class="compose">' + '<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>' + '</div>' +
'</div>' '</div>'
); );
// Click event: chat cleaner self._generateEvents(path, id, xid);
$(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) { } catch(e) {
Console.error('Chat.generate', e); Console.error('Chat.generate', e);
} }
@ -251,26 +468,32 @@ var Chat = (function () {
var chat_switch = '#page-switch .'; var chat_switch = '#page-switch .';
// Special code // Special code
var specialClass = ' unavailable'; var special_class = ' unavailable';
var show_close = true; var show_close = true;
// Groupchat // Groupchat
if(type == '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; show_close = false;
}
} }
// Generate the HTML code // Generate the HTML code
var html = '<div class="' + id + ' switcher chan" onclick="return Interface.switchChan(\'' + Utils.encodeOnclick(id) + '\')">' + var html = '<div class="' + id + ' switcher chan" onclick="return Interface.switchChan(\'' + Utils.encodeOnclick(id) + '\')">' +
'<div class="icon talk-images' + specialClass + '"></div>' + '<div class="icon talk-images' + special_class + '"></div>' +
'<div class="name">' + nick.htmlEnc() + '</div>'; '<div class="name">' + nick.htmlEnc() + '</div>';
// Show the close button if not MUC and not anonymous // Show the close button if not MUC and not anonymous
if(show_close) 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>'; 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 // Close the HTML
html += '</div>'; html += '</div>';
@ -353,7 +576,7 @@ var Chat = (function () {
// Create the chat switcher // Create the chat switcher
self.generateSwitch(type, hash, xid, nick); self.generateSwitch(type, hash, xid, nick);
// If the user is not in our roster // Is this a chat?
if(type == 'chat') { if(type == 'chat') {
// MAM? Get archives from there! // MAM? Get archives from there!
if(Features.enabledMAM()) { if(Features.enabledMAM()) {
@ -373,32 +596,43 @@ var Chat = (function () {
var friend_hash = hex_md5(xid); var friend_hash = hex_md5(xid);
// Add chat history HTML // Add chat history HTML
$('#' + hash + ' .content').append(chat_history); var path_sel = $('#' + hash);
path_sel.find('.content').append(chat_history);
// Filter old groups & messages // Filter old groups & messages
$('#' + hash + ' .one-group[data-type="user-message"]').addClass('from-history').attr('data-type', 'old-message'); var one_group_sel = path_sel.find('.one-group');
$('#' + hash + ' .user-message').removeClass('user-message').addClass('old-message'); 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 // Regenerate user names
$('#' + hash + ' .one-group.' + my_hash + ' b.name').text(Name.getBuddy(Common.getXID())); one_group_sel.filter('.' + my_hash + ' b.name').text(
$('#' + hash + ' .one-group.' + friend_hash + ' b.name').text(Name.getBuddy(xid)); Name.getBuddy(Common.getXID())
);
one_group_sel.filter('.' + friend_hash + ' b.name').text(
Name.getBuddy(xid)
);
// Regenerate group dates // Regenerate group dates
$('#' + hash + ' .one-group').each(function() { one_group_sel.each(function() {
var current_stamp = parseInt($(this).attr('data-stamp')); var current_stamp = parseInt($(this).attr('data-stamp'), 10);
$(this).find('span.date').text(DateUtils.relative(current_stamp)); $(this).find('span.date').text(DateUtils.relative(current_stamp));
}); });
// Regenerate avatars // 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'); 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'); Avatar.get(xid, 'cache', 'true', 'forget');
}
} }
} }
// Add button // Add button
if(!Roster.isFriend(xid)) if(!Roster.isFriend(xid)) {
$('#' + hash + ' .tools-add').click(function() { $('#' + hash + ' .tools-add').click(function() {
// Hide the icon (to tell the user all is okay) // Hide the icon (to tell the user all is okay)
$(this).hide(); $(this).hide();
@ -406,6 +640,7 @@ var Chat = (function () {
// Send the subscribe request // Send the subscribe request
Roster.addThisContact(xid, nick); Roster.addThisContact(xid, nick);
}).show(); }).show();
}
} }
// We catch the user's informations (like this avatar, vcard, and so on...) // We catch the user's informations (like this avatar, vcard, and so on...)
@ -415,81 +650,12 @@ var Chat = (function () {
Tooltip.icons(xid, hash); Tooltip.icons(xid, hash);
// The event handlers // 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() { // Input events
// Clean notifications for this chat ChatState.events(input_sel, xid, hash, 'chat');
Interface.chanCleanNotify(hash); Markers.events(input_sel, xid, hash, 'chat');
// 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');
} catch(e) { } catch(e) {
Console.error('Chat.create', e); Console.error('Chat.create', e);
} }

View file

@ -36,8 +36,9 @@ var ChatState = (function () {
// If the friend client supports chatstates and is online // 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'))) { if((user_type == 'groupchat') || ((user_type == 'chat') && $('#' + hash + ' .message-area').attr('data-chatstates') && !Common.exists('#page-switch .' + hash + ' .unavailable'))) {
// Already sent? // Already sent?
if(DataStore.getDB(Connection.desktop_hash, 'currentchatstate', xid) == state) if(DataStore.getDB(Connection.desktop_hash, 'currentchatstate', xid) == state) {
return; return;
}
// Write the state // Write the state
DataStore.setDB(Connection.desktop_hash, 'currentchatstate', xid, state); DataStore.setDB(Connection.desktop_hash, 'currentchatstate', xid, state);
@ -48,7 +49,9 @@ var ChatState = (function () {
aMsg.setType(user_type); aMsg.setType(user_type);
// Append the chatstate node // Append the chatstate node
aMsg.appendNode(state, {'xmlns': NS_CHATSTATES}); aMsg.appendNode(state, {
'xmlns': NS_CHATSTATES
});
// Send this! // Send this!
con.send(aMsg); con.send(aMsg);
@ -76,8 +79,9 @@ var ChatState = (function () {
self.reset(hash, type); self.reset(hash, type);
// "gone" state not allowed // "gone" state not allowed
if(state != 'gone') if(state != 'gone') {
$('#page-engine .page-engine-chan .user.' + hash).addClass(state); $('#page-engine .page-engine-chan .user.' + hash).addClass(state);
}
} }
// Chat // Chat
@ -125,7 +129,9 @@ var ChatState = (function () {
$('#' + hash + ' .chatstate').remove(); $('#' + hash + ' .chatstate').remove();
// We create the chatstate // We create the chatstate
$('#' + hash + ' .content').after('<div class="' + state + ' chatstate">' + text + '</div>'); $('#' + hash + ' .content').after(
'<div class="' + state + ' chatstate">' + text + '</div>'
);
} }
} catch(e) { } catch(e) {
Console.error('ChatState.display', e); Console.error('ChatState.display', e);
@ -147,10 +153,11 @@ var ChatState = (function () {
// Define the selector // Define the selector
var selector; var selector;
if(type == 'groupchat') if(type == 'groupchat') {
selector = $('#page-engine .page-engine-chan .user.' + hash); selector = $('#page-engine .page-engine-chan .user.' + hash);
else } else {
selector = $('#page-switch .' + hash + ' .name'); selector = $('#page-switch .' + hash + ' .name');
}
// Reset! // Reset!
selector.removeClass('active composing paused inactive gone'); selector.removeClass('active composing paused inactive gone');
@ -202,30 +209,33 @@ var ChatState = (function () {
target.focus(function() { target.focus(function() {
// Not needed // Not needed
if(target.is(':disabled')) if(target.is(':disabled')) {
return; return;
}
// Something was written, user started writing again // Something was written, user started writing again
if($(this).val()) if($(this).val()) {
self.send('composing', xid, hash); self.send('composing', xid, hash);
}
// Chat only: Nothing in the input, user is active // Chat only: Nothing in the input, user is active
else if(type == 'chat') else if(type == 'chat') {
self.send('active', xid, hash); self.send('active', xid, hash);
}
}); });
target.blur(function() { target.blur(function() {
// Not needed // Not needed
if(target.is(':disabled')) if(target.is(':disabled')) {
return; return;
}
// Something was written, user paused
if($(this).val())
self.send('paused', xid, hash);
// Chat only: Nothing in the input, user is inactive // Something was written, user paused
else if(type == 'chat') if($(this).val()) {
self.send('paused', xid, hash);
} else if(type == 'chat') {
self.send('inactive', xid, hash); self.send('inactive', xid, hash);
}
}); });
} catch(e) { } catch(e) {
Console.error('ChatState.events', e); Console.error('ChatState.events', e);

View file

@ -20,6 +20,10 @@ var Common = (function () {
var self = {}; 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 * Checks if an element exists in the DOM
* @public * @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 * Generates the good XID
* @public * @public
@ -120,20 +147,21 @@ var Common = (function () {
try { try {
// XID needs to be transformed // XID needs to be transformed
// .. and made lowercase (uncertain though this is the right place...)
xid = xid.toLowerCase(); xid = xid.toLowerCase();
if(xid && (xid.indexOf('@') == -1)) { if(xid && (xid.indexOf('@') === -1)) {
// Groupchat // Groupchat XID
if(type == 'groupchat') if(type == 'groupchat') {
return xid + '@' + HOST_MUC; return xid + '@' + HOST_MUC;
}
// One-to-one chat // Gateway XID
if(xid.indexOf('.') == -1) if(self.isDomain(xid) === true) {
return xid + '@' + HOST_MAIN; return xid;
}
// It might be a gateway? // User XID
return xid; return xid + '@' + HOST_MAIN;
} }
// Nothing special (yet bare XID) // Nothing special (yet bare XID)
@ -190,14 +218,16 @@ var Common = (function () {
self.strAfterLast = function(given_char, str) { self.strAfterLast = function(given_char, str) {
try { try {
if(!given_char || !str) if(!given_char || !str) {
return ''; return '';
}
var char_index = str.lastIndexOf(given_char); var char_index = str.lastIndexOf(given_char);
var str_return = str; var str_return = str;
if(char_index >= 0) if(char_index >= 0) {
str_return = str.substr(char_index + 1); str_return = str.substr(char_index + 1);
}
return str_return; return str_return;
} catch(e) { } catch(e) {
@ -223,10 +253,11 @@ var Common = (function () {
// We split if necessary the string // We split if necessary the string
if(index !== -1) { if(index !== -1) {
if(i === 0) if(i === 0) {
toStr = toStr.substr(0, index); toStr = toStr.substr(0, index);
else } else {
toStr = toStr.substr(index + 1); toStr = toStr.substr(index + 1);
}
} }
// We return the value // We return the value
@ -309,8 +340,9 @@ var Common = (function () {
// Spec: http://tools.ietf.org/html/rfc6122#appendix-A // Spec: http://tools.ietf.org/html/rfc6122#appendix-A
try { try {
if(!node) if(!node) {
return node; return node;
}
// Remove prohibited chars // Remove prohibited chars
var 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 * Gets the bare XID from a XID
* @public * @public
@ -360,8 +426,8 @@ var Common = (function () {
xid = self.cutResource(xid); xid = self.cutResource(xid);
// Launch nodeprep // Launch nodeprep
if(xid.indexOf('@') != -1) { if(xid.indexOf('@') !== -1) {
xid = self.nodeprep(self.getXIDNick(xid)) + '@' + self.getXIDHost(xid); xid = self.nodeprep(self.getXIDNick(xid, true)) + '@' + self.getXIDHost(xid);
} }
return xid; return xid;
@ -386,8 +452,9 @@ var Common = (function () {
var resource = self.thisResource(xid); var resource = self.thisResource(xid);
// Any resource? // Any resource?
if(resource) if(resource) {
full += '/' + resource; full += '/' + resource;
}
return full; return full;
} catch(e) { } catch(e) {
@ -401,14 +468,18 @@ var Common = (function () {
* Gets the nick from a XID * Gets the nick from a XID
* @public * @public
* @param {string} aXID * @param {string} aXID
* @param {boolean} raw_explode
* @return {string} * @return {string}
*/ */
self.getXIDNick = function(aXID) { self.getXIDNick = function(aXID, raw_explode) {
try { try {
// Gateway nick? if(raw_explode !== true) {
if(aXID.match(/\\40/)) // Gateway nick?
return self.explodeThis('\\40', aXID, 0); if(aXID.match(/\\40/)) {
return self.explodeThis('\\40', aXID, 0);
}
}
return self.explodeThis('@', aXID, 0); return self.explodeThis('@', aXID, 0);
} catch(e) { } catch(e) {
@ -549,7 +620,7 @@ var Common = (function () {
is_gateway = true; is_gateway = true;
try { try {
if(xid.indexOf('@') != -1) { if(xid.indexOf('@') !== -1) {
is_gateway = false; is_gateway = false;
} }
} catch(e) { } catch(e) {
@ -618,12 +689,14 @@ var Common = (function () {
try { try {
// Negative number (without first 0) // Negative number (without first 0)
if(i > -10 && i < 0) if(i > -10 && i < 0) {
return '-0' + (i * -1); return '-0' + (i * -1);
}
// Positive number (without first 0) // Positive number (without first 0)
if(i < 10 && i >= 0) if(i < 10 && i >= 0) {
return '0' + i; return '0' + i;
}
// All is okay // All is okay
return i; return i;
@ -643,23 +716,31 @@ var Common = (function () {
*/ */
self.escapeRegex = function(query) { self.escapeRegex = function(query) {
if (query instanceof Array) { var result = [];
var result = new Array(query.length);
for(i=0; i<query.length; i++) { 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 { try {
result[i] = Common.escapeRegex(query[i]); result = query.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
} catch(e) { } catch(e) {
Console.error('Common.escapeRegex', e); Console.error('Common.escapeRegex[inner]', e);
result[i] = null;
} }
} }
} catch(e) {
Console.error('Common.escapeRegex', e);
} finally {
return result; return result;
} else {
try {
return query.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
} catch(e) {
Console.error('Common.escapeRegex', e);
}
} }
}; };

View file

@ -29,6 +29,205 @@ var Connection = (function () {
self.resume = false; 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 * Does the user login
* @public * @public
@ -45,7 +244,7 @@ var Connection = (function () {
try { try {
// get optionnal conn handlers // get optionnal conn handlers
oExtend = loginOpts || {}; extend_obj = loginOpts || {};
// We remove the not completed class to avoid problems // We remove the not completed class to avoid problems
$('#home .loginer input').removeClass('please-complete'); $('#home .loginer input').removeClass('please-complete');
@ -71,7 +270,7 @@ var Connection = (function () {
} }
// And we handle everything that happen // And we handle everything that happen
self.setupCon(con, oExtend); self.setupCon(con, extend_obj);
// Generate a resource // Generate a resource
var random_resource = DataStore.getDB(self.desktop_hash, 'session', 'resource'); var random_resource = DataStore.getDB(self.desktop_hash, 'session', 'resource');
@ -79,17 +278,17 @@ var Connection = (function () {
if(!random_resource) { if(!random_resource) {
random_resource = lResource + ' (' + (new Date()).getTime() + ')'; 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) // Store the resource (for reconnection)
DataStore.setDB(self.desktop_hash, 'session', 'resource', random_resource); DataStore.setDB(self.desktop_hash, 'session', 'resource', random_resource);
@ -101,7 +300,7 @@ var Connection = (function () {
DataStore.setDB(self.desktop_hash, 'priority', 1, lPriority); DataStore.setDB(self.desktop_hash, 'priority', 1, lPriority);
// We connect ! // We connect !
con.connect(oArgs); con.connect(con_args);
// Change the page title // Change the page title
Interface.title('wait'); Interface.title('wait');
@ -169,7 +368,9 @@ var Connection = (function () {
// We change the registered information text // We change the registered information text
$('#home .homediv.registerer').append( $('#home .homediv.registerer').append(
'<div class="info success">' + '<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>' '</div>'
); );
@ -179,102 +380,9 @@ var Connection = (function () {
}); });
if((REGISTER_API == 'on') && (domain == HOST_MAIN) && captcha) { if((REGISTER_API == 'on') && (domain == HOST_MAIN) && captcha) {
// Show the waiting image self._doRegisterAPI(username, domain, pass, captcha);
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, '');
}
});
} else { } else {
try { self._doRegisterInBand(username, domain, pass);
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);
}
} }
} catch(e) { } catch(e) {
Console.error('Connection.doRegister', e); Console.error('Connection.doRegister', e);
@ -295,30 +403,28 @@ var Connection = (function () {
try { try {
Console.info('Trying to login anonymously...'); Console.info('Trying to login anonymously...');
var aPath = '#home .anonymouser '; var path_sel = $('#home .anonymouser');
var room = $(aPath + '.room').val(); var room = path_sel.find('.room').val();
var nick = $(aPath + '.nick').val(); var nick = path_sel.find('.nick').val();
// If the form is correctly completed // Form correctly completed?
if(room && nick) { if(room && nick) {
// We remove the not completed class to avoid problems // We remove the not completed class to avoid problems
$('#home .anonymouser input').removeClass('please-complete'); $('#home .anonymouser input').removeClass('please-complete');
// Redirect the user to the anonymous room // Redirect the user to the anonymous room
window.location.href = JAPPIX_LOCATION + '?r=' + room + '&n=' + nick; window.location.href = JAPPIX_LOCATION + '?r=' + room + '&n=' + nick;
} } else {
path_sel.find('input[type="text"]').each(function() {
// We check if the form is entirely completed var this_sel = $(this);
else {
$(aPath + 'input[type="text"]').each(function() {
var select = $(this);
if(!select.val()) if(!this_sel.val()) {
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
select.addClass('please-complete').focus(); this_sel.addClass('please-complete').focus();
}); });
else } else {
select.removeClass('please-complete'); this_sel.removeClass('please-complete');
}
}); });
} }
} catch(e) { } catch(e) {
@ -355,7 +461,7 @@ var Connection = (function () {
Interface.removeGeneralWait(); Interface.removeGeneralWait();
// Init Jingle // Init Jingle
Jingle.init(); Call.init();
} catch(e) { } catch(e) {
Console.error('Connection.handleConnected', e); Console.error('Connection.handleConnected', e);
} }
@ -374,8 +480,9 @@ var Connection = (function () {
// Not resumed? // Not resumed?
if(!self.resume) { if(!self.resume) {
// Remember the session? // 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); DataStore.setPersistent('global', 'session', 1, self.current_session);
}
// We show the chatting app. // We show the chatting app.
Talk.create(); Talk.create();
@ -431,24 +538,32 @@ var Connection = (function () {
* Setups the normal connection * Setups the normal connection
* @public * @public
* @param {object} con * @param {object} con
* @param {object} oExtend * @param {object} extend_obj
* @return {undefined} * @return {undefined}
*/ */
self.setupCon = function(con, oExtend) { self.setupCon = function(con, extend_obj) {
try { try {
// Setup connection handlers var connection_handlers = {
con.registerHandler('message', Message.handle); 'message': Message.handle,
con.registerHandler('presence', Presence.handle); 'presence': Presence.handle,
con.registerHandler('iq', IQ.handle); 'iq': IQ.handle,
con.registerHandler('onconnect', self.handleConnected); 'onconnect': self.handleConnected,
con.registerHandler('onerror', Errors.handle); 'onerror': Errors.handle,
con.registerHandler('ondisconnect', self.handleDisconnected); 'ondisconnect': self.handleDisconnected
};
for(var cur_handler in connection_handlers) {
con.registerHandler(
cur_handler,
connection_handlers[cur_handler]
);
}
// Extended handlers // 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); con.registerHandler(keywd, funct);
}); });
} catch(e) { } catch(e) {
@ -559,51 +674,25 @@ var Connection = (function () {
// Create the HTML code // Create the HTML code
var html = '<div id="reconnect" class="lock">' + var html = '<div id="reconnect" class="lock">' +
'<div class="pane">' + '<div class="pane">' +
Common._e("Due to a network issue, you were disconnected. What do you want to do now?"); Common._e("Due to a network issue, you were disconnected. What do you want to do now?");
// Can we cancel reconnection? // 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 cancel">' + Common._e("Cancel") + '</a>';
}
html += '<a href="#" class="finish reconnect">' + Common._e("Reconnect") + '</a>' + html += '<a href="#" class="finish reconnect">' + Common._e("Reconnect") + '</a>' +
'</div></div>'; '</div></div>';
// Append the code // Append the code
$('body').append(html); $('body').append(html);
// Click events // Attach events
if(mode == 'normal') self._eventsReconnect(mode);
$('#reconnect a.finish.cancel').click(function() {
return self.cancelReconnect();
});
$('#reconnect a.finish.reconnect').click(function() { // Schedule next reconnect
return self.acceptReconnect(mode); self._scheduleReconnect(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--;
});
// Page title // Page title
Interface.updateTitle(); Interface.updateTitle();
@ -634,9 +723,11 @@ var Connection = (function () {
// Reset some various stuffs // Reset some various stuffs
var groupchats = '#page-engine .page-engine-chan[data-type="groupchat"]'; var groupchats = '#page-engine .page-engine-chan[data-type="groupchat"]';
$(groupchats + ' .list .role').hide(); var groupchats_sel = $(groupchats);
$(groupchats + ' .one-group, ' + groupchats + ' .list .user').remove();
$(groupchats).attr('data-initial', 'false'); groupchats_sel.find('.list .role').hide();
groupchats_sel.find('.one-group, ' + groupchats + ' .list .user').remove();
groupchats_sel.attr('data-initial', 'false');
// Stop the timer // Stop the timer
$('#reconnect a.finish.reconnect').stopTime(); $('#reconnect a.finish.reconnect').stopTime();
@ -645,10 +736,11 @@ var Connection = (function () {
$('#reconnect').remove(); $('#reconnect').remove();
// Try to login again // Try to login again
if(mode == 'normal') if(mode == 'normal') {
self.loginFromSession(Common.XMLFromString(self.current_session)); self.loginFromSession(Common.XMLFromString(self.current_session));
else if(mode == 'anonymous') } else if(mode == 'anonymous') {
Anonymous.login(HOST_ANONYMOUS); Anonymous.login(HOST_ANONYMOUS);
}
} catch(e) { } catch(e) {
Console.error('Connection.acceptReconnect', e); Console.error('Connection.acceptReconnect', e);
} finally { } finally {
@ -817,7 +909,14 @@ var Connection = (function () {
try { try {
// Generate a session XML to be stored // 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) // Save the session parameters (for reconnect if network issue)
self.current_session = session_xml; self.current_session = session_xml;
@ -848,8 +947,9 @@ var Connection = (function () {
$(window).bind('beforeunload', Connection.terminate); $(window).bind('beforeunload', Connection.terminate);
// Nothing to do when anonymous! // Nothing to do when anonymous!
if(Utils.isAnonymous()) if(Utils.isAnonymous()) {
return; return;
}
// Connection params submitted in URL? // Connection params submitted in URL?
if(XMPPLinks.links_var.u && XMPPLinks.links_var.q) { if(XMPPLinks.links_var.u && XMPPLinks.links_var.q) {
@ -865,7 +965,15 @@ var Connection = (function () {
// Must store session? // Must store session?
if(XMPPLinks.links_var.h && (XMPPLinks.links_var.h === '1')) { if(XMPPLinks.links_var.h && (XMPPLinks.links_var.h === '1')) {
// Store session // 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); DataStore.setPersistent('global', 'session', 1, session_xml);
// Redirect to a clean URL // Redirect to a clean URL
@ -900,10 +1008,7 @@ var Connection = (function () {
self.loginFromSession(session); self.loginFromSession(session);
Console.info('Saved session found, resuming it...'); Console.info('Saved session found, resuming it...');
} } else if((parent.location.hash != '#OK') && XMPPLinks.links_var.x) {
// Not connected, maybe a XMPP link is submitted?
else if((parent.location.hash != '#OK') && XMPPLinks.links_var.x) {
Home.change('loginer'); Home.change('loginer');
Console.info('A XMPP link is set, switch to login page.'); Console.info('A XMPP link is set, switch to login page.');

View file

@ -11,103 +11,109 @@ Authors: Stefan Strigler, Valérian Saliou, Kloadut, Maranda
*/ */
// XMPP XMLNS attributes // XMPP XMLNS attributes
var NS_PROTOCOL = 'http://jabber.org/protocol/'; var NS_PROTOCOL = 'http://jabber.org/protocol/';
var NS_FEATURES = 'http://jabber.org/features/'; var NS_FEATURES = 'http://jabber.org/features/';
var NS_CLIENT = 'jabber:client'; var NS_CLIENT = 'jabber:client';
var NS_IQ = 'jabber:iq:'; var NS_IQ = 'jabber:iq:';
var NS_X = 'jabber:x:'; var NS_X = 'jabber:x:';
var NS_IETF = 'urn:ietf:params:xml:ns:'; var NS_IETF = 'urn:ietf:params:xml:ns:';
var NS_IETF_XMPP = NS_IETF + 'xmpp-'; var NS_IETF_XMPP = NS_IETF + 'xmpp-';
var NS_XMPP = 'urn:xmpp:'; var NS_XMPP = 'urn:xmpp:';
var NS_STORAGE = 'storage:'; var NS_STORAGE = 'storage:';
var NS_BOOKMARKS = NS_STORAGE + 'bookmarks'; var NS_BOOKMARKS = NS_STORAGE + 'bookmarks';
var NS_ROSTERNOTES = NS_STORAGE + 'rosternotes'; var NS_ROSTERNOTES = NS_STORAGE + 'rosternotes';
var NS_JAPPIX = 'jappix:'; var NS_JAPPIX = 'jappix:';
var NS_INBOX = NS_JAPPIX + 'inbox'; var NS_INBOX = NS_JAPPIX + 'inbox';
var NS_OPTIONS = NS_JAPPIX + 'options'; var NS_OPTIONS = NS_JAPPIX + 'options';
var NS_DISCO_ITEMS = NS_PROTOCOL + 'disco#items'; var NS_DISCO_ITEMS = NS_PROTOCOL + 'disco#items';
var NS_DISCO_INFO = NS_PROTOCOL + 'disco#info'; var NS_DISCO_INFO = NS_PROTOCOL + 'disco#info';
var NS_VCARD = 'vcard-temp'; var NS_VCARD = 'vcard-temp';
var NS_VCARD_P = NS_VCARD + ':x:update'; var NS_VCARD_P = NS_VCARD + ':x:update';
var NS_IETF_VCARD4 = NS_IETF + 'vcard-4.0'; var NS_IETF_VCARD4 = NS_IETF + 'vcard-4.0';
var NS_XMPP_VCARD4 = NS_XMPP + 'vcard4'; var NS_XMPP_VCARD4 = NS_XMPP + 'vcard4';
var NS_URN_ADATA = NS_XMPP + 'avatar:data'; var NS_URN_ADATA = NS_XMPP + 'avatar:data';
var NS_URN_AMETA = NS_XMPP + 'avatar:metadata'; var NS_URN_AMETA = NS_XMPP + 'avatar:metadata';
var NS_AUTH = NS_IQ + 'auth'; var NS_AUTH = NS_IQ + 'auth';
var NS_AUTH_ERROR = NS_IQ + 'auth:error'; var NS_AUTH_ERROR = NS_IQ + 'auth:error';
var NS_REGISTER = NS_IQ + 'register'; var NS_REGISTER = NS_IQ + 'register';
var NS_SEARCH = NS_IQ + 'search'; var NS_SEARCH = NS_IQ + 'search';
var NS_ROSTER = NS_IQ + 'roster'; var NS_ROSTER = NS_IQ + 'roster';
var NS_PRIVACY = NS_IQ + 'privacy'; var NS_PRIVACY = NS_IQ + 'privacy';
var NS_PRIVATE = NS_IQ + 'private'; var NS_PRIVATE = NS_IQ + 'private';
var NS_VERSION = NS_IQ + 'version'; var NS_VERSION = NS_IQ + 'version';
var NS_TIME = NS_IQ + 'time'; var NS_TIME = NS_IQ + 'time';
var NS_LAST = NS_IQ + 'last'; var NS_LAST = NS_IQ + 'last';
var NS_IQDATA = NS_IQ + 'data'; var NS_IQDATA = NS_IQ + 'data';
var NS_XDATA = NS_X + 'data'; var NS_XDATA = NS_X + 'data';
var NS_IQOOB = NS_IQ + 'oob'; var NS_IQOOB = NS_IQ + 'oob';
var NS_XOOB = NS_X + 'oob'; var NS_XOOB = NS_X + 'oob';
var NS_DELAY = NS_X + 'delay'; var NS_DELAY = NS_X + 'delay';
var NS_EXPIRE = NS_X + 'expire'; var NS_EXPIRE = NS_X + 'expire';
var NS_EVENT = NS_X + 'event'; var NS_EVENT = NS_X + 'event';
var NS_XCONFERENCE = NS_X + 'conference'; var NS_XCONFERENCE = NS_X + 'conference';
var NS_STATS = NS_PROTOCOL + 'stats'; var NS_STATS = NS_PROTOCOL + 'stats';
var NS_MUC = NS_PROTOCOL + 'muc'; var NS_MUC = NS_PROTOCOL + 'muc';
var NS_MUC_USER = NS_MUC + '#user'; var NS_MUC_USER = NS_MUC + '#user';
var NS_MUC_ADMIN = NS_MUC + '#admin'; var NS_MUC_ADMIN = NS_MUC + '#admin';
var NS_MUC_OWNER = NS_MUC + '#owner'; var NS_MUC_OWNER = NS_MUC + '#owner';
var NS_MUC_CONFIG = NS_MUC + '#roomconfig'; var NS_MUC_CONFIG = NS_MUC + '#roomconfig';
var NS_PUBSUB = NS_PROTOCOL + 'pubsub'; var NS_PUBSUB = NS_PROTOCOL + 'pubsub';
var NS_PUBSUB_EVENT = NS_PUBSUB + '#event'; var NS_PUBSUB_EVENT = NS_PUBSUB + '#event';
var NS_PUBSUB_OWNER = NS_PUBSUB + '#owner'; var NS_PUBSUB_OWNER = NS_PUBSUB + '#owner';
var NS_PUBSUB_NMI = NS_PUBSUB + '#node-meta-info'; var NS_PUBSUB_NMI = NS_PUBSUB + '#node-meta-info';
var NS_PUBSUB_NC = NS_PUBSUB + '#node_config'; var NS_PUBSUB_NC = NS_PUBSUB + '#node_config';
var NS_PUBSUB_CN = NS_PUBSUB + '#config-node'; var NS_PUBSUB_CN = NS_PUBSUB + '#config-node';
var NS_PUBSUB_RI = NS_PUBSUB + '#retrieve-items'; var NS_PUBSUB_RI = NS_PUBSUB + '#retrieve-items';
var NS_COMMANDS = NS_PROTOCOL + 'commands'; var NS_COMMANDS = NS_PROTOCOL + 'commands';
var NS_BOSH = NS_PROTOCOL + 'httpbind'; var NS_BOSH = NS_PROTOCOL + 'httpbind';
var NS_STREAM = 'http://etherx.jabber.org/streams'; var NS_STREAM = 'http://etherx.jabber.org/streams';
var NS_URN_TIME = NS_XMPP + 'time'; var NS_URN_TIME = NS_XMPP + 'time';
var NS_URN_PING = NS_XMPP + 'ping'; var NS_URN_PING = NS_XMPP + 'ping';
var NS_URN_MBLOG = NS_XMPP + 'microblog:0'; var NS_URN_MBLOG = NS_XMPP + 'microblog:0';
var NS_URN_INBOX = NS_XMPP + 'inbox'; var NS_URN_INBOX = NS_XMPP + 'inbox';
var NS_URN_FORWARD = NS_XMPP + 'forward:0'; var NS_URN_FORWARD = NS_XMPP + 'forward:0';
var NS_URN_MAM = NS_XMPP + 'mam:tmp'; var NS_URN_MAM = NS_XMPP + 'mam:tmp';
var NS_URN_DELAY = NS_XMPP + 'delay'; var NS_URN_DELAY = NS_XMPP + 'delay';
var NS_URN_RECEIPTS = NS_XMPP + 'receipts'; var NS_URN_RECEIPTS = NS_XMPP + 'receipts';
var NS_URN_CARBONS = NS_XMPP + 'carbons:2'; var NS_URN_CARBONS = NS_XMPP + 'carbons:2';
var NS_RSM = NS_PROTOCOL + 'rsm'; var NS_URN_CORRECT = NS_XMPP + 'message-correct:0';
var NS_IPV6 = 'ipv6'; var NS_URN_IDLE = NS_XMPP + 'idle:1';
var NS_XHTML = 'http://www.w3.org/1999/xhtml'; var NS_URN_REACH = NS_XMPP + 'reach:0';
var NS_XHTML_IM = NS_PROTOCOL + 'xhtml-im'; var NS_URN_MARKERS = NS_XMPP + 'chat-markers:0';
var NS_CHATSTATES = NS_PROTOCOL + 'chatstates'; var NS_URN_ATTENTION = NS_XMPP + 'attention:0';
var NS_HTTP_AUTH = NS_PROTOCOL + 'http-auth'; var NS_URN_HINTS = NS_XMPP + 'hints';
var NS_ROSTERX = NS_PROTOCOL + 'rosterx'; var NS_RSM = NS_PROTOCOL + 'rsm';
var NS_MOOD = NS_PROTOCOL + 'mood'; var NS_IPV6 = 'ipv6';
var NS_ACTIVITY = NS_PROTOCOL + 'activity'; var NS_XHTML = 'http://www.w3.org/1999/xhtml';
var NS_TUNE = NS_PROTOCOL + 'tune'; var NS_XHTML_IM = NS_PROTOCOL + 'xhtml-im';
var NS_GEOLOC = NS_PROTOCOL + 'geoloc'; var NS_CHATSTATES = NS_PROTOCOL + 'chatstates';
var NS_NICK = NS_PROTOCOL + 'nick'; var NS_HTTP_AUTH = NS_PROTOCOL + 'http-auth';
var NS_NOTIFY = '+notify'; var NS_ROSTERX = NS_PROTOCOL + 'rosterx';
var NS_CAPS = NS_PROTOCOL + 'caps'; var NS_MOOD = NS_PROTOCOL + 'mood';
var NS_ATOM = 'http://www.w3.org/2005/Atom'; 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_STANZAS = NS_IETF_XMPP + 'stanzas';
var NS_STREAMS = NS_IETF_XMPP + 'streams'; var NS_STREAMS = NS_IETF_XMPP + 'streams';
var NS_TLS = NS_IETF_XMPP + 'tls'; var NS_TLS = NS_IETF_XMPP + 'tls';
var NS_SASL = NS_IETF_XMPP + 'sasl'; var NS_SASL = NS_IETF_XMPP + 'sasl';
var NS_SESSION = NS_IETF_XMPP + 'session'; var NS_SESSION = NS_IETF_XMPP + 'session';
var NS_BIND = NS_IETF_XMPP + 'bind'; 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_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'; var NS_METRONOME_MAM_PURGE = 'http://metronome.im/protocol/mam-purge';

View 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;
})();

File diff suppressed because it is too large Load diff

View file

@ -39,8 +39,9 @@ var DataStore = (function () {
this.key = function(key) { this.key = function(key) {
if(legacy) { if(legacy) {
if(key >= this.length) if(key >= this.length) {
return null; return null;
}
var c = 0; var c = 0;
@ -56,8 +57,9 @@ var DataStore = (function () {
this.getItem = function(key) { this.getItem = function(key) {
if(legacy) { if(legacy) {
if(storage_emulated[key] !== undefined) if(storage_emulated[key] !== undefined) {
return storage_emulated[key]; return storage_emulated[key];
}
return null; return null;
} else { } else {
@ -67,8 +69,9 @@ var DataStore = (function () {
this.setItem = function(key, data) { this.setItem = function(key, data) {
if(legacy) { if(legacy) {
if(!(key in storage_emulated)) if(!(key in storage_emulated)) {
this.length++; this.length++;
}
storage_emulated[key] = (data + ''); storage_emulated[key] = (data + '');
} else { } else {
@ -472,8 +475,9 @@ var DataStore = (function () {
self.resetPersistent(); self.resetPersistent();
// Restaure the stored session entry // Restaure the stored session entry
if(session) if(session) {
self.setPersistent('global', 'session', 1, session); self.setPersistent('global', 'session', 1, session);
}
Console.info('Persistent database flushed.'); Console.info('Persistent database flushed.');

View file

@ -84,8 +84,9 @@ var DateUtils = (function () {
try { try {
// Last activity not yet initialized? // Last activity not yet initialized?
if(self.last_activity === 0) if(self.last_activity === 0) {
return 0; return 0;
}
return self.getTimeStamp() - self.last_activity; return self.getTimeStamp() - self.last_activity;
} catch(e) { } 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 * Gets the last user available presence in seconds
* @public * @public
@ -104,8 +126,9 @@ var DateUtils = (function () {
try { try {
// Last presence stamp not yet initialized? // Last presence stamp not yet initialized?
if(self.presence_last_activity === 0) if(self.presence_last_activity === 0) {
return 0; return 0;
}
return self.getTimeStamp() - self.presence_last_activity; return self.getTimeStamp() - self.presence_last_activity;
} catch(e) { } 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 * Generates the time for XMPP
* @public * @public
@ -123,43 +196,11 @@ var DateUtils = (function () {
*/ */
self.getXMPPTime = function(location) { self.getXMPPTime = function(location) {
/* FROM : http://trac.jwchat.org/jsjac/browser/branches/jsjac_1.0/jsextras.js?rev=221 */
try { try {
// Initialize return self.getDatetime(
var jInit = new Date(); (new Date()),
var year, month, day, hours, minutes, seconds; location
);
// 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;
} catch(e) { } catch(e) {
Console.error('DateUtils.getXMPPTime', e); Console.error('DateUtils.getXMPPTime', e);
} }
@ -176,6 +217,7 @@ var DateUtils = (function () {
try { try {
var init = new Date(); var init = new Date();
var time = Common.padZero(init.getHours()) + ':'; var time = Common.padZero(init.getHours()) + ':';
time += Common.padZero(init.getMinutes()) + ':'; time += Common.padZero(init.getMinutes()) + ':';
time += Common.padZero(init.getSeconds()); time += Common.padZero(init.getSeconds());
@ -332,20 +374,24 @@ var DateUtils = (function () {
var days = Math.round((current_stamp - old_stamp) / 86400000); var days = Math.round((current_stamp - old_stamp) / 86400000);
// Invalid date? // Invalid date?
if(isNaN(old_stamp) || isNaN(days)) if(isNaN(old_stamp) || isNaN(days)) {
return self.getCompleteTime(); return self.getCompleteTime();
}
// Is it today? // Is it today?
if(current_day == old_day) if(current_day == old_day) {
return old_time; return old_time;
}
// It is yesterday? // It is yesterday?
if(days <= 1) if(days <= 1) {
return Common._e("Yesterday") + ' - ' + old_time; return Common._e("Yesterday") + ' - ' + old_time;
}
// Is it less than a week ago? // Is it less than a week ago?
if(days <= 7) if(days <= 7) {
return Common.printf(Common._e("%s days ago"), days) + ' - ' + old_time; return Common.printf(Common._e("%s days ago"), days) + ' - ' + old_time;
}
// Another longer period // Another longer period
return old_date.toLocaleDateString() + ' - ' + old_time; return old_date.toLocaleDateString() + ' - ' + old_time;
@ -371,13 +417,12 @@ var DateUtils = (function () {
// Read the delay // Read the delay
d_delay = jQuery(node).find('delay[xmlns="' + NS_URN_DELAY + '"]:first').attr('stamp'); d_delay = jQuery(node).find('delay[xmlns="' + NS_URN_DELAY + '"]:first').attr('stamp');
// New delay (valid XEP) // Get delay
if(d_delay) if(d_delay) {
// New delay (valid XEP)
delay = d_delay; delay = d_delay;
} else {
// Old delay (obsolete XEP!) // Old delay (obsolete XEP!)
else {
// Try to read the old-school delay
var x_delay = jQuery(node).find('x[xmlns="' + NS_DELAY + '"]:first').attr('stamp'); var x_delay = jQuery(node).find('x[xmlns="' + NS_DELAY + '"]:first').attr('stamp');
if(x_delay) if(x_delay)

View file

@ -1,10 +1,10 @@
/** /**
* Version: 1.0 Alpha-1 * Version: 1.0 Alpha-1
* Build Date: 13-Nov-2007 * Build Date: 13-Nov-2007
* Copyright (c) 2006-2007, Coolite Inc. (http://www.coolite.com/). All rights reserved. * 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/. * 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/ * 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.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;}} 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;}} 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;} 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;} 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.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);};

View file

@ -123,8 +123,9 @@ var Directory = (function () {
$('#directory .directory-server-input').keyup(function(e) { $('#directory .directory-server-input').keyup(function(e) {
if(e.keyCode == 13) { if(e.keyCode == 13) {
// No value? // No value?
if(!$(this).val()) if(!$(this).val()) {
$(this).val(HOST_VJUD); $(this).val(HOST_VJUD);
}
// Start the directory search // Start the directory search
self.start(); self.start();

View file

@ -216,8 +216,9 @@ var Discovery = (function () {
$('#discovery .disco-server-input').keyup(function(e) { $('#discovery .disco-server-input').keyup(function(e) {
if(e.keyCode == 13) { if(e.keyCode == 13) {
// No value? // No value?
if(!$(this).val()) if(!$(this).val()) {
$(this).val(HOST_MAIN); $(this).val(HOST_MAIN);
}
// Start the discovery // Start the discovery
self.start(); self.start();

View file

@ -37,17 +37,20 @@ var Errors = (function () {
var eText = ''; var eText = '';
// Any error condition // Any error condition
if(condition) if(condition) {
eText += condition; eText += condition;
}
// Any error type // Any error type
if(type && eText) if(type && eText) {
eText += ' (' + type + ')'; eText += ' (' + type + ')';
}
// Any error reason // Any error reason
if(reason) { if(reason) {
if(eText) if(eText) {
eText += ' - '; eText += ' - ';
}
eText += reason; eText += reason;
} }
@ -119,10 +122,11 @@ var Errors = (function () {
// Show reconnect pane // Show reconnect pane
if(Connection.current_session && Connection.connected) { if(Connection.current_session && Connection.connected) {
// Anonymous? // Anonymous?
if(Utils.isAnonymous()) if(Utils.isAnonymous()) {
Connection.createReconnect('anonymous'); Connection.createReconnect('anonymous');
else } else {
Connection.createReconnect('normal'); Connection.createReconnect('normal');
}
} }
// Show the homepage (security) // Show the homepage (security)

View file

@ -143,16 +143,21 @@ var Favorites = (function () {
self.reset = function() { self.reset = function() {
try { try {
var path = '#favorites '; var path_sel = $('#favorites');
$(path + '.wait, ' + path + '.fedit-terminate').hide(); path_sel.find('.wait');
$(path + '.fedit-add').show(); path_sel.find('.fedit-terminate').hide();
$(path + '.fsearch-oneresult').remove(); path_sel.find('.fedit-add').show();
$(path + 'input').val('');
$(path + '.please-complete').removeClass('please-complete'); path_sel.find('.fsearch-oneresult').remove();
$(path + '.fedit-nick').val(Name.getNick()); path_sel.find('input').val('');
$(path + '.fsearch-head-server, ' + path + '.fedit-server').val(HOST_MUC); path_sel.find('.please-complete').removeClass('please-complete');
$(path + '.fedit-autojoin').removeAttr('checked');
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) { } catch(e) {
Console.error('Favorites.reset', e); Console.error('Favorites.reset', e);
} }
@ -182,29 +187,34 @@ var Favorites = (function () {
/** /**
* Adds a room to the favorites * Adds a room to the favorites
* @public * @public
* @param {string} roomXID * @param {string} room_xid
* @param {string} roomName * @param {string} room_name
* @return {boolean} * @return {boolean}
*/ */
self.addThis = function(roomXID, roomName) { self.addThis = function(room_xid, room_name) {
try { try {
// Button path // 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 // 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 // Click event
$(button + '.remove').click(function() { button_sel.filter('.remove').click(function() {
return self.removeThis(roomXID, roomName); return self.removeThis(room_xid, room_name);
}); });
// Hide the add button in the (opened?) groupchat // 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 // 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 // Publish the favorites
self.publish(); self.publish();
@ -220,29 +230,29 @@ var Favorites = (function () {
/** /**
* Removes a room from the favorites * Removes a room from the favorites
* @public * @public
* @param {string} roomXID * @param {string} room_xid
* @param {string} roomName * @param {string} room_name
* @return {boolean} * @return {boolean}
*/ */
self.removeThis = function(roomXID, roomName) { self.removeThis = function(room_xid, room_name) {
try { try {
// Button path // 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 // 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 // Click event
$(button + '.add').click(function() { button_sel.filter('.add').click(function() {
return self.addThis(roomXID, roomName); return self.addThis(room_xid, room_name);
}); });
// Show the add button in the (opened?) groupchat // Show the add button in the (opened?) groupchat
$('#' + hex_md5(roomXID) + ' .tools-add').show(); $('#' + hex_md5(room_xid) + ' .tools-add').show();
// Remove the favorite // Remove the favorite
self.remove(roomXID, true); self.remove(room_xid, true);
// Publish the favorites // Publish the favorites
self.publish(); self.publish();
@ -264,31 +274,34 @@ var Favorites = (function () {
try { try {
// Path to favorites // Path to favorites
var favorites = '#favorites .'; var favorites_sel = $('#favorites');
// Reset the favorites // Reset the favorites
self.reset(); self.reset();
// Show the edit/remove button, hide the others // Show the edit/remove button, hide the others
$(favorites + 'fedit-terminate').hide(); favorites_sel.find('.fedit-terminate').hide();
$(favorites + 'fedit-edit').show(); favorites_sel.find('.fedit-edit').show();
$(favorites + 'fedit-remove').show(); favorites_sel.find('.fedit-remove').show();
// We retrieve the values // We retrieve the values
var xid = $(favorites + 'fedit-head-select').val(); var xid = favorites_sel.find('.fedit-head-select').val();
var data = Common.XMLFromString(DataStore.getDB(Connection.desktop_hash, 'favorites', xid)); var data_sel = $(Common.XMLFromString(
DataStore.getDB(Connection.desktop_hash, 'favorites', xid)
));
// If this is not the default room // If this is not the default room
if(xid != 'none') { if(xid != 'none') {
// We apply the values // We apply the values
$(favorites + 'fedit-title').val($(data).find('name').text()); favorites_sel.find('.fedit-title').val(data_sel.find('name').text());
$(favorites + 'fedit-nick').val($(data).find('nick').text()); favorites_sel.find('.fedit-nick').val(data_sel.find('nick').text());
$(favorites + 'fedit-chan').val(Common.getXIDNick(xid)); favorites_sel.find('.fedit-chan').val(Common.getXIDNick(xid));
$(favorites + 'fedit-server').val(Common.getXIDHost(xid)); favorites_sel.find('.fedit-server').val(Common.getXIDHost(xid));
$(favorites + 'fedit-password').val($(data).find('password').text()); favorites_sel.find('.fedit-password').val(data_sel.find('password').text());
if($(data).find('autojoin').text() == 'true') if(data_sel.find('autojoin').text() == 'true') {
$(favorites + 'fedit-autojoin').attr('checked', true); favorites_sel.find('.fedit-autojoin').attr('checked', true);
}
} }
} catch(e) { } catch(e) {
Console.error('Favorites.edit', e); Console.error('Favorites.edit', e);
@ -307,52 +320,50 @@ var Favorites = (function () {
try { try {
// Path to favorites // Path to favorites
var favorites = '#favorites '; var favorites_sel = $('#favorites');
// We get the values of the current edited groupchat // 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 title = favorites_sel.find('.fedit-title').val();
var nick = $(favorites + '.fedit-nick').val(); var nick = favorites_sel.find('.fedit-nick').val();
var room = $(favorites + '.fedit-chan').val(); var room = favorites_sel.find('.fedit-chan').val();
var server = $(favorites + '.fedit-server').val(); var server = favorites_sel.find('.fedit-server').val();
var xid = room + '@' + server; var xid = room + '@' + server;
var password = $(favorites + '.fedit-password').val(); var password = favorites_sel.find('.fedit-password').val();
var autojoin = 'false'; var autojoin = 'false';
if($(favorites + '.fedit-autojoin').filter(':checked').size()) if(favorites_sel.find('.fedit-autojoin').filter(':checked').size()) {
autojoin = 'true'; autojoin = 'true';
}
// We check the missing values and send this if okay // We check the missing values and send this if okay
if((type == 'add') || (type == 'edit')) { if((type == 'add') || (type == 'edit')) {
if(title && nick && room && server) { if(title && nick && room && server) {
// Remove the edited room // Remove the edited room
if(type == 'edit') if(type == 'edit') {
self.remove(old_xid, true); self.remove(old_xid, true);
}
// Display the favorites // Display the favorites
self.display(xid, title, nick, autojoin, password); self.display(xid, title, nick, autojoin, password);
// Reset the inputs // Reset the inputs
self.reset(); self.reset();
} } else {
favorites_sel.find('input[required]').each(function() {
else {
$(favorites + 'input[required]').each(function() {
var select = $(this); var select = $(this);
if(!select.val()) if(!select.val()) {
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
select.addClass('please-complete').focus(); select.addClass('please-complete').focus();
}); });
else } else {
select.removeClass('please-complete'); select.removeClass('please-complete');
}
}); });
} }
} } else if(type == 'remove') {
// Must remove a favorite?
else if(type == 'remove') {
self.remove(old_xid, true); self.remove(old_xid, true);
// Reset the inputs // Reset the inputs
@ -409,7 +420,9 @@ var Favorites = (function () {
iq.setType('set'); iq.setType('set');
var query = iq.setQuery(NS_PRIVATE); 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 // We generate the XML
var db_regex = new RegExp(('^' + Connection.desktop_hash + '_') + 'favorites_(.+)'); 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 the pointer is on a stored favorite
if(current.match(db_regex)) { if(current.match(db_regex)) {
var data = Common.XMLFromString(DataStore.storageDB.getItem(current)); var data_sel = $(Common.XMLFromString(
var xid = $(data).find('xid').text(); DataStore.storageDB.getItem(current)
var rName = $(data).find('name').text(); ));
var nick = $(data).find('nick').text();
var password = $(data).find('password').text(); var xid = data_sel.find('xid').text();
var autojoin = $(data).find('autojoin').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 // We create the node for this groupchat
var item = storage.appendChild(iq.buildNode('conference', {'name': rName, 'jid': xid, 'autojoin': autojoin, xmlns: NS_BOOKMARKS})); var item = storage.appendChild(
item.appendChild(iq.buildNode('nick', {xmlns: NS_BOOKMARKS}, nick)); iq.buildNode('conference', {
'name': rName,
'jid': xid,
'autojoin': autojoin,
xmlns: NS_BOOKMARKS
})
);
if(password) item.appendChild(iq.buildNode('nick', {
item.appendChild(iq.buildNode('password', {xmlns: NS_BOOKMARKS}, password)); xmlns: NS_BOOKMARKS
}, nick));
if(password) {
item.appendChild(iq.buildNode('password', {
xmlns: NS_BOOKMARKS
}, password));
}
Console.info('Bookmark sent: ' + xid); Console.info('Bookmark sent: ' + xid);
} }
@ -454,17 +483,17 @@ var Favorites = (function () {
self.getGCList = function() { self.getGCList = function() {
try { try {
var path = '#favorites .'; var path_sel = $('#favorites');
var gcServer = $('.fsearch-head-server').val(); var groupchat_server = $('.fsearch-head-server').val();
// We reset some things // We reset some things
$(path + 'fsearch-oneresult').remove(); path_sel.find('.fsearch-oneresult').remove();
$(path + 'fsearch-noresults').hide(); path_sel.find('.fsearch-noresults').hide();
$(path + 'wait').show(); path_sel.find('.wait').show();
var iq = new JSJaCIQ(); var iq = new JSJaCIQ();
iq.setType('get'); iq.setType('get');
iq.setTo(gcServer); iq.setTo(groupchat_server);
iq.setQuery(NS_DISCO_ITEMS); iq.setQuery(NS_DISCO_ITEMS);
@ -485,13 +514,13 @@ var Favorites = (function () {
self.handleGCList = function(iq) { self.handleGCList = function(iq) {
try { try {
var path = '#favorites .'; var path_sel = $('#favorites');
var from = Common.fullXID(Common.getStanzaFrom(iq)); var from = Common.fullXID(Common.getStanzaFrom(iq));
if(!iq || (iq.getType() != 'result')) { if(!iq || (iq.getType() != 'result')) {
Board.openThisError(3); Board.openThisError(3);
$(path + 'wait').hide(); path_sel.find('.wait').hide();
Console.error('Error while retrieving the rooms: ' + from); Console.error('Error while retrieving the rooms: ' + from);
} }
@ -504,24 +533,37 @@ var Favorites = (function () {
var html = ''; var html = '';
$(handleXML).find('item').each(function() { $(handleXML).find('item').each(function() {
var roomXID = $(this).attr('jid'); var this_sel = $(this);
var roomName = $(this).attr('name');
var room_xid = this_sel.attr('jid');
var room_name = this_sel.attr('name');
if(roomXID && roomName) { if(room_xid && room_name) {
// Escaped values // Escaped values
var escaped_xid = Utils.encodeOnclick(roomXID); var escaped_xid = Utils.encodeOnclick(room_xid);
var escaped_name = Utils.encodeOnclick(roomName); var escaped_name = Utils.encodeOnclick(room_name);
// Initialize the room HTML // Initialize the room HTML
html += '<div class="oneresult fsearch-oneresult" data-xid="' + escape(roomXID) + '">' + html += '<div class="oneresult fsearch-oneresult" data-xid="' + escape(room_xid) + '">' +
'<div class="room-name">' + roomName.htmlEnc() + '</div>' + '<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>'; '<a href="#" class="one-button join talk-images" onclick="return Favorites.join(\'' + escaped_xid + '\');">' + Common._e("Join") + '</a>';
// This room is yet a favorite // This room is yet a favorite
if(DataStore.existDB('favorites', roomXID)) 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>'; html += '<a href="#" ' +
else 'class="one-button remove talk-images" ' +
html += '<a href="#" class="one-button add talk-images" onclick="return Favorites.addThis(\'' + escaped_xid + '\', \'' + escaped_name + '\');">' + Common._e("Add") + '</a>'; '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 // Close the room HTML
html += '</div>'; html += '</div>';
@ -529,16 +571,15 @@ var Favorites = (function () {
}); });
// Append this code to the popup // 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); Console.info('Rooms retrieved: ' + from);
} }
$(path + 'wait').hide(); path_sel.find('.wait').hide();
} catch(e) { } catch(e) {
Console.error('Favorites.handleGCList', e); Console.error('Favorites.handleGCList', e);
} }
@ -556,7 +597,14 @@ var Favorites = (function () {
try { try {
self.quit(); self.quit();
Chat.checkCreate(room, 'groupchat', '', '', Common.getXIDNick(room));
Chat.checkCreate(
room,
'groupchat',
'',
'',
Common.getXIDNick(room)
);
} catch(e) { } catch(e) {
Console.error('Favorites.join', e); Console.error('Favorites.join', e);
} finally { } finally {
@ -589,7 +637,14 @@ var Favorites = (function () {
$('#roster .gc-join-first-option, #favorites .fedit-head-select-first-option').after(html); $('#roster .gc-join-first-option, #favorites .fedit-head-select-first-option').after(html);
// We store the informations // 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); DataStore.setDB(Connection.desktop_hash, 'favorites', xid, value);
} catch(e) { } catch(e) {
Console.error('Favorites.display', e); Console.error('Favorites.display', e);
@ -621,13 +676,20 @@ var Favorites = (function () {
var data = Common.XMLFromString(DataStore.storageDB.getItem(current)); var data = Common.XMLFromString(DataStore.storageDB.getItem(current));
// Add the current favorite to the HTML code // 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 // 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_bubble = '<option value="none" class="gc-join-first-option" selected="">' +
var favorites_popup = '<option value="none" class="fedit-head-select-first-option" selected="">' + Common._e("Select a favorite") + '</option>' + html; 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 // Append the HTML code
$('#roster .buddy-conf-groupchat-select').html(favorites_bubble); $('#roster .buddy-conf-groupchat-select').html(favorites_bubble);
@ -647,29 +709,31 @@ var Favorites = (function () {
self.instance = function() { self.instance = function() {
try { try {
var path = '#favorites .'; var favorites_sel = $('#favorites');
// Keyboard events // Keyboard events
$(path + 'fsearch-head-server').keyup(function(e) { favorites_sel.find('.fsearch-head-server').keyup(function(e) {
if(e.keyCode == 13) { if(e.keyCode == 13) {
var this_sel = $(this);
// No value? // No value?
if(!$(this).val()) if(!this_sel.val()) {
$(this).val(HOST_MUC); this_sel.val(HOST_MUC);
}
// Get the list // Get the list
self.getGCList(); self.getGCList();
} }
}); });
$(path + 'fedit-line input').keyup(function(e) { favorites_sel.find('.fedit-line input').keyup(function(e) {
if(e.keyCode == 13) { if(e.keyCode == 13) {
// Edit a favorite // Edit a favorite
if($(path + 'fedit-edit').is(':visible')) if(favorites_sel.find('.fedit-edit').is(':visible')) {
self.terminateThis('edit'); self.terminateThis('edit');
} else {
// Add a favorite
else
self.terminateThis('add'); self.terminateThis('add');
}
} }
}); });
@ -677,33 +741,33 @@ var Favorites = (function () {
$('.fedit-head-select').change(self.edit); $('.fedit-head-select').change(self.edit);
// Click events // Click events
$(path + 'room-switcher').click(function() { favorites_sel.find('.room-switcher').click(function() {
$(path + 'favorites-content').hide(); favorites_sel.find('.favorites-content').hide();
self.reset(); self.reset();
}); });
$(path + 'room-list').click(function() { favorites_sel.find('.room-list').click(function() {
$(path + 'favorites-edit').show(); favorites_sel.find('.favorites-edit').show();
}); });
$(path + 'room-search').click(function() { favorites_sel.find('.room-search').click(function() {
$(path + 'favorites-search').show(); favorites_sel.find('.favorites-search').show();
self.getGCList(); self.getGCList();
}); });
$(path + 'fedit-add').click(function() { favorites_sel.find('.fedit-add').click(function() {
return self.terminateThis('add'); return self.terminateThis('add');
}); });
$(path + 'fedit-edit').click(function() { favorites_sel.find('.fedit-edit').click(function() {
return self.terminateThis('edit'); return self.terminateThis('edit');
}); });
$(path + 'fedit-remove').click(function() { favorites_sel.find('.fedit-remove').click(function() {
return self.terminateThis('remove'); return self.terminateThis('remove');
}); });
$(path + 'bottom .finish').click(function() { favorites_sel.find('.bottom .finish').click(function() {
return self.quit(); return self.quit();
}); });
} catch(e) { } catch(e) {

View file

@ -103,7 +103,7 @@ var Features = (function () {
}; };
// Markers // 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'); var identity = selector.find('identity');
@ -218,6 +218,11 @@ var Features = (function () {
if(self.enabledMAMPurge()) { if(self.enabledMAMPurge()) {
$(path + 'mam-purge-hidable').show(); $(path + 'mam-purge-hidable').show();
} }
// Message correction features
if(self.enabledCorrection()) {
$(path + 'correction-hidable').show();
}
// Commands features // Commands features
if(self.enabledCommands()) { 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 * Normalizes the XMPP server name
* @private * @private

View file

@ -20,6 +20,300 @@ var Filter = (function () {
var self = {}; 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': [
/((&lt;\/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': [
/(\]:-?&gt;)($|\s|<)/gi,
'$2'
],
'drink': [
/(\(D\))($|\s|<)/g,
'$2'
],
'flower': [
/(@}-&gt;--)($|\s|<)/gi,
'$2'
],
'frowning': [
/((:-?\/)|(:-?S))($|\s|<)/gi,
'$4'
],
'girl': [
/(\(X\))($|\s|<)/g,
'$2'
],
'heart': [
/((&lt;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 * Generates a given emoticon HTML code
* @public * @public
@ -42,83 +336,64 @@ var Filter = (function () {
/** /**
* Filters a given message * Filters a given message
* @public * @public
* @param {string} neutralMessage * @param {string} message
* @param {string} nick * @param {string} nick
* @param {string} html_escape * @param {string} html_escape
* @return {string} * @return {string}
*/ */
self.message = function(neutralMessage, nick, html_escape) { self.message = function(message, nick, html_escape) {
try { try {
var filteredMessage = neutralMessage; var filtered = message;
// We encode the HTML special chars // 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(/((&lt;\/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(/(\]:-?&gt;)($|\s|<)/gi, self.emoteImage('devil', '$1', '$2'))
.replace(/(\(D\))($|\s|<)/g, self.emoteImage('drink', '$1', '$2'))
.replace(/(@}-&gt;--)($|\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(/((&lt;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) { if(html_escape) {
filteredMessage = Links.apply(filteredMessage, 'desktop'); filtered = filtered.htmlEnc();
} }
// Filter integratebox links // Security: don't filter huge messages (avoids crash attacks)
filteredMessage = IntegrateBox.filter(filteredMessage); 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) { } catch(e) {
Console.error('Filter.message', e); Console.error('Filter.message', e);
} }
@ -135,85 +410,23 @@ var Filter = (function () {
self.xhtml = function(code) { self.xhtml = function(code) {
try { try {
// Allowed elements array var code_sel = $(code);
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'
);
// 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 // Check if Filter for XHTML-IM images is enabled
if(DataStore.getDB(Connection.desktop_hash, 'options', 'no-xhtml-images') != '1') { if(DataStore.getDB(Connection.desktop_hash, 'options', 'no-xhtml-images') != '1') {
elements.push("img"); self.xhtml_allow.elements.push("img");
} }
// Remove forbidden elements // Remove forbidden elements
$(code).find('html body *').each(function() { code_sel.find('html body *').each(function() {
// This element is not authorized // This element is not authorized
if(!Utils.existArrayValue(elements, (this).nodeName.toLowerCase())) if(!Utils.existArrayValue(self.xhtml_allow.elements, (this).nodeName.toLowerCase())) {
$(this).remove(); $(this).remove();
}
}); });
// Remove forbidden attributes // 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) // Put a pointer on this element (jQuery way & normal way)
var cSelector = $(this); var cSelector = $(this);
var cElement = (this); var cElement = (this);
@ -226,15 +439,17 @@ var Filter = (function () {
var cVal = cAttr.value; var cVal = cAttr.value;
// This attribute is not authorized, or contains JS code // 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); cSelector.removeAttr(cName);
}
}); });
}); });
// Filter some other elements // 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) { } catch(e) {
Console.error('Filter.xhtml', e); Console.error('Filter.xhtml', e);
} }

View file

@ -24,6 +24,196 @@ var Groupchat = (function () {
var JOIN_SUGGEST = []; 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 * Displays the MUC admin elements
* @public * @public
@ -37,16 +227,19 @@ var Groupchat = (function () {
try { try {
// We must be in the "login" mode // We must be in the "login" mode
if(Utils.isAnonymous()) if(Utils.isAnonymous()) {
return; return;
}
// We check if the user is a room owner or administrator to give him privileges // 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(); $('#' + id + ' .tools-mucadmin').show();
}
// We check if the room hasn't been yet created // We check if the room hasn't been yet created
if(statuscode == 201) if(statuscode == 201) {
Board.openThisInfo(4); Board.openThisInfo(4);
}
// We add the click event // We add the click event
$('#' + id + ' .tools-mucadmin').click(function() { $('#' + id + ' .tools-mucadmin').click(function() {
@ -80,14 +273,16 @@ var Groupchat = (function () {
// No nickname? // No nickname?
if(!nickname) { if(!nickname) {
// Get some values // Get some values
if(!Utils.isAnonymous()) if(!Utils.isAnonymous()) {
nickname = Name.getNick(); nickname = Name.getNick();
else } else {
nickname = ANONYMOUS_NICK; nickname = ANONYMOUS_NICK;
}
// If the nickname could not be retrieved, ask it // If the nickname could not be retrieved, ask it
if(!nickname) if(!nickname) {
self.generateMUCAsk('nickname', room, hash, nickname, password); self.generateMUCAsk('nickname', room, hash, nickname, password);
}
} }
// Got our nickname? // Got our nickname?
@ -126,10 +321,12 @@ var Groupchat = (function () {
var room = Common.bareXID(from); var room = Common.bareXID(from);
var nickname = Common.thisResource(from); var nickname = Common.thisResource(from);
var hash = hex_md5(room); var hash = hex_md5(room);
var id = presence.getID();
// No ID: must fix M-Link bug // No ID: must fix M-Link bug
if(presence.getID() === null) { if(id === null) {
presence.setID(1); id = 1;
presence.setID(id);
} }
Console.info('First MUC presence: ' + from); Console.info('First MUC presence: ' + from);
@ -139,11 +336,17 @@ var Groupchat = (function () {
// Define some stuffs // Define some stuffs
var muc_user = $(xml).find('x[xmlns="' + NS_MUC_USER + '"]'); var muc_user = $(xml).find('x[xmlns="' + NS_MUC_USER + '"]');
var affiliation = muc_user.find('item').attr('affiliation'); 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 // Handle my presence
Presence.handle(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 // Check if I am a room owner
self.openAdmin(affiliation, hash, room, statuscode); self.openAdmin(affiliation, hash, room, statuscode);
@ -279,65 +482,16 @@ var Groupchat = (function () {
}); });
// Must show the add button? // Must show the add button?
if(!DataStore.existDB('favorites', room)) if(!DataStore.existDB(Connection.desktop_hash, 'favorites', room)) {
$('#' + hash + ' .tools-add').show(); $('#' + hash + ' .tools-add').show();
}
// The event handlers // The event handlers
var inputDetect = $('#' + hash + ' .message-area'); var input_sel = $('#' + hash + ' .message-area');
self._createEvents(input_sel, hash, room);
// 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);
}
});
// Chatstate events // Chatstate events
ChatState.events(inputDetect, room, hash, 'groupchat'); ChatState.events(input_sel, room, hash, 'groupchat');
// Get the current muc informations and content // Get the current muc informations and content
self.getMUC(room, nickname, password); self.getMUC(room, nickname, password);
@ -361,23 +515,26 @@ var Groupchat = (function () {
var new_arr = []; var new_arr = [];
// Try to split it // Try to split it
if(GROUPCHATS_JOIN.indexOf(',') != -1) if(GROUPCHATS_JOIN.indexOf(',') != -1) {
muc_arr = GROUPCHATS_JOIN.split(','); muc_arr = GROUPCHATS_JOIN.split(',');
}
for(var i in muc_arr) { for(var i in muc_arr) {
// Get the current value // Get the current value
var muc_current = $.trim(muc_arr[i]); var muc_current = $.trim(muc_arr[i]);
// No current value? // No current value?
if(!muc_current) if(!muc_current) {
continue; continue;
}
// Filter the current value // Filter the current value
muc_current = Common.generateXID(muc_current, 'groupchat'); muc_current = Common.generateXID(muc_current, 'groupchat');
// Add the current value // Add the current value
if(!Utils.existArrayValue(new_arr, muc_current)) if(!Utils.existArrayValue(new_arr, muc_current)) {
new_arr.push(muc_current); new_arr.push(muc_current);
}
} }
return new_arr; return new_arr;
@ -397,8 +554,9 @@ var Groupchat = (function () {
try { try {
// Nothing to join? // Nothing to join?
if(!JOIN_SUGGEST) if(!JOIN_SUGGEST) {
return; return;
}
// Join the chats // Join the chats
if(JOIN_SUGGEST.length) { if(JOIN_SUGGEST.length) {
@ -425,8 +583,9 @@ var Groupchat = (function () {
// Must suggest the user? // Must suggest the user?
if((GROUPCHATS_SUGGEST == 'on') && groupchat_arr.length) { if((GROUPCHATS_SUGGEST == 'on') && groupchat_arr.length) {
if(Common.exists('#suggest')) if(Common.exists('#suggest')) {
return; return;
}
// Create HTML code // Create HTML code
var html = '<div id="suggest" class="removable">'; var html = '<div id="suggest" class="removable">';
@ -452,39 +611,8 @@ var Groupchat = (function () {
// Append HTML code // Append HTML code
$('body').append(html); $('body').append(html);
// Click events // Attach events
$('#suggest .content a.one').click(function() { self._suggestCheckEvents();
// 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;
});
} else { } else {
JOIN_SUGGEST = groupchat_arr; JOIN_SUGGEST = groupchat_arr;
@ -512,7 +640,7 @@ var Groupchat = (function () {
if(!ban_xid) { if(!ban_xid) {
Board.openThisInfo(6); 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 { } else {
// We generate the ban IQ // We generate the ban IQ
var iq = new JSJaCIQ(); var iq = new JSJaCIQ();
@ -520,10 +648,16 @@ var Groupchat = (function () {
iq.setType('set'); iq.setType('set');
var iqQuery = iq.setQuery(NS_MUC_ADMIN); 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) { 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); con.send(iq, Errors.handleReply);
@ -561,10 +695,16 @@ var Groupchat = (function () {
iq.setType('set'); iq.setType('set');
var iqQuery = iq.setQuery(NS_MUC_ADMIN); 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) { 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); 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; return self;
})(); })();

View file

@ -20,6 +20,119 @@ var Home = (function () {
var self = {}; 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 * Allows the user to switch the difference home page elements
* @public * @public
@ -76,7 +189,7 @@ var Home = (function () {
'<legend>' + Common._e("Required") + '</legend>' + '<legend>' + Common._e("Required") + '</legend>' +
'<label for="lnick">' + Common._e("Address") + '</label>' + '<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>' + '<label for="lpassword">' + Common._e("Password") + '</label>' +
'<input type="password" class="password" id="lpassword" required="" />' + '<input type="password" class="password" id="lpassword" required="" />' +
'<label for="lremember">' + Common._e("Remember me") + '</label>' + '<label for="lremember">' + Common._e("Remember me") + '</label>' +
@ -112,8 +225,9 @@ var Home = (function () {
disable_form = Utils.disableInput(ANONYMOUS, 'off'); 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>'; 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 += '<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">' + code += '<form action="#" method="post">' +
'<fieldset>' + '<fieldset>' +
@ -139,27 +253,30 @@ var Home = (function () {
case 'registerer': case 'registerer':
disable_form = Utils.disableInput(REGISTRATION, 'off'); disable_form = Utils.disableInput(REGISTRATION, 'off');
if(!disable_form) if(!disable_form) {
lock_host = Utils.disableInput(LOCK_HOST, 'on'); 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>'; 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 += '<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">' + code += '<form action="#" method="post">' +
'<fieldset>' + '<fieldset>' +
'<legend>' + Common._e("Required") + '</legend>' + '<legend>' + Common._e("Required") + '</legend>' +
'<label for="rnick">' + Common._e("Address") + '</label>' + '<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>' + '<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...") + '" />'; '<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">' + 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="" />' + '<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>'; '</div>';
}
code += '</fieldset>' + code += '</fieldset>' +
@ -170,78 +287,22 @@ var Home = (function () {
} }
// Form disabled? // Form disabled?
if(disable_form) if(disable_form) {
code += '<div class="info fail">' + code += '<div class="info fail">' +
Common._e("This tool has been disabled!") + Common._e("This tool has been disabled!") +
'</div>'; '</div>';
}
// Create this HTML code // Create this HTML code
if(code && !Common.exists(current)) { if(code && !Common.exists(current)) {
// Append it! $(right + '.homediv.default').after(
$(right + '.homediv.default').after('<div class="' + div + ' homediv">' + code + '</div>'); '<div class="' + div + ' homediv">' + code + '</div>'
);
// Create the attached events self._eventsChange(
switch(div) { $(current),
// Login tool div
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;
}
} }
// We focus on the first input // We focus on the first input
@ -288,13 +349,14 @@ var Home = (function () {
try { try {
// We get the values // We get the values
var lPath = '#home .loginer '; var path_sel = $('#home .loginer');
var lServer = $(lPath + '.server').val();
var lNick = Common.nodeprep($(lPath + '.nick').val()); var lServer = path_sel.find('.server').val();
var lPass = $(lPath + '.password').val(); var lNick = Common.nodeprep(path_sel.find('.nick').val());
var lResource = $(lPath + '.resource').val(); var lPass = path_sel.find('.password').val();
var lPriority = $(lPath + '.priority').val(); var lResource = path_sel.find('.resource').val();
var lRemember = $(lPath + '.remember').filter(':checked').size(); var lPriority = path_sel.find('.priority').val();
var lRemember = path_sel.find('.remember').filter(':checked').size();
// Enough values? // Enough values?
if(lServer && lNick && lPass && lResource && lPriority) { if(lServer && lNick && lPass && lResource && lPriority) {
@ -303,12 +365,13 @@ var Home = (function () {
$(lPath + 'input[type="text"], ' + lPath + 'input[type="password"]').each(function() { $(lPath + 'input[type="text"], ' + lPath + 'input[type="password"]').each(function() {
var select = $(this); var select = $(this);
if(!select.val()) if(!select.val()) {
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
select.addClass('please-complete').focus(); select.addClass('please-complete').focus();
}); });
else } else {
select.removeClass('please-complete'); select.removeClass('please-complete');
}
}); });
} }
} catch(e) { } catch(e) {
@ -328,17 +391,18 @@ var Home = (function () {
self.registerForm = function() { self.registerForm = function() {
try { try {
var rPath = '#home .registerer '; var path = '#home .registerer';
var path_sel = $(path);
// Remove the success info // Remove the success info
$(rPath + '.success').remove(); path_sel.find('.success').remove();
// Get the values // Get the values
var username = Common.nodeprep($(rPath + '.nick').val()); var username = Common.nodeprep(path_sel.find('.nick').val());
var domain = $(rPath + '.server').val(); var domain = path_sel.find('.server').val();
var pass = $(rPath + '.password').val(); var pass = path_sel.find('.password').val();
var spass = $(rPath + '.spassword').val(); var spass = path_sel.find('.spassword').val();
var captcha = $(rPath + '.captcha').val(); var captcha = path_sel.find('.captcha').val();
// Enough values? // Enough values?
if(domain && username && pass && spass && (pass == spass) && !((REGISTER_API == 'on') && (domain == HOST_MAIN) && !captcha)) { if(domain && username && pass && spass && (pass == spass) && !((REGISTER_API == 'on') && (domain == HOST_MAIN) && !captcha)) {
@ -351,15 +415,16 @@ var Home = (function () {
// Something is missing? // Something is missing?
else { else {
$(rPath + 'input[type="text"], ' + rPath + 'input[type="password"]').each(function() { $(path + ' input[type="text"], ' + path + ' input[type="password"]').each(function() {
var select = $(this); 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() { $(document).oneTime(10, function() {
select.addClass('please-complete').focus(); select.addClass('please-complete').focus();
}); });
else } else {
select.removeClass('please-complete'); select.removeClass('please-complete');
}
}); });
} }
} catch(e) { } catch(e) {
@ -394,12 +459,14 @@ var Home = (function () {
// Allows the user to switch the home page // Allows the user to switch the home page
$(button).click(function() { $(button).click(function() {
// Login button // Login button
if($(this).is('.login')) if($(this).is('.login')) {
return self.change('loginer'); return self.change('loginer');
}
// Register button // Register button
else else {
return self.change('registerer'); return self.change('registerer');
}
}); });
// Allows the user to view the corporation & about infobox // Allows the user to view the corporation & about infobox
@ -430,31 +497,14 @@ var Home = (function () {
// Disables the browser HTTP-requests stopper // Disables the browser HTTP-requests stopper
$(document).keydown(function(e) { $(document).keydown(function(e) {
if((e.keyCode == 27) && !System.isDeveloper()) if((e.keyCode == 27) && !System.isDeveloper()) {
return false; return false;
}
}); });
// Warns for an obsolete browser // Warns for an obsolete browser
if(Utils.isObsolete()) { if(Utils.isObsolete()) {
// Add the code self._obsolete();
$(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!');
} }
Console.log('Welcome to Jappix! Happy coding in developer mode!'); Console.log('Welcome to Jappix! Happy coding in developer mode!');
@ -473,4 +523,4 @@ var Home = (function () {
})(); })();
Home.launch(); Home.launch();

View file

@ -34,8 +34,6 @@ var HTTPAuth = (function () {
try { try {
// We add the login wait div // We add the login wait div
Interface.showGeneralWait(); Interface.showGeneralWait();
oArgs = {};
if(Common.hasWebSocket()) { if(Common.hasWebSocket()) {
// WebSocket supported & configured // WebSocket supported & configured
@ -67,15 +65,6 @@ var HTTPAuth = (function () {
// Generate a priority // Generate a priority
lPriority = lPriority ? lPriority : 10; 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) // Store the resource (for reconnection)
DataStore.setDB(Connection.desktop_hash, 'session', 'resource', random_resource); DataStore.setDB(Connection.desktop_hash, 'session', 'resource', random_resource);
@ -89,7 +78,14 @@ var HTTPAuth = (function () {
DataStore.setDB(Connection.desktop_hash, 'priority', 1, 10); DataStore.setDB(Connection.desktop_hash, 'priority', 1, 10);
// We connect ! // 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 // Change the page title
Interface.title('wait'); Interface.title('wait');

View file

@ -45,11 +45,19 @@ var HTTPReply = (function () {
// If "no" // If "no"
if(value == 'no') { if(value == 'no') {
aMsg.setType('error'); aMsg.setType('error');
aMsg.appendNode('error', {'code': '401', 'type': 'auth'}); aMsg.appendNode('error', {
'code': '401',
'type': 'auth'
});
} }
// We set the confirm node // 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 // We send the message
con.send(aMsg, Errors.handleReply); con.send(aMsg, Errors.handleReply);

View file

@ -176,17 +176,16 @@ var Inbox = (function () {
var value = $(Common.XMLFromString(DataStore.storageDB.getItem(current))); var value = $(Common.XMLFromString(DataStore.storageDB.getItem(current)));
// Create the storage node // Create the storage node
storage.appendChild(iq.buildNode('message', { storage.appendChild(
'id': value.find('id').text().revertHtmlEnc(), iq.buildNode('message', {
'from': value.find('from').text().revertHtmlEnc(), 'id': value.find('id').text().revertHtmlEnc(),
'subject': value.find('subject').text().revertHtmlEnc(), 'from': value.find('from').text().revertHtmlEnc(),
'status': value.find('status').text().revertHtmlEnc(), 'subject': value.find('subject').text().revertHtmlEnc(),
'date': value.find('date').text().revertHtmlEnc(), 'status': value.find('status').text().revertHtmlEnc(),
'xmlns': NS_INBOX 'date': value.find('date').text().revertHtmlEnc(),
}, 'xmlns': NS_INBOX
}, value.find('content').text().revertHtmlEnc()
value.find('content').text().revertHtmlEnc() ));
));
} }
} }
@ -207,18 +206,18 @@ var Inbox = (function () {
try { try {
// Init // Init
var mPath = '#inbox .'; var inbox_sel = $('#inbox');
// Reset the previous buddy search // Reset the previous buddy search
Search.resetBuddy('#inbox .inbox-new-to'); Search.resetBuddy('#inbox .inbox-new-to');
// We switch the divs // We switch the divs
$(mPath + 'inbox-results, #inbox .a-new-message, #inbox .a-delete-messages').hide(); inbox_sel.find('.inbox-results, .a-new-message, .a-delete-messages').hide();
$(mPath + 'inbox-new, #inbox .a-show-messages').show(); inbox_sel.find('.inbox-new, .a-show-messages').show();
// We focus on the first input // We focus on the first input
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
$(mPath + 'inbox-new-to-input').focus(); inbox_sel.find('.inbox-new-to-input').focus();
}); });
// We reset some stuffs // We reset some stuffs
@ -241,16 +240,16 @@ var Inbox = (function () {
try { try {
// Init // Init
var mPath = '#inbox .'; var inbox_sel = $('#inbox');
// We reset the forms // We reset the forms
$(mPath + 'inbox-new-block:not(form) input, ' + mPath + 'inbox-new textarea').val('').removeClass('please-complete'); inbox_sel.find('.inbox-new-block:not(form) input, .inbox-new textarea').val('').removeClass('please-complete');
$(mPath + 'inbox-new-file a').remove(); inbox_sel.find('.inbox-new-file a').remove();
$(mPath + 'inbox-new-file input').show(); inbox_sel.find('.inbox-new-file input').show();
// We close an eventual opened message // We close an eventual opened message
$(mPath + 'message-content').remove(); inbox_sel.find('.message-content').remove();
$(mPath + 'one-message').removeClass('message-reading'); inbox_sel.find('.one-message').removeClass('message-reading');
} catch(e) { } catch(e) {
Console.error('Inbox.cleanNewMessage', e); Console.error('Inbox.cleanNewMessage', e);
} }
@ -270,26 +269,26 @@ var Inbox = (function () {
try { try {
// We send the message // We send the message
var mess = new JSJaCMessage(); var message = new JSJaCMessage();
// Main attributes // Main attributes
mess.setTo(to); message.setTo(to);
mess.setSubject(subject); message.setSubject(subject);
mess.setType('normal'); message.setType('normal');
// Any file to attach? // Any file to attach?
var attached = '#inbox .inbox-new-file a.file'; var attached = '#inbox .inbox-new-file a.file';
if(Common.exists(attached)) { if(Common.exists(attached)) {
body += '\n' + body += '\n' +
'\n' + '\n' +
$(attached).attr('data-attachedtitle') + ' - ' + $(attached).attr('data-attachedhref'); $(attached).attr('data-attachedtitle') + ' - ' + $(attached).attr('data-attachedhref');
} }
// Set body // Set body
mess.setBody(body); message.setBody(body);
con.send(mess, Errors.handleReply); con.send(message, Errors.handleReply);
} catch(e) { } catch(e) {
Console.error('Inbox.sendMessage', e); Console.error('Inbox.sendMessage', e);
} }
@ -306,10 +305,10 @@ var Inbox = (function () {
try { try {
// We get some informations // We get some informations
var mPath = '#inbox '; var inbox_sel = $('#inbox');
var to = $(mPath + '.inbox-new-to-input').val(); var to = inbox_sel.find('.inbox-new-to-input').val();
var body = $(mPath + '.inbox-new-textarea').val(); var body = inbox_sel.find('.inbox-new-textarea').val();
var subject = $(mPath + '.inbox-new-subject-input').val(); var subject = inbox_sel.find('.inbox-new-subject-input').val();
if(to && body && subject) { if(to && body && subject) {
// New array of XID // New array of XID
@ -345,15 +344,15 @@ var Inbox = (function () {
} }
else { else {
$(mPath + 'input[type="text"], ' + mPath + 'textarea').each(function() { inbox_sel.find('input[type="text"], textarea').each(function() {
var current = this; var this_sel = $(this);
if(!$(current).val()) { if(!this_sel.val()) {
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
$(current).addClass('please-complete').focus(); this_sel.addClass('please-complete').focus();
}); });
} else { } else {
$(current).removeClass('please-complete'); this_sel.removeClass('please-complete');
} }
}); });
} }
@ -374,17 +373,16 @@ var Inbox = (function () {
self.showMessage = function() { self.showMessage = function() {
try { try {
// Init var inbox_sel = $('#inbox');
var mPath = '#inbox .';
// We switch the divs // We switch the divs
$(mPath + 'inbox-new').hide(); inbox_sel.find('.inbox-new').hide();
$(mPath + 'inbox-results').show(); inbox_sel.find('.inbox-results').show();
// We show a new link in the menu // We show a new link in the menu
$(mPath + 'a-show-messages').hide(); inbox_sel.find('.a-show-messages').hide();
$(mPath + 'a-delete-messages').show(); inbox_sel.find('.a-delete-messages').show();
$(mPath + 'a-new-message').show(); inbox_sel.find('.a-new-message').show();
// We reset some stuffs // We reset some stuffs
self.cleanNewMessage(); self.cleanNewMessage();
@ -484,10 +482,14 @@ var Inbox = (function () {
try { try {
// Initialize the XML data // 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>'; var xml = '<message>' +
'<id>' + id.htmlEnc().htmlEnc() + '</id>' +
// End the XML data '<date>' + date.htmlEnc().htmlEnc() + '</date>' +
xml += '</message>'; '<from>' + from.htmlEnc().htmlEnc() + '</from>' +
'<subject>' + subject.htmlEnc().htmlEnc() + '</subject>' +
'<status>' + status.htmlEnc().htmlEnc() + '</status>' +
'<content>' + content.htmlEnc().htmlEnc() + '</content>' +
'</message>';
// Store this message! // Store this message!
DataStore.setDB(Connection.desktop_hash, 'inbox', id, xml); DataStore.setDB(Connection.desktop_hash, 'inbox', id, xml);
@ -504,7 +506,7 @@ var Inbox = (function () {
* @param {string} id * @param {string} id
* @return {boolean} * @return {boolean}
*/ */
self.deleteMessage = function() { self.deleteMessage = function(id) {
try { try {
// Remove the message from the inbox // Remove the message from the inbox
@ -794,13 +796,13 @@ var Inbox = (function () {
// Display the current message // Display the current message
self.displayMessage( self.displayMessage(
value.find('from').text().revertHtmlEnc(), value.find('from').text().revertHtmlEnc(),
value.find('subject').text().revertHtmlEnc(), value.find('subject').text().revertHtmlEnc(),
value.find('content').text().revertHtmlEnc(), value.find('content').text().revertHtmlEnc(),
value.find('status').text().revertHtmlEnc(), value.find('status').text().revertHtmlEnc(),
value.find('id').text().revertHtmlEnc(), value.find('id').text().revertHtmlEnc(),
value.find('date').text().revertHtmlEnc() value.find('date').text().revertHtmlEnc()
); );
} }
} }
@ -854,16 +856,30 @@ var Inbox = (function () {
// Hide the attach link, show the unattach one // Hide the attach link, show the unattach one
$('#inbox .inbox-new-file input').hide(); $('#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 // Set values to the file link
$('#inbox .inbox-new-file a.file').attr('data-attachedtitle', fName) var inbox_file_sel = $('#inbox .inbox-new-file a.file');
.attr('data-attachedhref', fURL);
inbox_file_sel.attr('data-attachedtitle', fName);
inbox_file_sel.attr('data-attachedhref', fURL);
// Click events // Click events
$('#inbox .inbox-new-file a.remove').click(function() { var inbox_new_file_sel = $('#inbox .inbox-new-file');
$('#inbox .inbox-new-file a').remove();
$('#inbox .inbox-new-file input').show(); 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; return false;
}); });
@ -899,10 +915,11 @@ var Inbox = (function () {
// Send the message when enter pressend // Send the message when enter pressend
$(inbox + 'inbox-new input').keyup(function(e) { $(inbox + 'inbox-new input').keyup(function(e) {
if(e.keyCode == 13) { if(e.keyCode == 13) {
if(Common.exists(dHovered)) if(Common.exists(dHovered)) {
Search.addBuddy(destination, $(dHovered).attr('data-xid')); Search.addBuddy(destination, $(dHovered).attr('data-xid'));
else } else {
self.checkMessage(); self.checkMessage();
}
} }
}); });
@ -948,7 +965,7 @@ var Inbox = (function () {
// File upload // File upload
var attach_options = { var attach_options = {
dataType: 'xml', dataType: 'xml',
beforeSubmit: self.waitAttach, beforeSubmit: self.waitAttach,
success: self.handleAttach success: self.handleAttach
}; };

View file

@ -161,8 +161,9 @@ var IntegrateBox = (function () {
self.close(); self.close();
// Media integration not wanted? // Media integration not wanted?
if(DataStore.getDB(Connection.desktop_hash, 'options', 'integratemedias') == '0') if(DataStore.getDB(Connection.desktop_hash, 'options', 'integratemedias') == '0') {
return true; return true;
}
// Apply the HTML code // Apply the HTML code
var dom_code = self.code(service, url); var dom_code = self.code(service, url);

View file

@ -74,8 +74,9 @@ var Interface = (function () {
try { try {
// Item exists? // Item exists?
if(Common.exists('#general-wait')) if(Common.exists('#general-wait')) {
return false; return false;
}
// Generate the HTML code // Generate the HTML code
var html = var html =
@ -178,8 +179,9 @@ var Interface = (function () {
var more_content = '#page-switch .more-content'; var more_content = '#page-switch .more-content';
// Yet displayed? // Yet displayed?
if(Common.exists(more_content)) if(Common.exists(more_content)) {
return Bubble.close(); return Bubble.close();
}
// Add the bubble // Add the bubble
Bubble.show(more_content); Bubble.show(more_content);
@ -397,32 +399,48 @@ var Interface = (function () {
var date = DateUtils.getXMPPTime('local'); var date = DateUtils.getXMPPTime('local');
var type = $('#' + hash).attr('data-type'); var type = $('#' + hash).attr('data-type');
var direction = $('html').attr('dir') || 'ltr'; var direction = $('html').attr('dir') || 'ltr';
var content_sel = $(content);
// Filter the content smileys // Filter the content smileys
$(content).find('img.emoticon').each(function() { content_sel.find('img.emoticon').each(function() {
$(this).replaceWith($(this).attr('alt')); $(this).replaceWith($(this).attr('alt'));
}); });
// Remove the useless attributes // Remove the useless attributes
$(content).removeAttr('data-type').removeAttr('data-stamp'); content_sel.removeAttr('data-type').removeAttr('data-stamp');
// Remove the content avatars // 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 // Remove the content click events
$(content).find('a').removeAttr('onclick'); content_sel.find('a').removeAttr('onclick');
// Extract the content HTML code // Extract the content HTML code
content = $(content).parent().html(); content = content_sel.parent().html();
// No avatar? // No avatar?
if(!avatar || !avatar.match(/data:/)) if(!avatar || !avatar.match(/data:/)) {
avatar = 'none'; avatar = 'none';
}
// POST the values to the server // 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! // 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) { } catch(e) {
Console.error('Interface.generateChatLog', 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 * Notifies the user from a new incoming message
* @public * @public
@ -449,7 +492,7 @@ var Interface = (function () {
var active = $(tested).hasClass('activechan'); var active = $(tested).hasClass('activechan');
// We notify the user if he has not the focus on the chat // 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(!active) {
if(type == 'personal') { if(type == 'personal') {
$(tested + ', ' + chat_switch + 'more-button').addClass('chan-newmessage'); $(tested + ', ' + chat_switch + 'more-button').addClass('chan-newmessage');
@ -509,10 +552,11 @@ var Interface = (function () {
try { try {
// Any pending events? // Any pending events?
if(Common.exists('.one-counter[data-counter]')) if(Common.exists('.one-counter[data-counter]')) {
self.title('new'); self.title('new');
else } else {
self.title('talk'); self.title('talk');
}
} catch(e) { } catch(e) {
Console.error('Interface.updateTitle', e); Console.error('Interface.updateTitle', e);
} }
@ -534,8 +578,9 @@ var Interface = (function () {
$(chat_switch + hash).removeClass('chan-newmessage chan-unread'); $(chat_switch + hash).removeClass('chan-newmessage chan-unread');
// We reset the global notifications if no more unread messages // 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'); $(chat_switch + 'more-button').removeClass('chan-newmessage');
}
// We reset the chat counter // We reset the chat counter
$('#' + hash).removeAttr('data-counter'); $('#' + hash).removeAttr('data-counter');
@ -598,8 +643,9 @@ var Interface = (function () {
// We show all the groups // We show all the groups
$('#roster .one-group').show(); $('#roster .one-group').show();
if(Search.search_filtered) if(Search.search_filtered) {
Search.funnelFilterBuddy(); Search.funnelFilterBuddy();
}
// Store this in the options // Store this in the options
if((from == 'roster') && Options.loaded()) { if((from == 'roster') && Options.loaded()) {
@ -687,6 +733,39 @@ var Interface = (function () {
$(document).ready(function() { $(document).ready(function() {
// Focus on the first visible input // Focus on the first visible input
$(window).focus(self.inputFocus); $(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) { } catch(e) {
Console.error('Interface.launch', e); Console.error('Interface.launch', e);

View file

@ -20,6 +20,352 @@ var IQ = (function () {
var self = {}; 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 * Handles an incoming IQ packet
* @public * @public
@ -37,9 +383,6 @@ var IQ = (function () {
var iqQuery = iq.getQuery(); var iqQuery = iq.getQuery();
var iqType = iq.getType(); var iqType = iq.getType();
// Handle Jingle packet?
JSJaCJingle_route(iq);
// Build the response // Build the response
var iqResponse = new JSJaCIQ(); var iqResponse = new JSJaCIQ();
@ -49,178 +392,62 @@ var IQ = (function () {
// OOB request // OOB request
if((iqQueryXMLNS == NS_IQOOB) && (iqType == 'set')) { if((iqQueryXMLNS == NS_IQOOB) && (iqType == 'set')) {
/* REF: http://xmpp.org/extensions/xep-0066.html */ self._handleOOBRequest(iqFrom, iqID, iqNode);
OOB.handle(iqFrom, iqID, 'iq', iqNode);
Console.log('Received IQ OOB request: ' + iqFrom);
} }
// OOB reply // OOB reply
else if(DataStore.getDB(Connection.desktop_hash, 'send/url', iqID)) { else if(DataStore.getDB(Connection.desktop_hash, 'send/url', iqID)) {
// Get the values self._handleOOBReply(iqResponse, iqFrom, iqType, iqID, iqNode);
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);
}
} }
// Software version query // Software version query
else if((iqQueryXMLNS == NS_VERSION) && (iqType == 'get')) { else if((iqQueryXMLNS == NS_VERSION) && (iqType == 'get')) {
/* REF: http://xmpp.org/extensions/xep-0092.html */ self._handleSoftwareVersion(iqResponse, iqFrom);
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);
} }
// Last activity query // Last activity query
else if((iqQueryXMLNS == NS_LAST) && (iqType == 'get')) { else if((iqQueryXMLNS == NS_LAST) && (iqType == 'get')) {
/* REF: http://xmpp.org/extensions/xep-0012.html */ self._handleLastActivity(iqResponse, iqFrom);
iqQuery = iqResponse.setQuery(NS_LAST);
iqQuery.setAttribute('seconds', DateUtils.getLastActivity());
con.send(iqResponse);
Console.log('Received last activity query: ' + iqFrom);
} }
// Privacy lists push // Privacy lists push
else if((iqQueryXMLNS == NS_PRIVACY) && (iqType == 'set') && Common.isSafeStanza(iq)) { else if((iqQueryXMLNS == NS_PRIVACY) && (iqType == 'set') && Common.isSafeStanza(iq)) {
// REF : http://xmpp.org/extensions/xep-0016.html self._handlePrivacyLists(iqResponse, iqFrom, iqQuery);
// 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);
} }
// Roster push // Roster push
else if((iqQueryXMLNS == NS_ROSTER) && (iqType == 'set') && Common.isSafeStanza(iq)) { else if((iqQueryXMLNS == NS_ROSTER) && (iqType == 'set') && Common.isSafeStanza(iq)) {
// REF : http://xmpp.org/extensions/xep-0092.html self._handleRosterPush(iqResponse, iqFrom, iqQuery);
// Roster push
con.send(iqResponse);
// Get the values
$(iqQuery).find('item').each(function() {
Roster.parse($(this), 'presence');
});
Console.log('Received roster push: ' + iqFrom);
} }
// Roster Item Exchange query // Roster Item Exchange query
else if($(iqNode).find('x[xmlns="' + NS_ROSTERX + '"]').size()) { else if($(iqNode).find('x[xmlns="' + NS_ROSTERX + '"]').size()) {
// Open a new notification self._handleRosterItemExchange(iqNode, iqFrom);
Notification.create('rosterx', iqFrom, [iqNode], '');
Console.log('Roster Item Exchange from: ' + iqFrom);
} }
// Disco info query // Disco info query
else if((iqQueryXMLNS == NS_DISCO_INFO) && (iqType == 'get')) { else if((iqQueryXMLNS == NS_DISCO_INFO) && (iqType == 'get')) {
/* REF: http://xmpp.org/extensions/xep-0030.html */ self._handleDiscoInfo(iqResponse, iqFrom);
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);
} }
// User time query // User time query
else if($(iqNode).find('time').size() && (iqType == 'get')) { else if($(iqNode).find('time').size() && (iqType == 'get')) {
/* REF: http://xmpp.org/extensions/xep-0202.html */ self._handleUserTime(iqResponse, iqFrom);
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);
} }
// Ping // Ping
else if($(iqNode).find('ping').size() && (iqType == 'get')) { else if($(iqNode).find('ping').size() && (iqType == 'get')) {
/* REF: http://xmpp.org/extensions/xep-0199.html */ self._handlePing(iqResponse, iqFrom);
con.send(iqResponse);
Console.log('Received a ping: ' + iqFrom);
} }
// Jingle // Jingle
else if($(iqNode).find('jingle').size()) { else if($(iqNode).find('jingle').size()) {
/* REF: http://xmpp.org/extensions/xep-0166.html */ self._handleJingle(iqFrom);
// Handled via JSJaCJingle_route() (see above)
Console.log('Received a Jingle packet: ' + iqFrom);
} }
// Not implemented // Not implemented
else if(!$(iqNode).find('error').size() && ((iqType == 'get') || (iqType == 'set'))) { else if(!$(iqNode).find('error').size() && ((iqType == 'get') || (iqType == 'set'))) {
// Change IQ type self._raiseNotImplemented(iqResponse, iqNode, iqFrom);
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) { } catch(e) {
Console.error('IQ.handle', e); Console.error('IQ.handle', e);

File diff suppressed because it is too large Load diff

View file

@ -1,138 +1,138 @@
/** /**
* jQuery.timers - Timer abstractions for jQuery * jQuery.timers - Timer abstractions for jQuery
* Written by Blair Mitchelmore (blair DOT mitchelmore AT gmail DOT com) * Written by Blair Mitchelmore (blair DOT mitchelmore AT gmail DOT com)
* Licensed under the WTFPL (http://sam.zoy.org/wtfpl/). * Licensed under the WTFPL (http://sam.zoy.org/wtfpl/).
* Date: 2009/10/16 * Date: 2009/10/16
* *
* @author Blair Mitchelmore * @author Blair Mitchelmore
* @version 1.2 * @version 1.2
* *
**/ **/
jQuery.fn.extend({ jQuery.fn.extend({
everyTime: function(interval, label, fn, times) { everyTime: function(interval, label, fn, times) {
return this.each(function() { return this.each(function() {
jQuery.timer.add(this, interval, label, fn, times); jQuery.timer.add(this, interval, label, fn, times);
}); });
}, },
oneTime: function(interval, label, fn) { oneTime: function(interval, label, fn) {
return this.each(function() { return this.each(function() {
jQuery.timer.add(this, interval, label, fn, 1); jQuery.timer.add(this, interval, label, fn, 1);
}); });
}, },
stopTime: function(label, fn) { stopTime: function(label, fn) {
return this.each(function() { return this.each(function() {
jQuery.timer.remove(this, label, fn); jQuery.timer.remove(this, label, fn);
}); });
} }
}); });
jQuery.extend({ jQuery.extend({
timer: { timer: {
global: [], global: [],
guid: 1, guid: 1,
dataKey: "jQuery.timer", dataKey: "jQuery.timer",
regex: /^([0-9]+(?:\.[0-9]*)?)\s*(.*s)?$/, regex: /^([0-9]+(?:\.[0-9]*)?)\s*(.*s)?$/,
powers: { powers: {
// Yeah this is major overkill... // Yeah this is major overkill...
'ms': 1, 'ms': 1,
'cs': 10, 'cs': 10,
'ds': 100, 'ds': 100,
's': 1000, 's': 1000,
'das': 10000, 'das': 10000,
'hs': 100000, 'hs': 100000,
'ks': 1000000 'ks': 1000000
}, },
timeParse: function(value) { timeParse: function(value) {
if (value == undefined || value == null) if (value == undefined || value == null)
return null; return null;
var result = this.regex.exec(jQuery.trim(value.toString())); var result = this.regex.exec(jQuery.trim(value.toString()));
if (result[2]) { if (result[2]) {
var num = parseFloat(result[1]); var num = parseFloat(result[1]);
var mult = this.powers[result[2]] || 1; var mult = this.powers[result[2]] || 1;
return num * mult; return num * mult;
} else { } else {
return value; return value;
} }
}, },
add: function(element, interval, label, fn, times) { add: function(element, interval, label, fn, times) {
var counter = 0; var counter = 0;
if (jQuery.isFunction(label)) { if (jQuery.isFunction(label)) {
if (!times) if (!times)
times = fn; times = fn;
fn = label; fn = label;
label = interval; label = interval;
} }
interval = jQuery.timer.timeParse(interval); interval = jQuery.timer.timeParse(interval);
if (typeof interval != 'number' || isNaN(interval) || interval < 0) if (typeof interval != 'number' || isNaN(interval) || interval < 0)
return; return;
if (typeof times != 'number' || isNaN(times) || times < 0) if (typeof times != 'number' || isNaN(times) || times < 0)
times = 0; times = 0;
times = times || 0; times = times || 0;
var timers = jQuery.data(element, this.dataKey) || jQuery.data(element, this.dataKey, {}); var timers = jQuery.data(element, this.dataKey) || jQuery.data(element, this.dataKey, {});
if (!timers[label]) if (!timers[label])
timers[label] = {}; timers[label] = {};
fn.timerID = fn.timerID || this.guid++; fn.timerID = fn.timerID || this.guid++;
var handler = function() { var handler = function() {
if ((++counter > times && times !== 0) || fn.call(element, counter) === false) if ((++counter > times && times !== 0) || fn.call(element, counter) === false)
jQuery.timer.remove(element, label, fn); jQuery.timer.remove(element, label, fn);
}; };
handler.timerID = fn.timerID; handler.timerID = fn.timerID;
if (!timers[label][fn.timerID]) if (!timers[label][fn.timerID])
timers[label][fn.timerID] = window.setInterval(handler,interval); timers[label][fn.timerID] = window.setInterval(handler,interval);
this.global.push( element ); this.global.push( element );
}, },
remove: function(element, label, fn) { remove: function(element, label, fn) {
var timers = jQuery.data(element, this.dataKey), ret; var timers = jQuery.data(element, this.dataKey), ret;
if ( timers ) { if ( timers ) {
if (!label) { if (!label) {
for ( label in timers ) for ( label in timers )
this.remove(element, label, fn); this.remove(element, label, fn);
} else if ( timers[label] ) { } else if ( timers[label] ) {
if ( fn ) { if ( fn ) {
if ( fn.timerID ) { if ( fn.timerID ) {
window.clearInterval(timers[label][fn.timerID]); window.clearInterval(timers[label][fn.timerID]);
delete timers[label][fn.timerID]; delete timers[label][fn.timerID];
} }
} else { } else {
for ( var fn in timers[label] ) { for ( var fn in timers[label] ) {
window.clearInterval(timers[label][fn]); window.clearInterval(timers[label][fn]);
delete timers[label][fn]; delete timers[label][fn];
} }
} }
for ( ret in timers[label] ) break; for ( ret in timers[label] ) break;
if ( !ret ) { if ( !ret ) {
ret = null; ret = null;
delete timers[label]; delete timers[label];
} }
} }
for ( ret in timers ) break; for ( ret in timers ) break;
if ( !ret ) if ( !ret )
jQuery.removeData(element, this.dataKey); jQuery.removeData(element, this.dataKey);
} }
} }
} }
}); });
jQuery(window).bind("unload", function() { jQuery(window).bind("unload", function() {
jQuery.each(jQuery.timer.global, function(index, item) { jQuery.each(jQuery.timer.global, function(index, item) {
jQuery.timer.remove(item); jQuery.timer.remove(item);
}); });
}); });

File diff suppressed because it is too large Load diff

View file

@ -14,11 +14,11 @@ Authors: Stefan Strigler, Valérian Saliou, Zash, Maranda
* @fileoverview Magic dependency loading. Taken from script.aculo.us * @fileoverview Magic dependency loading. Taken from script.aculo.us
* and modified to break it. * and modified to break it.
* @author Stefan Strigler steve@zeank.in-berlin.de * @author Stefan Strigler steve@zeank.in-berlin.de
* @version $Revision$ * @version 1.3
*/ */
var JSJaC = { var JSJaC = {
Version: '$Rev$', Version: '1.3',
bind: function(fn, obj, optArg) { bind: function(fn, obj, optArg) {
return function(arg) { return function(arg) {
return fn.apply(obj, [arg, optArg]); return fn.apply(obj, [arg, optArg]);
@ -26,9 +26,6 @@ var JSJaC = {
} }
}; };
if (typeof JSJaCConnection == 'undefined')
JSJaC.load();
/* Copyright 2006 Erik Arvidsson /* Copyright 2006 Erik Arvidsson
@ -52,7 +49,7 @@ if (typeof JSJaCConnection == 'undefined')
* this code is taken from * this code is taken from
* http://webfx.eae.net/dhtml/xmlextras/xmlextras.html * http://webfx.eae.net/dhtml/xmlextras/xmlextras.html
* @author Stefan Strigler steve@zeank.in-berlin.de * @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 * @fileoverview Collection of functions to make live easier
* @author Stefan Strigler * @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 * @fileoverview This file contains all things that make life easier when
* dealing with JIDs * dealing with JIDs
* @author Stefan Strigler * @author Stefan Strigler
* @version $Revision$ * @version 1.3
*/ */
/** /**
@ -1714,7 +1711,7 @@ var JSJaCBuilder = {
/** /**
* @fileoverview Contains all Jabber/XMPP packet related classes. * @fileoverview Contains all Jabber/XMPP packet related classes.
* @author Stefan Strigler steve@zeank.in-berlin.de * @author Stefan Strigler steve@zeank.in-berlin.de
* @version $Revision$ * @version 1.3
*/ */
var JSJACPACKET_USE_XMLNS = true; var JSJACPACKET_USE_XMLNS = true;
@ -2567,7 +2564,7 @@ function JSJaCKeys(func,oDbg) {
* @fileoverview Contains all things in common for all subtypes of connections * @fileoverview Contains all things in common for all subtypes of connections
* supported. * supported.
* @author Stefan Strigler steve@zeank.in-berlin.de * @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()) if (!packet.getID())
return false; return false;
if (packet.pType() != 'iq' ||
(packet.getType() != 'error' && packet.getType() != 'result'))
return false;
var jid = packet.getFrom() || this.jid; var jid = packet.getFrom() || this.jid;
if (packet.getFrom() == this.domain) if (packet.getFrom() == this.domain)
@ -3723,7 +3716,7 @@ JSJaCConnection.prototype._parseStreamFeatures = function(doc) {
// Get legacy session capability if available // Get legacy session capability if available
this.legacy_sessions=null; this.legacy_sessions=null;
if (doc.getElementsByTagName("session")[0]) { if (doc.getElementsByTagName("session")) {
this.legacy_sessions=true; this.legacy_sessions=true;
} }
@ -3955,7 +3948,7 @@ JSJaCConnection.prototype._setStatus = function(status) {
/** /**
* @fileoverview All stuff related to HTTP Binding * @fileoverview All stuff related to HTTP Binding
* @author Stefan Strigler steve@zeank.in-berlin.de * @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); this.oDbg.log('Parsing: ' + s, 4);
try { try {
doc = XmlDocument.create('stream', NS_STREAM); 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. // 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>"); doc.loadXML("<stream:stream xmlns:stream='" + NS_STREAM + "' xmlns='jabber:client'>" + s + "</stream:stream>");
return doc.documentElement.firstChild; return doc.documentElement.firstChild;
@ -5018,3 +5030,61 @@ JSJaCWebSocketConnection.prototype._sendRaw = function(xml, cb, arg) {
return true; 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();
}
}
};

View file

@ -1,116 +1,116 @@
// jXHR.js (JSON-P XHR) // jXHR.js (JSON-P XHR)
// v0.1 (c) Kyle Simpson // v0.1 (c) Kyle Simpson
// License: MIT // License: MIT
// modified by gueron Jonathan to work with strophe lib // modified by gueron Jonathan to work with strophe lib
// for http://www.iadvize.com // for http://www.iadvize.com
(function(global){ (function(global){
var SETTIMEOUT = global.setTimeout, // for better compression var SETTIMEOUT = global.setTimeout, // for better compression
doc = global.document, doc = global.document,
callback_counter = 0; callback_counter = 0;
global.jXHR = function() { global.jXHR = function() {
var script_url, var script_url,
script_loaded, script_loaded,
jsonp_callback, jsonp_callback,
scriptElem, scriptElem,
publicAPI = null; publicAPI = null;
function removeScript() { try { scriptElem.parentNode.removeChild(scriptElem); } catch (err) { } } function removeScript() { try { scriptElem.parentNode.removeChild(scriptElem); } catch (err) { } }
function reset() { function reset() {
script_loaded = false; script_loaded = false;
script_url = ""; script_url = "";
removeScript(); removeScript();
scriptElem = null; scriptElem = null;
fireReadyStateChange(0); fireReadyStateChange(0);
} }
function ThrowError(msg) { function ThrowError(msg) {
try { try {
publicAPI.onerror.call(publicAPI,msg,script_url); publicAPI.onerror.call(publicAPI,msg,script_url);
} catch (err) { } catch (err) {
//throw new Error(msg); //throw new Error(msg);
} }
} }
function handleScriptLoad() { function handleScriptLoad() {
if ((this.readyState && this.readyState!=="complete" && this.readyState!=="loaded") || script_loaded) { return; } if ((this.readyState && this.readyState!=="complete" && this.readyState!=="loaded") || script_loaded) { return; }
this.onload = this.onreadystatechange = null; // prevent memory leak this.onload = this.onreadystatechange = null; // prevent memory leak
script_loaded = true; script_loaded = true;
if (publicAPI.readyState !== 4) ThrowError("handleScriptLoad: Script failed to load ["+script_url+"]."); if (publicAPI.readyState !== 4) ThrowError("handleScriptLoad: Script failed to load ["+script_url+"].");
removeScript(); removeScript();
} }
function parseXMLString(xmlStr) { function parseXMLString(xmlStr) {
var xmlDoc = null; var xmlDoc = null;
if(window.DOMParser) { if(window.DOMParser) {
var parser = new DOMParser(); var parser = new DOMParser();
xmlDoc = parser.parseFromString(xmlStr,"text/xml"); xmlDoc = parser.parseFromString(xmlStr,"text/xml");
} }
else { else {
xmlDoc = new ActiveXObject("Microsoft.XMLDOM"); xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async="false"; xmlDoc.async="false";
xmlDoc.loadXML(xmlStr); xmlDoc.loadXML(xmlStr);
} }
return xmlDoc; return xmlDoc;
} }
function fireReadyStateChange(rs,args) { function fireReadyStateChange(rs,args) {
args = args || []; args = args || [];
publicAPI.readyState = rs; publicAPI.readyState = rs;
if (rs == 4) { if (rs == 4) {
publicAPI.responseText = args[0].reply; publicAPI.responseText = args[0].reply;
publicAPI.responseXML = parseXMLString(args[0].reply); publicAPI.responseXML = parseXMLString(args[0].reply);
} }
if (typeof publicAPI.onreadystatechange === "function") publicAPI.onreadystatechange.apply(publicAPI,args); if (typeof publicAPI.onreadystatechange === "function") publicAPI.onreadystatechange.apply(publicAPI,args);
} }
publicAPI = { publicAPI = {
onerror:null, onerror:null,
onreadystatechange:null, onreadystatechange:null,
readyState:0, readyState:0,
status:200, status:200,
responseBody: null, responseBody: null,
responseText: null, responseText: null,
responseXML: null, responseXML: null,
open:function(method,url){ open:function(method,url){
reset(); reset();
var internal_callback = "cb"+(callback_counter++); var internal_callback = "cb"+(callback_counter++);
(function(icb){ (function(icb){
global.jXHR[icb] = function() { global.jXHR[icb] = function() {
try { fireReadyStateChange.call(publicAPI,4,arguments); } try { fireReadyStateChange.call(publicAPI,4,arguments); }
catch(err) { catch(err) {
publicAPI.readyState = -1; publicAPI.readyState = -1;
ThrowError("Script failed to run ["+script_url+"]."); ThrowError("Script failed to run ["+script_url+"].");
} }
global.jXHR[icb] = null; global.jXHR[icb] = null;
}; };
})(internal_callback); })(internal_callback);
script_url = url + '?callback=?jXHR&data='; script_url = url + '?callback=?jXHR&data=';
script_url = script_url.replace(/=\?jXHR/,"=jXHR."+internal_callback); script_url = script_url.replace(/=\?jXHR/,"=jXHR."+internal_callback);
fireReadyStateChange(1); fireReadyStateChange(1);
}, },
send:function(data){ send:function(data){
script_url = script_url + encodeURIComponent(data); script_url = script_url + encodeURIComponent(data);
SETTIMEOUT(function(){ SETTIMEOUT(function(){
scriptElem = doc.createElement("script"); scriptElem = doc.createElement("script");
scriptElem.setAttribute("type","text/javascript"); scriptElem.setAttribute("type","text/javascript");
scriptElem.onload = scriptElem.onreadystatechange = function(){handleScriptLoad.call(scriptElem);}; scriptElem.onload = scriptElem.onreadystatechange = function(){handleScriptLoad.call(scriptElem);};
scriptElem.setAttribute("src",script_url); scriptElem.setAttribute("src",script_url);
doc.getElementsByTagName("head")[0].appendChild(scriptElem); doc.getElementsByTagName("head")[0].appendChild(scriptElem);
},0); },0);
fireReadyStateChange(2); fireReadyStateChange(2);
}, },
abort:function(){}, abort:function(){},
setRequestHeader:function(){}, // noop setRequestHeader:function(){}, // noop
getResponseHeader:function(){return "";}, // basically noop getResponseHeader:function(){return "";}, // basically noop
getAllResponseHeaders:function(){return [];} // ditto getAllResponseHeaders:function(){return [];} // ditto
}; };
reset(); reset();
return publicAPI; return publicAPI;
}; };
})(window); })(window);

View file

@ -34,22 +34,30 @@ var Links = (function () {
var target; var target;
// Links style // Links style
if(!style) if(!style) {
style = ''; style = '';
else } else {
style = ' style="' + style + '"'; style = ' style="' + style + '"';
}
// Open in new tabs // Open in new tabs
if(mode != 'xhtml-im') if(mode != 'xhtml-im') {
target = ' target="_blank"'; target = ' target="_blank"';
else } else {
target = ''; target = '';
}
// XMPP address // 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 // 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; return string;
} catch(e) { } catch(e) {

View file

@ -35,6 +35,7 @@ var MAM = (function () {
self.map_reqs = {}; self.map_reqs = {};
self.map_pending = {}; self.map_pending = {};
self.map_states = {}; self.map_states = {};
self.map_messages = {};
self.msg_queue = {}; self.msg_queue = {};
@ -311,11 +312,16 @@ var MAM = (function () {
if(c_message[0]) { if(c_message[0]) {
// Re-build a proper JSJaC message stanza // Re-build a proper JSJaC message stanza
var message = JSJaCPacket.wrapNode(c_message[0]); var message = JSJaCPacket.wrapNode(c_message[0]);
var message_node = message.getNode();
// Check message type // Check message type
var type = message.getType() || 'chat'; var type = message.getType() || 'chat';
if(type == 'chat') { if(type == 'chat') {
// Display function
var c_display_fn;
var c_display_msg_bool = false;
// Read message data // Read message data
var xid = Common.bareXID(Common.getStanzaFrom(message)); var xid = Common.bareXID(Common.getStanzaFrom(message));
var id = message.getID(); var id = message.getID();
@ -331,50 +337,100 @@ var MAM = (function () {
var hash = hex_md5(xid); var hash = hex_md5(xid);
var body = message.getBody(); var body = message.getBody();
// Read delay (required since we deal w/ a past message!) // Content message?
var time, stamp; if(body) {
var delay = c_delay.attr('stamp'); // Read delay (required since we deal w/ a past message!)
var time, stamp;
var delay = c_delay.attr('stamp');
if(delay) { if(delay) {
time = DateUtils.relative(delay); time = DateUtils.relative(delay);
stamp = DateUtils.extractStamp(Date.jab2date(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;
} }
// 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 // 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 { } else {
// Delay display (we may not have received the MAM reply ATM) // Delay display (we may not have received the MAM reply ATM)
if(typeof self.msg_queue[xid] != 'object') { if(typeof self.msg_queue[xid] != 'object') {
self.msg_queue[xid] = []; self.msg_queue[xid] = [];
} }
self.msg_queue[xid].push(c_msg_display); self.msg_queue[xid].push(c_display_fn);
} }
} }
} }

View 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;
})();

View file

@ -93,12 +93,14 @@ var Me = (function () {
self.instance = function() { self.instance = function() {
try { try {
var me_sel = $('#me');
// Click events // Click events
$('#me .content a.go').click(function() { me_sel.find('.content a.go').click(function() {
self.close(); self.close();
}); });
$('#me .bottom .finish').click(self.close); me_sel.find('.bottom .finish').click(self.close);
} catch(e) { } catch(e) {
Console.error('Me.instance', e); Console.error('Me.instance', e);
} }

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -748,7 +748,7 @@ var JappixMini = (function () {
var resources_obj = {}; var resources_obj = {};
// Is this a groupchat? // 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; xid = from;
} }
@ -1003,7 +1003,7 @@ var JappixMini = (function () {
is_groupchat = true; is_groupchat = true;
// Groupchat buddy presence (not me) // 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 // Regenerate some stuffs
var groupchat = xid; var groupchat = xid;
var groupchat_hash = hash; var groupchat_hash = hash;
@ -1059,7 +1059,7 @@ var JappixMini = (function () {
// Check against search string // Check against search string
var search = jQuery('#jappix_mini div.jm_roster div.jm_search input.jm_searchbox').val(); var search = jQuery('#jappix_mini div.jm_roster div.jm_search input.jm_searchbox').val();
var regex = new RegExp('((^)|( ))' + JappixCommon.escapeRegex(search), 'gi'); 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)) { if(search && !nick.match(regex)) {
jQuery(friend).hide(); jQuery(friend).hide();
@ -1110,7 +1110,7 @@ var JappixMini = (function () {
// Is it a valid server presence? // Is it a valid server presence?
var valid = false; 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; valid = true;
} }
@ -1154,7 +1154,7 @@ var JappixMini = (function () {
self.presence('', '', '', '', room + '/' + nickname, '', true, self.handleMUC); self.presence('', '', '', '', room + '/' + nickname, '', true, self.handleMUC);
// Update the nickname marker // 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 // 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 // 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 // @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) { if(known_roster_entry.size() === 0) {
var subscription = known_roster_entry.attr('data-sub'); 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() { jQuery('#jappix_mini div.jm_conversation[data-type="groupchat"]').each(function() {
var this_sub_sel = jQuery(this); 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 // Loop on XIDs
@ -2032,7 +2032,7 @@ var JappixMini = (function () {
var chat_pwd = MINI_SUGGEST_PASSWORDS[i] || ''; var chat_pwd = MINI_SUGGEST_PASSWORDS[i] || '';
chans_html += 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_icon jm_images"></span>' +
'<span class="jm_chan_name">' + JappixCommon.getXIDNick(chat_room).htmlEnc() + '</span>' + '<span class="jm_chan_name">' + JappixCommon.getXIDNick(chat_room).htmlEnc() + '</span>' +
'</a>'; '</a>';
@ -2064,12 +2064,12 @@ var JappixMini = (function () {
if(!chat_nick) { if(!chat_nick) {
chat_nick = JappixCommon.getXIDNick(chat_xid); chat_nick = JappixCommon.getXIDNick(chat_xid);
} else { } else {
chat_nick = unescape(chat_nick); chat_nick = JappixCommon.unescapeQuotes(chat_nick);
} }
// Generate HTML for current chat // Generate HTML for current chat
chans_html += 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_icon jm_images"></span>' +
'<span class="jm_chan_name">' + JappixCommon.getXIDNick(chat_nick).htmlEnc() + '</span>' + '<span class="jm_chan_name">' + JappixCommon.getXIDNick(chat_nick).htmlEnc() + '</span>' +
'</a>'; '</a>';
@ -2103,18 +2103,18 @@ var JappixMini = (function () {
// Chat? // Chat?
if(this_sub_sel.is('.jm_suggest_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)); self.chat('chat', current_chat, this_sub_sel.find('span.jm_chan_name').text(), hex_md5(current_chat));
} }
// Groupchat? // Groupchat?
else if(this_sub_sel.is('.jm_suggest_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; var current_password = this_sub_sel.attr('data-pwd') || null;
if(current_password) 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); 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 // Filter buddies
jQuery('#jappix_mini div.jm_roster div.jm_buddies a.jm_online').each(function() { jQuery('#jappix_mini div.jm_roster div.jm_buddies a.jm_online').each(function() {
var this_sub_sel = jQuery(this); 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)) { if(nick.match(regex)) {
this_sub_sel.show(); this_sub_sel.show();
@ -2380,7 +2380,7 @@ var JappixMini = (function () {
// Restore chat click events // Restore chat click events
jQuery('#jappix_mini div.jm_conversation').each(function() { jQuery('#jappix_mini div.jm_conversation').each(function() {
var this_sub_sel = jQuery(this); 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 // Restore init marker on all groupchats
@ -2447,7 +2447,7 @@ var JappixMini = (function () {
// Using a try/catch override IE issues // Using a try/catch override IE issues
try { try {
var this_sel = jQuery(this); 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) {} catch(e) {}
@ -2866,7 +2866,7 @@ var JappixMini = (function () {
} }
// Create the HTML markup // 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_chat-content">' +
'<div class="jm_actions">' + '<div class="jm_actions">' +
'<span class="jm_nick">' + nick + '</span>'; '<span class="jm_nick">' + nick + '</span>';
@ -2952,7 +2952,7 @@ var JappixMini = (function () {
// Join the groupchat // Join the groupchat
if(type == 'groupchat') { if(type == 'groupchat') {
// Add nickname & init values // Add nickname & init values
jQuery(current).attr('data-nick', escape(nickname)) jQuery(current).attr('data-nick', JappixCommon.escapeQuotes(nickname))
.attr('data-init', 'false'); .attr('data-init', 'false');
// Send the first groupchat presence // Send the first groupchat presence
@ -3035,7 +3035,7 @@ var JappixMini = (function () {
// Quit the groupchat? // Quit the groupchat?
if(type == 'groupchat') { if(type == 'groupchat') {
// Send an unavailable presence // 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! // Remove this groupchat!
self.removeGroupchat(xid); self.removeGroupchat(xid);
@ -3221,7 +3221,7 @@ var JappixMini = (function () {
try { try {
// Remove the groupchat private chats & the groupchat buddies from the roster // 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 // Update the presence counter
self.updateRoster(); self.updateRoster();
@ -3282,7 +3282,7 @@ var JappixMini = (function () {
if(!chat_nick) { if(!chat_nick) {
chat_nick = JappixCommon.getXIDNick(chat_xid); chat_nick = JappixCommon.getXIDNick(chat_xid);
} else { } else {
chat_nick = unescape(chat_nick); chat_nick = JappixCommon.unescapeQuotes(chat_nick);
} }
// Open the current chat // Open the current chat
@ -3325,7 +3325,7 @@ var JappixMini = (function () {
// Group: start // Group: start
if(c != MINI_ROSTER_NOGROUP) { 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>'; buddy_str += '<div class="jm_name">' + c.htmlEnc() + '</div>';
} }
@ -3392,23 +3392,23 @@ var JappixMini = (function () {
// Generate the groupchat group path // Generate the groupchat group path
if(groupchat) { 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? // Must add a groupchat group?
if(!JappixCommon.exists(path)) { if(!JappixCommon.exists(path)) {
jQuery('#jappix_mini div.jm_roster div.jm_buddies').append( 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 class="jm_name">' + JappixCommon.getXIDNick(groupchat).htmlEnc() + '</div>' +
'</div>' '</div>'
); );
} }
} else if(group) { } 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? // Must add a roster group?
if(!JappixCommon.exists(path)) { if(!JappixCommon.exists(path)) {
jQuery('#jappix_mini div.jm_roster div.jm_buddies').append( 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 class="jm_name">' + group.htmlEnc() + '</div>' +
'</div>' '</div>'
); );
@ -3465,8 +3465,8 @@ var JappixMini = (function () {
buddy_str += '<a class="jm_friend jm_offline jm_friend-' + hash; buddy_str += '<a class="jm_friend jm_offline jm_friend-' + hash;
buddy_str += '" id="friend-' + hash; buddy_str += '" id="friend-' + hash;
buddy_str += '" title="' + JappixCommon.encodeQuotes(xid) + '"'; buddy_str += '" title="' + JappixCommon.encodeQuotes(xid) + '"';
buddy_str += '" data-xid="' + escape(xid) + '"'; buddy_str += '" data-xid="' + JappixCommon.escapeQuotes(xid) + '"';
buddy_str += '" data-nick="' + escape(nick) + '"'; buddy_str += '" data-nick="' + JappixCommon.escapeQuotes(nick) + '"';
buddy_str += '" data-hash="' + hash + '"'; buddy_str += '" data-hash="' + hash + '"';
buddy_str += ' ' + (subscription ? ' data-sub="' + subscription + '" ' : ''); buddy_str += ' ' + (subscription ? ' data-sub="' + subscription + '" ' : '');
buddy_str += '>'; buddy_str += '>';
@ -3501,7 +3501,7 @@ var JappixMini = (function () {
jQuery('#jappix_mini a#friend-' + hash).remove(); jQuery('#jappix_mini a#friend-' + hash).remove();
// Empty group? // 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()) { if(groupchat && !jQuery(group + ' a.jm_friend').size()) {
jQuery(group).remove(); jQuery(group).remove();
@ -3962,8 +3962,8 @@ var JappixMini = (function () {
jQuery('#jappix_mini').append( jQuery('#jappix_mini').append(
'<div id="jm_audio">' + '<div id="jm_audio">' +
'<audio preload="auto">' + '<audio preload="auto">' +
'<source src="' + JAPPIX_STATIC + 'snd/receive-message.mp3" />' + '<source src="' + JAPPIX_STATIC + 'sounds/receive-message.mp3" />' +
'<source src="' + JAPPIX_STATIC + 'snd/receive-message.oga" />' + '<source src="' + JAPPIX_STATIC + 'sounds/receive-message.oga" />' +
'</audio>' + '</audio>' +
'</div>' '</div>'
); );
@ -4185,7 +4185,7 @@ var JappixMini = (function () {
// Append final stylesheet HTML // Append final stylesheet HTML
for(var u in css_url) { 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(/&amp;/g, '&')) + '" type="text/css" media="all" />';
} }
jQuery('head').append(css_html); jQuery('head').append(css_html);

View file

@ -47,10 +47,8 @@ var Mobile = (function () {
return false; return false;
} }
} } else {
// No "@" in the XID, we should add the default domain
// No "@" in the XID, we should add the default domain
else {
username = xid; username = xid;
domain = HOST_MAIN; domain = HOST_MAIN;
} }
@ -58,8 +56,9 @@ var Mobile = (function () {
var pwd = aForm.pwd.value; var pwd = aForm.pwd.value;
var reg = false; var reg = false;
if(aForm.reg) if(aForm.reg) {
reg = aForm.reg.checked; reg = aForm.reg.checked;
}
// Enough parameters // Enough parameters
if(username && domain && pwd) { 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 * Shows target element
* @public * @public
@ -308,8 +331,9 @@ var Mobile = (function () {
var nick = self.getNick(xid, hash); var nick = self.getNick(xid, hash);
// No nickname? // No nickname?
if(!nick) if(!nick) {
nick = xid; nick = xid;
}
// Create the chat if it does not exist // Create the chat if it does not exist
self.chat(xid, nick); self.chat(xid, nick);
@ -340,10 +364,8 @@ var Mobile = (function () {
var type = pre.getType(); var type = pre.getType();
var show = pre.getShow(); var show = pre.getShow();
// Online buddy: show it! // Online buddy
if(!type) { if(!type) {
self.showThis('buddy-' + hash);
// Display the correct presence // Display the correct presence
switch(show) { switch(show) {
case 'chat': case 'chat':
@ -366,8 +388,6 @@ var Mobile = (function () {
self.displayPresence(hash, 'available'); self.displayPresence(hash, 'available');
break; break;
} }
} else {
self.hideThis('buddy-' + hash);
} }
} catch(e) { } catch(e) {
Console.error('Mobile.handlePresence', e); Console.error('Mobile.handlePresence', e);
@ -538,7 +558,9 @@ var Mobile = (function () {
return self.sendPresence('', 'available', 1); return self.sendPresence('', 'available', 1);
// Define some pre-vars // 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'); var roster = document.getElementById('roster');
// Get roster items // Get roster items
@ -554,18 +576,30 @@ var Mobile = (function () {
hash = hex_md5(xid); hash = hex_md5(xid);
// No defined nick? // No defined nick?
if(!nick) if(!nick) {
nick = self.getDirectNick(xid); nick = self.getDirectNick(xid);
}
// Display the values
oneBuddy = document.createElement('a'); roster_buddies.push({
oneID = 'buddy-' + hash; 'xid': xid,
oneBuddy.setAttribute('href', '#'); 'hash': hash,
oneBuddy.setAttribute('id', oneID); 'nick': nick
oneBuddy.setAttribute('class', 'one-buddy'); });
oneBuddy.setAttribute('onclick', 'return Mobile.chat(\'' + self.encodeOnclick(xid) + '\', \'' + self.encodeOnclick(nick) + '\');'); }
oneBuddy.innerHTML = nick.htmlEnc();
roster.appendChild(oneBuddy); // 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 // Start handling buddies presence
@ -721,10 +755,11 @@ var Mobile = (function () {
// We split if necessary the string // We split if necessary the string
if(index !== -1) { if(index !== -1) {
if(i === 0) if(i === 0) {
toStr = toStr.substr(0, index); toStr = toStr.substr(0, index);
else } else {
toStr = toStr.substr(index + 1); toStr = toStr.substr(index + 1);
}
} }
// We return the value // We return the value
@ -831,10 +866,11 @@ var Mobile = (function () {
// Display the message // Display the message
html = '<span><b'; html = '<span><b';
if(nick == 'me') if(nick == 'me') {
html += ' class="me">' + self._e("You"); html += ' class="me">' + self._e("You");
else } else {
html += ' class="him">' + nick; html += ' class="him">' + nick;
}
html += '</b> ' + self.filter(body) + '</span>'; 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 * Goes back to roster view
* @public * @public
@ -885,8 +976,9 @@ var Mobile = (function () {
var divs = document.getElementsByTagName('div'); var divs = document.getElementsByTagName('div');
for(var i = 0; i < divs.length; i++) { 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'; divs.item(i).style.display = 'none';
}
} }
// Show the chat // Show the chat
@ -941,8 +1033,9 @@ var Mobile = (function () {
// If the chat was not yet opened // If the chat was not yet opened
if(!self.exists('chat-' + hash)) { if(!self.exists('chat-' + hash)) {
// No nick? // No nick?
if(!nick) if(!nick) {
nick = self.getNick(xid, hash); nick = self.getNick(xid, hash);
}
// Create the chat // Create the chat
self.createChat(xid, nick, hash); self.createChat(xid, nick, hash);
@ -990,6 +1083,7 @@ var Mobile = (function () {
try { try {
onbeforeunload = self.doLogout; onbeforeunload = self.doLogout;
onload = self.doInitialize;
} catch(e) { } catch(e) {
Console.error('Mobile.launch', e); Console.error('Mobile.launch', e);
} }

View file

@ -154,6 +154,7 @@ var MUCAdmin = (function () {
self.query(xid, 'owner'); self.query(xid, 'owner');
self.query(xid, 'admin'); self.query(xid, 'admin');
self.query(xid, 'outcast'); self.query(xid, 'outcast');
// We query the room to edit // We query the room to edit
DataForm.go(xid, 'muc', '', '', 'mucadmin'); DataForm.go(xid, 'muc', '', '', 'mucadmin');
} else if(aff == 'admin') { } else if(aff == 'admin') {
@ -434,8 +435,9 @@ var MUCAdmin = (function () {
Board.openThisInfo(5); Board.openThisInfo(5);
// We remove the user's favorite // 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)); Favorites.removeThis(room, Common.explodeThis('@', room, 0));
}
Console.info('MUC admin destroyed: ' + room); Console.info('MUC admin destroyed: ' + room);
} }
@ -555,10 +557,13 @@ var MUCAdmin = (function () {
try { try {
// Click events // Click events
$('#mucadmin .bottom .finish').click(function() { $('#mucadmin .bottom .finish').click(function() {
if($(this).is('.cancel')) if($(this).is('.cancel')) {
return self.close(); return self.close();
if($(this).is('.save')) }
if($(this).is('.save')) {
return self.save(); return self.save();
}
}); });
} catch(e) { } catch(e) {
Console.error('MUCAdmin.instance', e); Console.error('MUCAdmin.instance', e);

File diff suppressed because it is too large Load diff

View file

@ -63,34 +63,30 @@ var Music = (function () {
if(!Common.exists(path_type)) { if(!Common.exists(path_type)) {
var code = '<div class="' + type + '"></div>'; var code = '<div class="' + type + '"></div>';
if(type == 'local') if(type == 'local') {
$(content).prepend(code); $(content).prepend(code);
else } else {
$(content).append(code); $(content).append(code);
}
} }
// Fill the results // Fill the results
$(xml).find('track').each(function() { $(xml).find('track').each(function() {
// Parse the XML // Parse the XML
var id = $(this).find('id').text(); var this_sel = $(this);
var title = $(this).find('name').text();
var artist = $(this).find('artist').text(); var id = this_sel.find('id').text() || hex_md5(uri);
var source = $(this).find('source').text(); var title = this_sel.find('name').text();
var duration = $(this).find('duration').text(); var artist = this_sel.find('artist').text();
var uri = $(this).find('url').text(); var source = this_sel.find('source').text();
var mime = $(this).find('type').text(); var duration = this_sel.find('duration').text();
var uri = this_sel.find('url').text();
// No ID? var mime = this_sel.find('type').text() || 'audio/ogg';
if(!id)
id = hex_md5(uri);
// No MIME?
if(!mime)
mime = 'audio/ogg';
// Local URL? // Local URL?
if(type == 'local') if(type == 'local') {
uri = Utils.generateURL(uri); uri = Utils.generateURL(uri);
}
// Append the HTML code // Append the HTML code
$(path_type).append('<a href="#" class="song" data-id="' + id + '">' + title + '</a>'); $(path_type).append('<a href="#" class="song" data-id="' + id + '">' + title + '</a>');
@ -98,8 +94,9 @@ var Music = (function () {
// Current playing song? // Current playing song?
var current_song = $(path_type + ' a[data-id="' + id + '"]'); 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'); current_song.addClass('playing');
}
// Click event // Click event
current_song.click(function() { current_song.click(function() {
@ -117,12 +114,14 @@ var Music = (function () {
$(path + 'input').val('').removeAttr('disabled'); $(path + 'input').val('').removeAttr('disabled');
// No result // No result
if(!jamendo && !local) if(!jamendo && !local) {
$(path + '.no-results').show(); $(path + '.no-results').show();
}
// We must put a separator between the categories // We must put a separator between the categories
if(jamendo && local) if(jamendo && local) {
$(content + ' .local').addClass('special'); $(content + ' .local').addClass('special');
}
} }
} catch(e) { } catch(e) {
Console.error('Music.parse', e); Console.error('Music.parse', e);
@ -157,7 +156,10 @@ var Music = (function () {
}); });
// Get the local results // 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'); self.parse(data, 'local');
}); });
} catch(e) { } catch(e) {
@ -177,33 +179,35 @@ var Music = (function () {
try { try {
// Initialize // Initialize
var playThis = document.getElementById('top-content').getElementsByTagName('audio')[0]; var audio_sel = document.getElementById('top-content').getElementsByTagName('audio')[0];
// Nothing to play, exit // Nothing to play, exit
if(!playThis) if(!audio_sel) {
return false; return false;
}
var stopButton = $('#top-content a.stop'); var stopButton = $('#top-content a.stop');
// User play a song // User play a song
if(action == 'play') { if(action == 'play') {
stopButton.show(); stopButton.show();
playThis.load(); audio_sel.load();
playThis.play(); audio_sel.play();
playThis.addEventListener('ended', function() {
audio_sel.addEventListener('ended', function() {
self.action('stop'); self.action('stop');
}, true); }, true);
Console.log('Music is now playing.'); Console.log('Music is now playing.');
} } else if(action == 'stop') {
// User stop the song / end of song
// User stop the song or the song came to its end
else if(action == 'stop') {
stopButton.hide(); stopButton.hide();
playThis.pause(); audio_sel.pause();
$('#top-content .music').removeClass('actived'); $('#top-content .music').removeClass('actived');
$('.music-content .list a').removeClass('playing'); $('.music-content .list a').removeClass('playing');
$('.music-audio').remove(); $('.music-audio').remove();
self.publish(); self.publish();
Console.log('Music is now stopped.'); Console.log('Music is now stopped.');
@ -245,27 +249,24 @@ var Music = (function () {
// Enough data? // Enough data?
if(title || artist || source || uri) { if(title || artist || source || uri) {
// Data array var music_data = {
var nodes = new Array( 'title': title,
'title', 'artist': artist,
'artist', 'source': source,
'source', 'length': length,
'length', 'uri': uri
'uri' };
);
var values = new Array(
title,
artist,
source,
length,
uri
);
// Create the children nodes // Create the children nodes
for(var i in nodes) { var cur_value;
if(values[i]) {
tune.appendChild(iq.buildNode(nodes[i], {'xmlns': NS_TUNE}, values[i])); 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 { try {
var path = '.music-content '; var path = '.music-content ';
var music_audio_sel = $('.music-audio');
// We remove & create a new audio tag // 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 + '" />'); $(path + '.player').prepend('<audio class="music-audio" type="' + mime + '" data-id="' + id + '" />');
// We apply the new source to the player // We apply the new source to the player
if(type == 'jamendo') if(type == 'jamendo') {
$('.music-audio').attr('src', 'http://api.jamendo.com/get2/stream/track/redirect/?id=' + id + '&streamencoding=ogg2'); music_audio_sel.attr('src', 'http://api.jamendo.com/get2/stream/track/redirect/?id=' + id + '&streamencoding=ogg2');
else } else {
$('.music-audio').attr('src', uri); music_audio_sel.attr('src', uri);
}
// We play the target sound // We play the target sound
self.action('play'); self.action('play');

View file

@ -53,8 +53,9 @@ var Name = (function () {
try { try {
// Was it an obsolete request? // 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; return false;
}
// Reset the waiting item // Reset the waiting item
$('.add-contact-name-get').hide().removeAttr('data-for'); $('.add-contact-name-get').hide().removeAttr('data-for');
@ -63,8 +64,9 @@ var Name = (function () {
if(iq.getType() == 'result') { if(iq.getType() == 'result') {
var full_name = self.generateBuddy(iq)[0]; var full_name = self.generateBuddy(iq)[0];
if(full_name) if(full_name) {
$('.add-contact-name').val(full_name); $('.add-contact-name').val(full_name);
}
} }
} catch(e) { } catch(e) {
Console.error('Name.handleAddUser', e); Console.error('Name.handleAddUser', e);
@ -85,16 +87,16 @@ var Name = (function () {
try { try {
// Get the IQ content // Get the IQ content
var xml = $(iq.getNode()).find('vCard'); var vcard_sel = $(iq.getNode()).find('vCard');
// Get the full name & the nickname // Get the full name & the nickname
var pFull = xml.find('FN:first').text(); var pFull = vcard_sel.find('FN:first').text();
var pNick = xml.find('NICKNAME:first').text(); var pNick = vcard_sel.find('NICKNAME:first').text();
// No full name? // No full name?
if(!pFull) { if(!pFull) {
// Get the given name // Get the given name
var pN = xml.find('N:first'); var pN = vcard_sel.find('N:first');
var pGiven = pN.find('GIVEN:first').text(); var pGiven = pN.find('GIVEN:first').text();
if(pGiven) { if(pGiven) {
@ -103,8 +105,9 @@ var Name = (function () {
// Get the family name (optional) // Get the family name (optional)
var pFamily = pN.find('FAMILY:first').text(); var pFamily = pN.find('FAMILY:first').text();
if(pFamily) if(pFamily) {
pFull += ' ' + pFamily; pFull += ' ' + pFamily;
}
} }
} }
@ -132,22 +135,22 @@ var Name = (function () {
xid = Common.bareXID(xid); xid = Common.bareXID(xid);
// This is me? // This is me?
if(Utils.isAnonymous() && !xid) if(Utils.isAnonymous() && !xid) {
bname = Common._e("You"); bname = Common._e("You");
else if(xid == Common.getXID()) } else if(xid == Common.getXID()) {
bname = self.get(); bname = self.get();
}
// Not me! // Not me!
else { else {
cname = $('#roster .buddy[data-xid="' + escape(xid) + '"]:first .buddy-name').html(); cname = $('#roster .buddy[data-xid="' + escape(xid) + '"]:first .buddy-name').html();
// If the complete name exists // Complete name exists?
if(cname) if(cname) {
bname = cname.revertHtmlEnc(); bname = cname.revertHtmlEnc();
} else {
// Else, we just get the nickname of the buddy
else
bname = Common.getXIDNick(xid); bname = Common.getXIDNick(xid);
}
} }
return bname; return bname;
@ -170,8 +173,9 @@ var Name = (function () {
var nick = DataStore.getDB(Connection.desktop_hash, 'profile', 'nick'); var nick = DataStore.getDB(Connection.desktop_hash, 'profile', 'nick');
// No nick? // No nick?
if(!nick) if(!nick) {
nick = con.username; nick = con.username;
}
return nick; return nick;
} catch(e) { } catch(e) {
@ -192,9 +196,10 @@ var Name = (function () {
// Try to read the user name // Try to read the user name
var name = DataStore.getDB(Connection.desktop_hash, 'profile', 'name'); var name = DataStore.getDB(Connection.desktop_hash, 'profile', 'name');
// No name? Use the nickname instead! // No name? Use the nickname instead
if(!name) if(!name) {
name = self.getNick(); name = self.getNick();
}
return name; return name;
} catch(e) { } catch(e) {

View file

@ -62,10 +62,7 @@ var Notification = (function () {
$(notif).prepend('<div class="notify one-counter" data-counter="' + number + '">' + number + '</div>'); $(notif).prepend('<div class="notify one-counter" data-counter="' + number + '">' + number + '</div>');
$(nothing).hide(); $(nothing).hide();
$(empty).show(); $(empty).show();
} } else {
// No notification!
else {
$(empty).hide(); $(empty).hide();
$(nothing).show(); $(nothing).show();
@ -96,8 +93,9 @@ var Notification = (function () {
self.create = function(type, from, data, body, id, inverse) { self.create = function(type, from, data, body, id, inverse) {
try { try {
if(!type || !from) if(!type || !from) {
return; return;
}
// Generate an ID hash // Generate an ID hash
if(!id) { if(!id) {
@ -229,8 +227,9 @@ var Notification = (function () {
} }
// No text? // No text?
if(!text) if(!text) {
return; return;
}
// Action links? // Action links?
switch(type) { switch(type) {
@ -248,8 +247,9 @@ var Notification = (function () {
action = '<a href="#" class="no">' + Common._e("Hide") + '</a>'; action = '<a href="#" class="no">' + Common._e("Hide") + '</a>';
// Any parent link? // Any parent link?
if((type == 'comment') && data[2]) if((type == 'comment') && data[2]) {
action = '<a href="#" class="yes">' + Common._e("Show") + '</a>' + action; action = '<a href="#" class="yes">' + Common._e("Show") + '</a>' + action;
}
break; break;
@ -284,10 +284,11 @@ var Notification = (function () {
'</div>'; '</div>';
// Add the HTML code // Add the HTML code
if(inverse) if(inverse) {
$('.notifications-content .nothing').before(code); $('.notifications-content .nothing').before(code);
else } else {
$('.notifications-content .empty').after(code); $('.notifications-content .empty').after(code);
}
// Play a sound to alert the user // Play a sound to alert the user
Audio.play('notification'); Audio.play('notification');
@ -296,8 +297,9 @@ var Notification = (function () {
$('.' + id + ' a.yes').click(function() { $('.' + id + ' a.yes').click(function() {
self.action(type, data, 'yes', id); self.action(type, data, 'yes', id);
if(($(this).attr('href') == '#') && ($(this).attr('target') != '_blank')) if(($(this).attr('href') == '#') && ($(this).attr('target') != '_blank')) {
return false; return false;
}
}); });
// The no click function // The no click function
@ -334,28 +336,23 @@ var Notification = (function () {
try { try {
// We launch a function depending of the type // We launch a function depending of the type
if((type == 'subscribe') && (value == 'yes')) if((type == 'subscribe') && (value == 'yes')) {
Presence.acceptSubscribe(data[0], data[1]); Presence.acceptSubscribe(data[0], data[1]);
} else if((type == 'subscribe') && (value == 'no')) {
else if((type == 'subscribe') && (value == 'no'))
Presence.sendSubscribe(data[0], 'unsubscribed'); Presence.sendSubscribe(data[0], 'unsubscribed');
} else if((type == 'invite_room') && (value == 'yes')) {
else if((type == 'invite_room') && (value == 'yes'))
Chat.checkCreate(data[0], 'groupchat'); Chat.checkCreate(data[0], 'groupchat');
} else if(type == 'request') {
else if(type == 'request')
HTTPReply.go(value, data[0]); 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]); 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]); 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]); 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') { if(value == 'yes') {
// Get the microblog item // Get the microblog item
Microblog.fromInfos(data[2]); Microblog.fromInfos(data[2]);
@ -452,25 +449,29 @@ var Notification = (function () {
// Should we inverse? // Should we inverse?
var inverse = true; var inverse = true;
if(items.size() == 1) if(items.size() == 1) {
inverse = false; inverse = false;
}
// Parse notifications // Parse notifications
items.each(function() { items.each(function() {
var this_sel = $(this);
// Parse the current item // Parse the current item
var current_item = $(this).attr('id'); var current_item = this_sel.attr('id');
var current_type = $(this).find('link[rel="via"]:first').attr('title'); var current_type = this_sel.find('link[rel="via"]:first').attr('title');
var current_href = $(this).find('link[rel="via"]:first').attr('href'); var current_href = this_sel.find('link[rel="via"]:first').attr('href');
var current_parent_href = $(this).find('link[rel="related"]:first').attr('href'); var current_parent_href = this_sel.find('link[rel="related"]:first').attr('href');
var current_xid = Common.explodeThis(':', $(this).find('author uri').text(), 1); var current_xid = Common.explodeThis(':', this_sel.find('author uri').text(), 1);
var current_name = $(this).find('author name').text(); var current_name = this_sel.find('author name').text();
var current_text = $(this).find('content[type="text"]:first').text(); var current_text = this_sel.find('content[type="text"]:first').text();
var current_bname = Name.getBuddy(current_xid); var current_bname = Name.getBuddy(current_xid);
var current_id = hex_md5(current_type + current_xid + current_href + current_text); var current_id = hex_md5(current_type + current_xid + current_href + current_text);
// Choose the good name! // 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; current_name = current_bname;
}
// Create it! // Create it!
self.create(current_type, current_xid, [current_name, current_href, current_parent_href, current_item], current_text, current_id, inverse); self.create(current_type, current_xid, [current_name, current_href, current_parent_href, current_item], current_text, current_id, inverse);

View file

@ -39,8 +39,9 @@ var OOB = (function () {
to = Caps.getFeatureResource(to, NS_IQOOB); to = Caps.getFeatureResource(to, NS_IQOOB);
// IQs cannot be sent to offline users // IQs cannot be sent to offline users
if(!to) if(!to) {
return; return;
}
// Register the ID // Register the ID
DataStore.setDB(Connection.desktop_hash, 'send/url', id, url); DataStore.setDB(Connection.desktop_hash, 'send/url', id, url);
@ -92,19 +93,15 @@ var OOB = (function () {
self.handle = function(from, id, type, node) { self.handle = function(from, id, type, node) {
try { try {
var xid = ''; var xid = '', url = '', desc = '';
var url = '';
var desc = '';
// IQ stanza?
if(type == 'iq') { if(type == 'iq') {
// IQ stanza
xid = Common.fullXID(from); xid = Common.fullXID(from);
url = $(node).find('url').text(); url = $(node).find('url').text();
desc = $(node).find('desc').text(); desc = $(node).find('desc').text();
} } else {
// Message stanza
// Message stanza?
else {
xid = Common.bareXID(from); xid = Common.bareXID(from);
url = $(node).find('url').text(); url = $(node).find('url').text();
desc = $(node).find('body').text(); desc = $(node).find('body').text();
@ -140,8 +137,9 @@ var OOB = (function () {
try { try {
// Not IQ type? // Not IQ type?
if(type != 'iq') if(type != 'iq') {
return; return;
}
// New IQ // New IQ
var aIQ = new JSJaCIQ(); var aIQ = new JSJaCIQ();
@ -160,11 +158,17 @@ var OOB = (function () {
aIQ.setType('error'); aIQ.setType('error');
// Append stanza content // 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)); aIQ.getNode().appendChild(node.childNodes.item(i).cloneNode(true));
}
// Append error content // 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})); aError.appendChild(aIQ.buildNode('not-acceptable', {'xmlns': NS_STANZAS}));
Console.info('Rejected file request from: ' + to); Console.info('Rejected file request from: ' + to);
@ -187,11 +191,16 @@ var OOB = (function () {
try { try {
// Append the wait icon // Append the wait icon
$('#page-engine .chat-tools-file:not(.mini) .tooltip-subitem *').hide(); var chat_tools_file_sel = page_engine_sel.find('.chat-tools-file:not(.mini)');
$('#page-engine .chat-tools-file:not(.mini) .tooltip-subitem').append('<div class="wait wait-medium"></div>'); 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 // Lock the bubble
$('#page-engine .chat-tools-file:not(.mini)').addClass('mini'); chat_tools_file_sel.addClass('mini');
} catch(e) { } catch(e) {
Console.error('OOB.waitUpload', e); Console.error('OOB.waitUpload', e);
} }
@ -208,6 +217,8 @@ var OOB = (function () {
self.handleUpload = function(responseXML) { self.handleUpload = function(responseXML) {
try { try {
var page_engine_sel = $('#page-engine');
// Data selector // Data selector
var dData = $(responseXML).find('jappix'); var dData = $(responseXML).find('jappix');
@ -220,25 +231,27 @@ var OOB = (function () {
var oob_has; var oob_has;
// No ID provided? // No ID provided?
if(!fID) if(!fID) {
oob_has = ':has(.wait)'; oob_has = ':has(.wait)';
else } else {
oob_has = ':has(#oob-upload input[value="' + fID + '"])'; oob_has = ':has(#oob-upload input[value="' + fID + '"])';
}
var xid = $('#page-engine .page-engine-chan' + oob_has).attr('data-xid'); var xid = page_engine_sel.find('.page-engine-chan' + oob_has).attr('data-xid');
var oob_type = $('#page-engine .chat-tools-file' + oob_has).attr('data-oob'); var oob_type = page_engine_sel.find('.chat-tools-file' + oob_has).attr('data-oob');
// Reset the file send tool // Reset the file send tool
$('#page-engine .chat-tools-file' + oob_has).removeClass('mini'); page_engine_sel.find('.chat-tools-file' + oob_has).removeClass('mini');
$('#page-engine .bubble-file' + oob_has).remove(); page_engine_sel.find('.bubble-file' + oob_has).remove();
// Not available? // 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); Board.openThisError(4);
// Remove the file we sent // Remove the file we sent
if(fURL) if(fURL) {
$.get(fURL + '&action=remove'); $.get(fURL + '&action=remove');
}
} }
// Everything okay? // Everything okay?
@ -250,10 +263,7 @@ var OOB = (function () {
Notification.create('send_pending', xid, [xid, fURL, oob_type, '', ''], fDesc, hex_md5(fURL + fDesc + fID)); Notification.create('send_pending', xid, [xid, fURL, oob_type, '', ''], fDesc, hex_md5(fURL + fDesc + fID));
Console.info('File request sent.'); Console.info('File request sent.');
} } else {
// Upload error?
else {
Board.openThisError(4); Board.openThisError(4);
Console.error('Error while sending the file', dData.find('error').text()); Console.error('Error while sending the file', dData.find('error').text());

View file

@ -275,11 +275,13 @@ var Options = (function () {
self.switchTab = function(id) { self.switchTab = function(id) {
try { try {
$('#options .one-lap').hide(); var options_sel = $('#options');
$('#options #conf' + id).show();
$('#options .tab a').removeClass('tab-active'); options_sel.find('.one-lap').hide();
$('#options .tab a[data-key="' + id + '"]').addClass('tab-active'); options_sel.find('#conf' + id).show();
$('#options .sub-ask .sub-ask-close').click(); 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) { } catch(e) {
Console.error('Options.switchTab', e); Console.error('Options.switchTab', e);
} finally { } finally {
@ -298,15 +300,16 @@ var Options = (function () {
self.wait = function(id) { self.wait = function(id) {
try { try {
var sOptions = $('#options .content'); var options_sel = $('#options');
var content_sel = options_sel.find('.content');
// Remove the current item class // Remove the current item class
sOptions.removeClass(id); content_sel.removeClass(id);
// Hide the waiting items if all was received // Hide the waiting items if all was received
if(!sOptions.hasClass('microblog') && !sOptions.hasClass('mam')) { if(!content_sel.hasClass('microblog') && !content_sel.hasClass('mam')) {
$('#options .wait').hide(); options_sel.find('.wait').hide();
$('#options .finish:first').removeClass('disabled'); options_sel.find('.finish:first').removeClass('disabled');
} }
} catch(e) { } catch(e) {
Console.error('Options.wait', e); Console.error('Options.wait', e);
@ -533,22 +536,26 @@ var Options = (function () {
$('.sub-ask-pass input').each(function() { $('.sub-ask-pass input').each(function() {
var select = $(this); var select = $(this);
if(!select.val()) if(!select.val()) {
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
select.addClass('please-complete').focus(); select.addClass('please-complete').focus();
}); });
else } else {
select.removeClass('please-complete'); select.removeClass('please-complete');
}
}); });
if(password0 != Utils.getPassword()) if(password0 != Utils.getPassword()) {
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
$('#options .old').addClass('please-complete').focus(); $('#options .old').addClass('please-complete').focus();
}); });
if(password1 != password2) }
if(password1 != password2) {
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
$('#options .new1, #options .new2').addClass('please-complete').focus(); $('#options .new1, #options .new2').addClass('please-complete').focus();
}); });
}
} }
} catch(e) { } catch(e) {
Console.error('Options.sendNewPassword', e); Console.error('Options.sendNewPassword', e);
@ -612,12 +619,13 @@ var Options = (function () {
} else { } else {
var selector = $('#options .check-mam'); var selector = $('#options .check-mam');
if(password != Utils.getPassword()) if(password != Utils.getPassword()) {
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
selector.addClass('please-complete').focus(); selector.addClass('please-complete').focus();
}); });
else } else {
selector.removeClass('please-complete'); selector.removeClass('please-complete');
}
} }
} catch(e) { } catch(e) {
Console.error('Options.purgeMyArchives', e); Console.error('Options.purgeMyArchives', e);
@ -659,12 +667,13 @@ var Options = (function () {
} else { } else {
var selector = $('#options .check-empty'); var selector = $('#options .check-empty');
if(password != Utils.getPassword()) if(password != Utils.getPassword()) {
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
selector.addClass('please-complete').focus(); selector.addClass('please-complete').focus();
}); });
else } else {
selector.removeClass('please-complete'); selector.removeClass('please-complete');
}
} }
} catch(e) { } catch(e) {
Console.error('Options.purgeMyMicroblog', e); Console.error('Options.purgeMyMicroblog', e);
@ -726,17 +735,16 @@ var Options = (function () {
con.send(iq, self.handleAccDeletion); con.send(iq, self.handleAccDeletion);
Console.info('Delete account sent.'); Console.info('Delete account sent.');
} } else {
else {
var selector = $('#options .check-password'); var selector = $('#options .check-password');
if(password != Utils.getPassword()) if(password != Utils.getPassword()) {
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
selector.addClass('please-complete').focus(); selector.addClass('please-complete').focus();
}); });
else } else {
selector.removeClass('please-complete'); selector.removeClass('please-complete');
}
} }
} catch(e) { } catch(e) {
Console.error('Options.deleteMyAccount', e); Console.error('Options.deleteMyAccount', e);
@ -781,50 +789,58 @@ var Options = (function () {
} }
// We show the "privacy" form if something is visible into it // 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(); $('#options fieldset.privacy').show();
}
// We get the values of the forms for the sounds // 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); $('#sounds').attr('checked', false);
else } else {
$('#sounds').attr('checked', true); $('#sounds').attr('checked', true);
}
// We get the values of the forms for the geolocation // 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); $('#geolocation').attr('checked', true);
else } else {
$('#geolocation').attr('checked', false); $('#geolocation').attr('checked', false);
}
// We get the values of the forms for the roster show all // 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); $('#showall').attr('checked', true);
else } else {
$('#showall').attr('checked', false); $('#showall').attr('checked', false);
}
// We get the values of the forms for the XHTML-IM images filter // 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); $('#noxhtmlimg').attr('checked', true);
else } else {
$('#noxhtmlimg').attr('checked', false); $('#noxhtmlimg').attr('checked', false);
}
// We get the values of the forms for the integratemedias // 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); $('#integratemedias').attr('checked', false);
else } else {
$('#integratemedias').attr('checked', true); $('#integratemedias').attr('checked', true);
}
// We get the values of the forms for the groupchatpresence // 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); $('#groupchatpresence').attr('checked', false);
else } else {
$('#groupchatpresence').attr('checked', true); $('#groupchatpresence').attr('checked', true);
}
// We get the values of the forms for the localarchives // 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); $('#localarchives').attr('checked', false);
else } else {
$('#localarchives').attr('checked', true); $('#localarchives').attr('checked', true);
}
} catch(e) { } catch(e) {
Console.error('Options.load', e); Console.error('Options.load', e);
} }
@ -939,10 +955,13 @@ var Options = (function () {
}); });
$('#options .bottom .finish').click(function() { $('#options .bottom .finish').click(function() {
if($(this).is('.save') && !$(this).hasClass('disabled')) if($(this).is('.save') && !$(this).hasClass('disabled')) {
return self.save(); return self.save();
if($(this).is('.cancel')) }
if($(this).is('.cancel')) {
return self.close(); return self.close();
}
return false; return false;
}); });
@ -951,20 +970,24 @@ var Options = (function () {
$('#options .sub-ask input').keyup(function(e) { $('#options .sub-ask input').keyup(function(e) {
if(e.keyCode == 13) { if(e.keyCode == 13) {
// Archives purge // Archives purge
if($(this).is('.purge-archives')) if($(this).is('.purge-archives')) {
return self.purgeMyArchives(); return self.purgeMyArchives();
}
// Microblog purge // Microblog purge
else if($(this).is('.purge-microblog')) else if($(this).is('.purge-microblog')) {
return self.purgeMyMicroblog(); return self.purgeMyMicroblog();
}
// Password change // Password change
else if($(this).is('.password-change')) else if($(this).is('.password-change')) {
return self.sendNewPassword(); return self.sendNewPassword();
}
// Account deletion // Account deletion
else if($(this).is('.delete-account')) else if($(this).is('.delete-account')) {
return self.deleteMyAccount(); return self.deleteMyAccount();
}
} }
}); });

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -215,16 +215,18 @@ var Privacy = (function () {
// Any block list? // Any block list?
if($(iqQuery).find('list[name="block"]').size()) { if($(iqQuery).find('list[name="block"]').size()) {
// Not the default one? // Not the default one?
if(!$(iqQuery).find('default[name="block"]').size()) if(!$(iqQuery).find('default[name="block"]').size()) {
self.change('block', 'default'); self.change('block', 'default');
else } else {
DataStore.setDB(Connection.desktop_hash, 'privacy-marker', 'default', 'block'); DataStore.setDB(Connection.desktop_hash, 'privacy-marker', 'default', 'block');
}
// Not the active one? // Not the active one?
if(!$(iqQuery).find('active[name="block"]').size()) if(!$(iqQuery).find('active[name="block"]').size()) {
self.change('block', 'active'); self.change('block', 'active');
else } else {
DataStore.setDB(Connection.desktop_hash, 'privacy-marker', 'active', 'block'); DataStore.setDB(Connection.desktop_hash, 'privacy-marker', 'active', 'block');
}
// Get the block list rules // Get the block list rules
self.get('block'); self.get('block');
@ -381,10 +383,11 @@ var Privacy = (function () {
} }
con.send(iq, function(iq) { con.send(iq, function(iq) {
if(iq.getType() == 'result') if(iq.getType() == 'result') {
Console.log('Sent privacy list.'); Console.log('Sent privacy list.');
else } else {
Console.error('Error sending privacy list.'); Console.error('Error sending privacy list.');
}
}); });
Console.log('Sending privacy list: ' + list); Console.log('Sending privacy list: ' + list);
@ -455,8 +458,9 @@ var Privacy = (function () {
if(!c_order) if(!c_order)
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); highest_order = parseInt(c_order);
}
type.push(c_type); type.push(c_type);
value.push(c_value); value.push(c_value);
@ -464,25 +468,29 @@ var Privacy = (function () {
order.push(c_order); order.push(c_order);
// Child elements // Child elements
if($(this).find('presence-in').size()) if($(this).find('presence-in').size()) {
presence_in.push(true); presence_in.push(true);
else } else {
presence_in.push(false); presence_in.push(false);
}
if($(this).find('presence-out').size()) if($(this).find('presence-out').size()) {
presence_out.push(true); presence_out.push(true);
else } else {
presence_out.push(false); presence_out.push(false);
}
if($(this).find('message').size()) if($(this).find('message').size()) {
msg.push(true); msg.push(true);
else } else {
msg.push(false); msg.push(false);
}
if($(this).find('iq').size()) if($(this).find('iq').size()) {
iq_p.push(true); iq_p.push(true);
else } else {
iq_p.push(false); iq_p.push(false);
}
} }
}); });
@ -508,8 +516,9 @@ var Privacy = (function () {
try { try {
// Yet sent? // Yet sent?
if(DataStore.getDB(Connection.desktop_hash, 'privacy-marker', status) == list) if(DataStore.getDB(Connection.desktop_hash, 'privacy-marker', status) == list) {
return; return;
}
// Write a marker // Write a marker
DataStore.setDB(Connection.desktop_hash, 'privacy-marker', status, list); 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})); var iqStatus = iqQuery.appendChild(iq.buildNode(status, {'xmlns': NS_PRIVACY}));
// Can add a "name" attribute? // Can add a "name" attribute?
if(list) if(list) {
iqStatus.setAttribute('name', list); iqStatus.setAttribute('name', list);
}
con.send(iq); con.send(iq);
@ -596,18 +606,20 @@ var Privacy = (function () {
$(data).find('list').each(function() { $(data).find('list').each(function() {
var list_name = $(this).attr('name'); var list_name = $(this).attr('name');
if(list_name) if(list_name) {
code += '<option value="' + Common.encodeQuotes(list_name) + '">' + list_name.htmlEnc() + '</option>'; code += '<option value="' + Common.encodeQuotes(list_name) + '">' + list_name.htmlEnc() + '</option>';
}
}); });
// Apply HTML code // Apply HTML code
select.html(code); select.html(code);
// Not empty? // Not empty?
if(code) if(code) {
select.removeAttr('disabled'); select.removeAttr('disabled');
else } else {
select.attr('disabled', true); select.attr('disabled', true);
}
} catch(e) { } catch(e) {
Console.error('Privacy.displayLists', e); Console.error('Privacy.displayLists', e);
} finally { } finally {
@ -638,8 +650,9 @@ var Privacy = (function () {
select.html(''); select.html('');
// No list? // No list?
if(!list) if(!list) {
return false; return false;
}
// Reset the list status // Reset the list status
$('#privacy .privacy-active input[type="checkbox"]').removeAttr('checked'); $('#privacy .privacy-active input[type="checkbox"]').removeAttr('checked');
@ -648,8 +661,9 @@ var Privacy = (function () {
var status = ['active', 'default']; var status = ['active', 'default'];
for(var s in status) { 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); $('#privacy .privacy-active input[name=' + status[s] + ']').attr('checked', true);
}
} }
// Try to read the stored items // Try to read the stored items
@ -660,10 +674,9 @@ var Privacy = (function () {
select.attr('disabled', true); select.attr('disabled', true);
return self.get(list); return self.get(list);
} } else {
else
select.removeAttr('disabled'); select.removeAttr('disabled');
}
// Parse the XML data! // Parse the XML data!
$(items).find('item').each(function() { $(items).find('item').each(function() {
@ -814,8 +827,9 @@ var Privacy = (function () {
$(type_check).attr('checked', true); $(type_check).attr('checked', true);
// Can apply a value? // Can apply a value?
if(value_input) if(value_input) {
$(value_input).val(value); $(value_input).val(value);
}
// Apply the things to do // Apply the things to do
var privacy_do = '#privacy .privacy-third input[type="checkbox"]'; 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(); var list = $('#privacy .privacy-head .list-left select').val();
// No value? // No value?
if(!list) if(!list) {
return false; return false;
}
// Remove it from popup // Remove it from popup
$('#privacy .privacy-head .list-left select option[value="' + list + '"]').remove(); $('#privacy .privacy-head .list-left select option[value="' + list + '"]').remove();
@ -941,8 +956,9 @@ var Privacy = (function () {
var status = ['active', 'default']; var status = ['active', 'default'];
for(var s in status) { 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]); self.change('', status[s]);
}
} }
// Remove from server // Remove from server
@ -957,8 +973,9 @@ var Privacy = (function () {
$('#privacy .privacy-head .list-right input').keyup(function(e) { $('#privacy .privacy-head .list-right input').keyup(function(e) {
// Not enter? // Not enter?
if(e.keyCode != 13) if(e.keyCode != 13) {
return; return;
}
// Get list name // Get list name
var list = $('#privacy .privacy-head .list-right input').val(); var list = $('#privacy .privacy-head .list-right input').val();
@ -1002,21 +1019,22 @@ var Privacy = (function () {
// Display the data! // Display the data!
self.displayForm( self.displayForm(
item.attr('data-type'), item.attr('data-type'),
item.attr('data-value'), item.attr('data-value'),
item.attr('data-action'), item.attr('data-action'),
item.attr('data-order'), item.attr('data-order'),
item.attr('data-presence_in'), item.attr('data-presence_in'),
item.attr('data-presence_out'), item.attr('data-presence_out'),
item.attr('data-message'), item.attr('data-message'),
item.attr('data-iq') item.attr('data-iq')
); );
}); });
$('#privacy .privacy-item a.item-add').click(function() { $('#privacy .privacy-item a.item-add').click(function() {
// Cannot add anything? // 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; return false;
}
// Disable item select // Disable item select
$('#privacy .privacy-item select').attr('disabled', true); $('#privacy .privacy-item select').attr('disabled', true);
@ -1034,8 +1052,9 @@ var Privacy = (function () {
$('#privacy .privacy-item a.item-remove').click(function() { $('#privacy .privacy-item a.item-remove').click(function() {
// Cannot add anything? // 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; return false;
}
// Get values // Get values
var list = $('#privacy .privacy-head .list-left select').val(); 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(); $('#privacy .privacy-head .list-left select option[value="' + list + '"]').remove();
// No more privacy lists? // 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); $('#privacy .privacy-head .list-left select').attr('disabled', true);
}
// Disable this list before removing it // Disable this list before removing it
var status = ['active', 'default']; var status = ['active', 'default'];
for(var s in status) { 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]); self.change('', status[s]);
}
} }
} }
@ -1079,14 +1100,16 @@ var Privacy = (function () {
$('#privacy .privacy-item a.item-save').click(function() { $('#privacy .privacy-item a.item-save').click(function() {
// Canot push item? // Canot push item?
if(Common.exists('#privacy .privacy-form input:disabled')) if(Common.exists('#privacy .privacy-form input:disabled')) {
return false; return false;
}
// Get the hash // Get the hash
var item_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'); item_hash = $('#privacy .privacy-item select option:selected').attr('data-hash');
}
// Read the form // Read the form
var privacy_second = '#privacy .privacy-second'; var privacy_second = '#privacy .privacy-second';
@ -1142,17 +1165,17 @@ var Privacy = (function () {
// Push item to the server! // Push item to the server!
self.push( self.push(
item_list, item_list,
[item_type], [item_type],
[item_value], [item_value],
[item_action], [item_action],
[item_order], [item_order],
[item_prin], [item_prin],
[item_prout], [item_prout],
[item_msg], [item_msg],
[item_iq], [item_iq],
item_hash item_hash
); );
return false; return false;
}); });
@ -1170,16 +1193,19 @@ var Privacy = (function () {
var target = '#privacy .privacy-third input[type="checkbox"]'; var target = '#privacy .privacy-third input[type="checkbox"]';
// Must tick "everything" checkbox? // Must tick "everything" checkbox?
if(!$(target).filter(':checked').size()) if(!$(target).filter(':checked').size()) {
$(target + '[name="everything"]').attr('checked', true); $(target + '[name="everything"]').attr('checked', true);
}
// Must untick the other checkboxes? // Must untick the other checkboxes?
else if($(this).is('[name="everything"]')) else if($(this).is('[name="everything"]')) {
$(target + ':not([name="everything"])').removeAttr('checked'); $(target + ':not([name="everything"])').removeAttr('checked');
}
// Must untick "everything" checkbox? // Must untick "everything" checkbox?
else else {
$(target + '[name="everything"]').removeAttr('checked'); $(target + '[name="everything"]').removeAttr('checked');
}
}); });
$('#privacy .privacy-active input[name="order"]').keyup(function() { $('#privacy .privacy-active input[name="order"]').keyup(function() {
@ -1187,14 +1213,16 @@ var Privacy = (function () {
var value = $(this).val(); var value = $(this).val();
// No value? // No value?
if(!value) if(!value) {
return; return;
}
// Not a number? // Not a number?
if(isNaN(value)) if(isNaN(value)) {
value = 1; value = 1;
else } else {
value = parseInt(value); value = parseInt(value);
}
// Negative? // Negative?
if(value < 0) if(value < 0)
@ -1206,8 +1234,9 @@ var Privacy = (function () {
.blur(function() { .blur(function() {
// No value? // No value?
if(!$(this).val()) if(!$(this).val()) {
$(this).val('1'); $(this).val('1');
}
}); });
$('#privacy .privacy-active .privacy-active-elements input').change(function() { $('#privacy .privacy-active .privacy-active-elements input').change(function() {
@ -1216,14 +1245,16 @@ var Privacy = (function () {
var state_name = $(this).attr('name'); var state_name = $(this).attr('name');
// Cannot continue? // Cannot continue?
if(!list_name || !state_name) if(!list_name || !state_name) {
return; return;
}
// Change the current list status // Change the current list status
if($(this).filter(':checked').size()) if($(this).filter(':checked').size()) {
self.change(list_name, state_name); self.change(list_name, state_name);
else } else {
self.change('', state_name); self.change('', state_name);
}
}); });
} catch(e) { } catch(e) {
Console.error('Privacy.instance', e); Console.error('Privacy.instance', e);

View file

@ -108,8 +108,9 @@ var Receipts = (function () {
aMsg.setID(id); aMsg.setID(id);
// Any type? // Any type?
if(type) if(type) {
aMsg.setType(type); aMsg.setType(type);
}
// Append the received node // Append the received node
aMsg.appendNode('received', {'xmlns': NS_URN_RECEIPTS, 'id': id}); aMsg.appendNode('received', {'xmlns': NS_URN_RECEIPTS, 'id': id});
@ -147,7 +148,7 @@ var Receipts = (function () {
// Remove the group marker // Remove the group marker
if(!group.find('.one-line[data-lost]').size()) { if(!group.find('.one-line[data-lost]').size()) {
group.find('b.name').removeClass('talk-images') group.find('b.name').removeClass('talk-images')
.removeAttr('title'); .removeAttr('title');
} }
} catch(e) { } catch(e) {
Console.error('Receipts.messageReceived', e); Console.error('Receipts.messageReceived', e);
@ -170,14 +171,19 @@ var Receipts = (function () {
try { try {
// Fire a check 10 seconds later // Fire a check 10 seconds later
$('#' + hash + ' .one-line[data-id="' + id + '"]').oneTime('10s', function() { $('#' + hash + ' .one-line[data-id="' + id + '"]').oneTime('10s', function() {
var this_sel = $(this);
// Not received? // Not received?
if($(this).attr('data-received') != 'true') { if(this_sel.attr('data-received') != 'true') {
// Add a "lost" marker // Add a "lost" marker
$(this).attr('data-lost', 'true'); this_sel.attr('data-lost', 'true');
// Add a warn on the buddy-name // Add a warn on the buddy-name
$(this).parent().find('b.name').addClass('talk-images') this_sel.parent().find('b.name').addClass('talk-images')
.attr('title', Common._e("Your friend seems not to have received your message(s)!")); .attr(
'title',
Common._e("Your friend seems not to have received your message(s)!")
);
} }
}); });
} catch(e) { } catch(e) {

View file

@ -57,12 +57,12 @@ var Roster = (function () {
// Parse the roster xml // Parse the roster xml
$(iq.getQuery()).find('item').each(function() { $(iq.getQuery()).find('item').each(function() {
// Get user data // Get user data
var _this = $(this); var this_sel = $(this);
var user_xid = _this.attr('jid'); var user_xid = this_sel.attr('jid');
var user_subscription = _this.attr('subscription'); var user_subscription = this_sel.attr('subscription');
// Parse roster data & display user // Parse roster data & display user
self.parse($(this), 'load'); self.parse(this_sel, 'load');
// Request user microblog (populates channel) // Request user microblog (populates channel)
if(user_xid && ((user_subscription == 'both') || (user_subscription == 'to'))) { if(user_xid && ((user_subscription == 'both') || (user_subscription == 'to'))) {
@ -106,17 +106,20 @@ var Roster = (function () {
current.find('group').each(function() { current.find('group').each(function() {
var group_text = $(this).text(); var group_text = $(this).text();
if(group_text) if(group_text) {
groups.push(group_text); groups.push(group_text);
}
}); });
// No group? // No group?
if(!groups.length) if(!groups.length) {
groups.push(Common._e("Unclassified")); groups.push(Common._e("Unclassified"));
}
// If no name is defined, we get the default nick of the buddy // If no name is defined, we get the default nick of the buddy
if(!dName) if(!dName) {
dName = Common.getXIDNick(xid); dName = Common.getXIDNick(xid);
}
self.display(xid, xidHash, dName, subscription, groups, mode); self.display(xid, xidHash, dName, subscription, groups, mode);
} catch(e) { } catch(e) {
@ -135,23 +138,28 @@ var Roster = (function () {
try { try {
$('#roster .one-group').each(function() { $('#roster .one-group').each(function() {
var this_sel = $(this);
// Current values // Current values
var check = $(this).find('.buddy').size(); var check = this_sel.find('.buddy').size();
var hidden = $(this).find('.buddy:not(.hidden-buddy:hidden)').size(); var hidden = this_sel.find('.buddy:not(.hidden-buddy:hidden)').size();
// Special case: the filtering tool // Special case: the filtering tool
if(Search.search_filtered) if(Search.search_filtered) {
hidden = $(this).find('.buddy:visible').size(); hidden = this_sel.find('.buddy:visible').size();
}
// If the group is empty // If the group is empty
if(!check) if(!check) {
$(this).remove(); this_sel.remove();
}
// If the group contains no online buddy (and is not just hidden) // If the group contains no online buddy (and is not just hidden)
if(!hidden && $(this).find('a.group').hasClass('minus')) if(!hidden && this_sel.find('a.group').hasClass('minus')) {
$(this).hide(); this_sel.hide();
else } else {
$(this).show(); this_sel.show();
}
}); });
} catch(e) { } catch(e) {
Console.error('Roster.updateGroups', e); Console.error('Roster.updateGroups', e);
@ -202,8 +210,9 @@ var Roster = (function () {
var privacy_class = ''; var privacy_class = '';
var privacy_state = Privacy.status('block', dXID); var privacy_state = Privacy.status('block', dXID);
if(privacy_state == 'deny') if(privacy_state == 'deny') {
privacy_class = ' blocked'; privacy_class = ' blocked';
}
// For each group this buddy has // For each group this buddy has
$.each(dGroup, function(i, cGroup) { $.each(dGroup, function(i, cGroup) {
@ -214,8 +223,9 @@ var Roster = (function () {
var groupBuddies = groupContent + ' .group-buddies'; var groupBuddies = groupContent + ' .group-buddies';
// Is this group blocked? // 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'; privacy_class = ' blocked';
}
// Group not yet displayed // Group not yet displayed
if(!Common.exists(groupContent)) { if(!Common.exists(groupContent)) {
@ -272,13 +282,13 @@ var Roster = (function () {
html += '<div class="name">'; html += '<div class="name">';
// Special gateway code // Special gateway code
if(is_gateway) if(is_gateway) {
html += presence_code + html += presence_code +
name_code; name_code;
} else {
else
html += name_code + html += name_code +
presence_code; presence_code;
}
html += '</div></div></div>'; html += '</div></div></div>';
@ -374,8 +384,9 @@ var Roster = (function () {
}); });
// Create a new checked checkbox // 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>'); $(bm_choose).prepend('<label><input type="checkbox" data-group="' + escaped_value + '" /><span>' + this_value.htmlEnc() + '</span></label>');
}
// Check the checkbox // Check the checkbox
$(bm_choose + ' input[data-group="' + escaped_value + '"]').attr('checked', true); $(bm_choose + ' input[data-group="' + escaped_value + '"]').attr('checked', true);
@ -423,8 +434,9 @@ var Roster = (function () {
Bubble.close(); Bubble.close();
// First unregister if gateway // First unregister if gateway
if(Common.isGateway(xid)) if(Common.isGateway(xid)) {
self.unregisterGateway(xid); self.unregisterGateway(xid);
}
// Then send roster removal query // Then send roster removal query
self.send(xid, 'remove'); self.send(xid, 'remove');
@ -462,8 +474,9 @@ var Roster = (function () {
// If the pointer is on a stored presence // If the pointer is on a stored presence
if(current.match(db_regex)) { if(current.match(db_regex)) {
if(Common.bareXID(RegExp.$1) == xid) if(Common.bareXID(RegExp.$1) == xid) {
DataStore.storageDB.removeItem(current); DataStore.storageDB.removeItem(current);
}
} }
} }
@ -510,13 +523,15 @@ var Roster = (function () {
// Apply the hover event // Apply the hover event
$(bPath).hover(function() { $(bPath).hover(function() {
// Another bubble exist // Another bubble exist
if(Common.exists('#roster .buddy-infos')) if(Common.exists('#roster .buddy-infos')) {
return false; return false;
}
$(bPath).oneTime(200, function() { $(bPath).oneTime(200, function() {
// Another bubble exist // Another bubble exist
if(Common.exists('#roster .buddy-infos')) if(Common.exists('#roster .buddy-infos')) {
return false; return false;
}
// Add this bubble! // Add this bubble!
Bubble.show(iPath); Bubble.show(iPath);
@ -552,36 +567,45 @@ var Roster = (function () {
// Click events // Click events
$(bPath + ' .bi-view a').click(function() { $(bPath + ' .bi-view a').click(function() {
var this_sel = $(this);
// Renitialize the buddy infos // Renitialize the buddy infos
Bubble.close(); Bubble.close();
// Profile // Profile
if($(this).is('.profile')) if(this_sel.is('.profile')) {
UserInfos.open(xid); UserInfos.open(xid);
}
// Channel // Channel
else if($(this).is('.channel')) else if(this_sel.is('.channel')) {
Microblog.fromInfos(xid, hash); Microblog.fromInfos(xid, hash);
}
// Command // Command
else if($(this).is('.commands')) else if(this_sel.is('.commands')) {
AdHoc.retrieve(xid); AdHoc.retrieve(xid);
}
return false; return false;
}); });
// Jingle events // Jingle events
$(bPath + ' .bi-jingle a').click(function() { $(bPath + ' .bi-jingle a').click(function() {
var this_sel = $(this);
// Renitialize the buddy infos // Renitialize the buddy infos
Bubble.close(); Bubble.close();
// Audio call? // Audio call?
if($(this).is('.audio')) if(this_sel.is('.audio')) {
Jingle.start(xid, 'audio'); Jingle.start(xid, 'audio');
}
// Video call? // Video call?
else if($(this).is('.video')) else if(this_sel.is('.video')) {
Jingle.start(xid, 'video'); Jingle.start(xid, 'video');
}
return false; return false;
}); });
@ -593,8 +617,9 @@ var Roster = (function () {
}); });
}); });
}, function() { }, function() {
if(!Common.exists(iPath + ' .manage-infos')) if(!Common.exists(iPath + ' .manage-infos')) {
Bubble.close(); Bubble.close();
}
$(bPath).stopTime(); $(bPath).stopTime();
}); });
@ -623,8 +648,9 @@ var Roster = (function () {
// Get the offset to define // Get the offset to define
var offset = 3; var offset = 3;
if(Common.isGateway(xid)) if(Common.isGateway(xid)) {
offset = -8; offset = -8;
}
// Process the position // Process the position
var v_position = $(buddy).position().top + offset; var v_position = $(buddy).position().top + offset;
@ -634,10 +660,11 @@ var Roster = (function () {
$(buddy_infos).css('top', v_position); $(buddy_infos).css('top', v_position);
// Apply the left/right position // Apply the left/right position
if($('html').attr('dir') == 'rtl') if($('html').attr('dir') == 'rtl') {
$(buddy_infos).css('right', h_position); $(buddy_infos).css('right', h_position);
else } else {
$(buddy_infos).css('left', h_position); $(buddy_infos).css('left', h_position);
}
} catch(e) { } catch(e) {
Console.error('Roster.buddyInfosPosition', e); Console.error('Roster.buddyInfosPosition', e);
} }
@ -659,14 +686,17 @@ var Roster = (function () {
// Each checked checkboxes // Each checked checkboxes
$(path + 'div.bm-choose input[type="checkbox"]').filter(':checked').each(function() { $(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) // Entered input value (and not yet in the array)
var value = $.trim($(path + 'p.bm-group input').val()); var value = $.trim($(path + 'p.bm-group input').val());
if(value && !Utils.existArrayValue(array, value)) if(value && !Utils.existArrayValue(array, value)) {
array.push(value); array.push(value);
}
return array; return array;
} catch(e) { } catch(e) {
@ -719,10 +749,13 @@ var Roster = (function () {
var groups = []; var groups = [];
$('#roster .one-group').each(function() { $('#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); groups.push(current);
}
}); });
return groups.sort(); return groups.sort();
@ -757,8 +790,9 @@ var Roster = (function () {
// Get the group privacy state // Get the group privacy state
for(var g in groups) { 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'; privacy_state = 'deny';
}
} }
// The subscription with this buddy is not full // The subscription with this buddy is not full
@ -767,21 +801,24 @@ var Roster = (function () {
html += '<p class="bm-authorize talk-images">'; html += '<p class="bm-authorize talk-images">';
// Link to allow to see our status // 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>'; authorize_links += '<a href="#" class="to">' + Common._e("Authorize") + '</a>';
}
// Link to ask to see his/her status // Link to ask to see his/her status
if((subscription == 'from') || (subscription == 'none')) { if((subscription == 'from') || (subscription == 'none')) {
if(authorize_links) if(authorize_links) {
authorize_links += ' / '; authorize_links += ' / ';
}
authorize_links += '<a href="#" class="from">' + Common._e("Ask for authorization") + '</a>'; authorize_links += '<a href="#" class="from">' + Common._e("Ask for authorization") + '</a>';
} }
// Link to unblock this buddy // Link to unblock this buddy
if((privacy_state == 'deny') && privacy_active) { if((privacy_state == 'deny') && privacy_active) {
if(authorize_links) if(authorize_links) {
authorize_links += ' / '; authorize_links += ' / ';
}
html += '<a href="#" class="unblock">' + Common._e("Unblock") + '</a>'; 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>'; remove_links = '<a href="#" class="remove">' + Common._e("Remove") + '</a>';
// This buddy is allowed to see our presence, we can show a "prohibit" link // 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>'; remove_links += ' / <a href="#" class="prohibit">' + Common._e("Prohibit") + '</a>';
}
// Complete the HTML code // Complete the HTML code
if((privacy_state != 'deny') && privacy_active) { if((privacy_state != 'deny') && privacy_active) {
if(remove_links) if(remove_links) {
remove_links += ' / '; remove_links += ' / ';
}
remove_links += '<a href="#" class="block">' + Common._e("Block") + '</a>'; 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>'; '<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 // 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>' + html += '<p class="bm-group talk-images"><label>' + Common._e("Groups") + '</label> <input type="text" /></p>' +
'<div class="bm-choose">' + '<div class="bm-choose">' +
'<div></div>' + '<div></div>' +
'</div>'; '</div>';
}
// Close the DOM element // Close the DOM element
html += '<a href="#" class="save">' + Common._e("Save") + '</a>' + html += '<a href="#" class="save">' + Common._e("Save") + '</a>' +
@ -836,8 +876,9 @@ var Roster = (function () {
// Is the current group checked? // Is the current group checked?
var checked = ''; var checked = '';
if(Utils.existArrayValue(groups, all_groups_current)) if(Utils.existArrayValue(groups, all_groups_current)) {
checked = ' checked="true"'; checked = ' checked="true"';
}
// Add the current group HTML // 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>'; 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})); var item = iqQuery.appendChild(iq.buildNode('item', {'xmlns': NS_ROSTER, 'jid': xid}));
// Any subscription? // Any subscription?
if(subscription) if(subscription) {
item.setAttribute('subscription', subscription); item.setAttribute('subscription', subscription);
}
// Any name? // Any name?
if(name) if(name) {
item.setAttribute('name', name); item.setAttribute('name', name);
}
// Any group? // Any group?
if(group && group.length) { if(group && group.length) {
for(var i in group) for(var i in group) {
item.appendChild(iq.buildNode('group', {'xmlns': NS_ROSTER}, group[i])); item.appendChild(iq.buildNode('group', {'xmlns': NS_ROSTER}, group[i]));
}
} }
con.send(iq); con.send(iq);
@ -936,8 +980,9 @@ var Roster = (function () {
var new_height = $('#left-content').height() - $('#my-infos').height() - 97; var new_height = $('#left-content').height() - $('#my-infos').height() - 97;
// New height too small // New height too small
if(new_height < 211) if(new_height < 211) {
new_height = 211; new_height = 211;
}
// Apply the new height // Apply the new height
$('#roster .content').css('height', new_height); $('#roster .content').css('height', new_height);
@ -1034,10 +1079,11 @@ var Roster = (function () {
.blur(function() { .blur(function() {
// Nothing is entered, put the placeholder instead // Nothing is entered, put the placeholder instead
if(!$.trim($(this).val())) if(!$.trim($(this).val())) {
aFilter.hide(); aFilter.hide();
else } else {
aFilter.show(); aFilter.show();
}
}) })
.keyup(function(e) { .keyup(function(e) {
@ -1062,8 +1108,9 @@ var Roster = (function () {
// When the user click on the add button, show the contact adding tool // When the user click on the add button, show the contact adding tool
$('#roster .foot .add').click(function() { $('#roster .foot .add').click(function() {
// Yet displayed? // Yet displayed?
if(Common.exists('#buddy-conf-add')) if(Common.exists('#buddy-conf-add')) {
return Bubble.close(); return Bubble.close();
}
// Add the bubble // Add the bubble
Bubble.show('#buddy-conf-add'); Bubble.show('#buddy-conf-add');
@ -1137,25 +1184,28 @@ var Roster = (function () {
var gateway = unescape($('.add-contact-gateway').val()); var gateway = unescape($('.add-contact-gateway').val());
// Generate the XID to add // Generate the XID to add
if((gateway != 'none') && xid) if((gateway != 'none') && xid) {
xid = xid.replace(/@/g, '%') + '@' + gateway; xid = xid.replace(/@/g, '%') + '@' + gateway;
else } else {
xid = Common.generateXID(xid, 'chat'); xid = Common.generateXID(xid, 'chat');
}
// Submit the form // Submit the form
if(xid && Common.getXIDNick(xid) && (xid != Common.getXID())) if(xid && Common.getXIDNick(xid) && (xid != Common.getXID())) {
self.addThisContact(xid, name); self.addThisContact(xid, name);
else } else {
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
$('.add-contact-jid').addClass('please-complete').focus(); $('.add-contact-jid').addClass('please-complete').focus();
}); });
}
return false; return false;
} }
// Escape : quit // Escape : quit
if(e.keyCode == 27) if(e.keyCode == 27) {
Bubble.close(); Bubble.close();
}
}); });
// Click event on search link // 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 // When the user click on the join button, show the chat joining tool
$('#roster .foot .join').click(function() { $('#roster .foot .join').click(function() {
// Yet displayed? // Yet displayed?
if(Common.exists('#buddy-conf-join')) if(Common.exists('#buddy-conf-join')) {
return Bubble.close(); return Bubble.close();
}
// Add the bubble // Add the bubble
Bubble.show('#buddy-conf-join'); Bubble.show('#buddy-conf-join');
@ -1209,10 +1260,7 @@ var Roster = (function () {
// Select something from the search // Select something from the search
if(Common.exists(dHovered)) { if(Common.exists(dHovered)) {
Search.addBuddy(destination, $(dHovered).attr('data-xid')); Search.addBuddy(destination, $(dHovered).attr('data-xid'));
} } else {
// Join something
else {
var xid = $.trim($('.join-jid').val()); var xid = $.trim($('.join-jid').val());
var type = $('.buddy-conf-join-select').val(); var type = $('.buddy-conf-join-select').val();
@ -1228,14 +1276,10 @@ var Roster = (function () {
// Create a new chat // Create a new chat
Chat.checkCreate(xid, type); Chat.checkCreate(xid, type);
} } else {
else {
$('.join-jid').addClass('please-complete'); $('.join-jid').addClass('please-complete');
} }
} } else {
else {
$('.join-jid').addClass('please-complete'); $('.join-jid').addClass('please-complete');
} }
} }
@ -1250,8 +1294,9 @@ var Roster = (function () {
// Buddy search? // Buddy search?
else if($('.buddy-conf-join-select').val() == 'chat') { else if($('.buddy-conf-join-select').val() == 'chat') {
// New buddy search // New buddy search
if((e.keyCode != 40) && (e.keyCode != 38)) if((e.keyCode != 40) && (e.keyCode != 38)) {
Search.createBuddy(destination); Search.createBuddy(destination);
}
// Navigating with keyboard in the results // Navigating with keyboard in the results
Search.arrowsBuddy(e, destination); Search.arrowsBuddy(e, destination);
@ -1282,8 +1327,9 @@ var Roster = (function () {
// When the user click on the groupchat button, show the groupchat menu // When the user click on the groupchat button, show the groupchat menu
$('#roster .foot .groupchat').click(function() { $('#roster .foot .groupchat').click(function() {
// Yet displayed? // Yet displayed?
if(Common.exists('#buddy-conf-groupchat')) if(Common.exists('#buddy-conf-groupchat')) {
return Bubble.close(); return Bubble.close();
}
// Add the bubble // Add the bubble
Bubble.show('#buddy-conf-groupchat'); Bubble.show('#buddy-conf-groupchat');
@ -1334,12 +1380,61 @@ var Roster = (function () {
return false; 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 // When the user click on the more button, show the more menu
$('#roster .foot .more').click(function() { $('#roster .foot .more').click(function() {
// Yet displayed? // Yet displayed?
if(Common.exists('#buddy-conf-more')) if(Common.exists('#buddy-conf-more')) {
return Bubble.close(); return Bubble.close();
}
// Add the bubble // Add the bubble
Bubble.show('#buddy-conf-more'); Bubble.show('#buddy-conf-more');
@ -1410,11 +1505,13 @@ var Roster = (function () {
$('.buddy-conf-more-display-available').show(); $('.buddy-conf-more-display-available').show();
} }
if(Features.enabledCommands()) if(Features.enabledCommands()) {
$('.buddy-conf-more-commands').parent().show(); $('.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(); $('.buddy-conf-more-privacy').parent().show();
}
return false; return false;
}); });

View file

@ -97,34 +97,44 @@ var RosterX = (function () {
// Parse data // Parse data
x.find('item').each(function() { x.find('item').each(function() {
var this_sel = $(this);
// Generate group XML // Generate group XML
var group = ''; var group = '';
$(this).find('group').each(function() { this_sel.find('group').each(function() {
group += '<group>' + $(this).text().htmlEnc() + '</group>'; group += '<group>' + this_sel.text().htmlEnc() + '</group>';
}); });
if(group) if(group) {
group = '<groups>' + group + '</groups>'; group = '<groups>' + group + '</groups>';
}
// Display it! // 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 // Click to check/uncheck
$('#rosterx .oneresult').click(function(evt) { $('#rosterx .oneresult').click(function(evt) {
// No need to apply when click on input // No need to apply when click on input
if($(evt.target).is('input[type="checkbox"]')) if($(evt.target).is('input[type="checkbox"]')) {
return; return;
}
// Input selector // Input selector
var checkbox = $(this).find('input[type="checkbox"]'); var checkbox = $(this).find('input[type="checkbox"]');
// Check or uncheck? // Check or uncheck?
if(checkbox.filter(':checked').size()) if(checkbox.filter(':checked').size()) {
checkbox.removeAttr('checked'); checkbox.removeAttr('checked');
else } else {
checkbox.attr('checked', true); checkbox.attr('checked', true);
}
}); });
} catch(e) { } catch(e) {
Console.error('RosterX.parse', e); Console.error('RosterX.parse', e);
@ -146,16 +156,19 @@ var RosterX = (function () {
try { try {
// End if no XID // End if no XID
if(!xid) if(!xid) {
return false; return false;
}
// Set up a default action if no one // Set up a default action if no one
if(!action || (action != 'modify') || (action != 'delete')) if(!action || (action != 'modify') || (action != 'delete')) {
action = 'add'; action = 'add';
}
// Override "undefined" for nickname // Override "undefined" for nickname
if(!nick) if(!nick) {
nick = ''; nick = '';
}
// Display it // Display it
$('#rosterx .results').append( $('#rosterx .results').append(
@ -178,25 +191,27 @@ var RosterX = (function () {
/** /**
* Saves the rosterx settings * Saves the rosterx settings
* @public * @public
* @return {undefined} * @return {boolean}
*/ */
self.save = function() { self.save = function() {
try { try {
// Send the requests // Send the requests
$('#rosterx .results input[type="checkbox"]').filter(':checked').each(function() { $('#rosterx .results input[type="checkbox"]').filter(':checked').each(function() {
var this_sel = $(this);
// Read the attributes // Read the attributes
var nick = $(this).attr('data-name'); var nick = this_sel.attr('data-name');
var xid = $(this).attr('data-xid'); var xid = this_sel.attr('data-xid');
var action = $(this).attr('data-action'); var action = this_sel.attr('data-action');
var group = $(this).attr('data-group'); var group = this_sel.attr('data-group');
// Parse groups XML // Parse groups XML
var group_arr = []; var group_arr = [];
if(group) { if(group) {
$(group).find('group').each(function() { $(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(); self.close();
} catch(e) { } catch(e) {
Console.error('RosterX.save', e); Console.error('RosterX.save', e);
} finally {
return false;
} }
}; };
@ -248,17 +265,25 @@ var RosterX = (function () {
try { try {
// Click events // Click events
$('#rosterx .bottom .finish').click(function() { $('#rosterx .bottom .finish').click(function() {
if($(this).is('.save')) var this_sel = $(this);
if(this_sel.is('.save')) {
return self.save(); return self.save();
if($(this).is('.cancel')) }
if(this_sel.is('.cancel')) {
return self.close(); return self.close();
}
}); });
$('#rosterx .rosterx-head a').click(function() { $('#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); $('#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'); $('#rosterx .results input[type="checkbox"]').removeAttr('checked');
}
return false; return false;
}); });

View file

@ -112,8 +112,9 @@ var Search = (function () {
// Get the old value (if there's another value) // Get the old value (if there's another value)
var old = ''; var old = '';
if(value.match(/(^(.+)(,)(\s)?)(\w+)$/)) if(value.match(/(^(.+)(,)(\s)?)(\w+)$/)) {
old = RegExp.$1; old = RegExp.$1;
}
// Add the XID to the "to" input and focus on it // Add the XID to the "to" input and focus on it
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
@ -144,8 +145,9 @@ var Search = (function () {
var value = $(destination + ' input').val(); var value = $(destination + ' input').val();
// Separation with a comma? // Separation with a comma?
if(value.match(/^(.+)((,)(\s)?)(\w+)$/)) if(value.match(/^(.+)((,)(\s)?)(\w+)$/)) {
value = RegExp.$5; value = RegExp.$5;
}
// Get the result array // Get the result array
var entered = self.processBuddy(value); var entered = self.processBuddy(value);
@ -217,8 +219,9 @@ var Search = (function () {
var code = evt.keyCode; var code = evt.keyCode;
// Not the key we want here // Not the key we want here
if((code != 40) && (code != 38)) if((code != 40) && (code != 38)) {
return; return;
}
// Remove the eventual mouse hover marker // Remove the eventual mouse hover marker
$(destination + ' ul').removeAttr('mouse-hover'); $(destination + ' ul').removeAttr('mouse-hover');
@ -234,25 +237,25 @@ var Search = (function () {
if(Common.exists(path + '.hovered')) { if(Common.exists(path + '.hovered')) {
var index = $(path).attr('data-hovered'); var index = $(path).attr('data-hovered');
if(index) if(index) {
i = parseInt(index); i = parseInt(index);
}
if(code == 40) if(code == 40) {
i++; i++;
else } else {
i--; i--;
}
} else if(code == 38) {
i = pSize - 1;
} }
else if(code == 38)
i = pSize - 1;
// We must not override the maximum i limit // We must not override the maximum i limit
if(i >= pSize) if(i >= pSize) {
i = 0; i = 0;
} else if(i < 0) {
// We must not have negative i
else if(i < 0)
i = pSize - 1; i = pSize - 1;
}
// Modify the list // Modify the list
$(path + '.hovered').removeClass('hovered'); $(path + '.hovered').removeClass('hovered');
@ -289,11 +292,13 @@ var Search = (function () {
// Only show the buddies which match the search // Only show the buddies which match the search
if(!Roster.blist_all) { 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(); $('#roster .buddy[data-xid="' + escape(rFilter[i]) + '"]:not(.hidden-buddy)').show();
}
} else { } else {
for(var j in rFilter) for(var j in rFilter) {
$('#roster .buddy[data-xid="' + escape(rFilter[j]) + '"]').show(); $('#roster .buddy[data-xid="' + escape(rFilter[j]) + '"]').show();
}
} }
} catch(e) { } catch(e) {
Console.error('Search.goFilterBuddy', e); Console.error('Search.goFilterBuddy', e);
@ -317,8 +322,9 @@ var Search = (function () {
$('#roster .buddy').show(); $('#roster .buddy').show();
// Only show available buddies // Only show available buddies
if(!Roster.blist_all) if(!Roster.blist_all) {
$('#roster .buddy.hidden-buddy').hide(); $('#roster .buddy.hidden-buddy').hide();
}
// Update the groups // Update the groups
Roster.updateGroups(); Roster.updateGroups();
@ -349,15 +355,13 @@ var Search = (function () {
// Nothing is entered, or escape pressed // Nothing is entered, or escape pressed
if(!value || (keycode == 27)) { if(!value || (keycode == 27)) {
if(keycode == 27) if(keycode == 27) {
input.val(''); input.val('');
}
self.resetFilterBuddy(); self.resetFilterBuddy();
cancel.hide(); cancel.hide();
} } else {
// Process the filtering
else {
cancel.show(); cancel.show();
self.goFilterBuddy(value); self.goFilterBuddy(value);
} }

View file

@ -20,6 +20,51 @@ var Smileys = (function () {
var self = {}; 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 * Generates the correct HTML code for an emoticon insertion tool
* @public * @public
@ -43,101 +88,19 @@ var Smileys = (function () {
* Emoticon links arrays * Emoticon links arrays
* @public * @public
* @param {string} hash * @param {string} hash
* @return {object} * @return {string}
*/ */
self.links = function(hash) { self.links = function(hash) {
try { try {
var links = ''; var links = '';
var sArray = [ for(var cur_emote in self.emote_list) {
':-D', links += self.emoteLink(
']:->', self.emote_list[cur_emote],
'8-)', cur_emote,
':-P', hash
':-)', );
';-)',
':-$',
':-|',
':-/',
'=-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);
} }
return links; return links;

View file

@ -70,44 +70,51 @@ var Storage = (function () {
// Parse the options xml // Parse the options xml
options.find('option').each(function() { options.find('option').each(function() {
var this_sel = $(this);
// We retrieve the informations // We retrieve the informations
var type = $(this).attr('type'); var type = this_sel.attr('type');
var value = $(this).text(); var value = this_sel.text();
// We display the storage // We display the storage
DataStore.setDB(Connection.desktop_hash, 'options', type, value); DataStore.setDB(Connection.desktop_hash, 'options', type, value);
// If this is the buddy list show status // If this is the buddy list show status
if((type == 'roster-showall') && (value == '1')) if((type == 'roster-showall') && (value == '1')) {
Interface.showAllBuddies('storage'); Interface.showAllBuddies('storage');
}
}); });
// Parse the inbox xml // Parse the inbox xml
inbox.find('message').each(function() { inbox.find('message').each(function() {
var this_sel = $(this);
Inbox.storeMessage( Inbox.storeMessage(
$(this).attr('from'), this_sel.attr('from'),
$(this).attr('subject'), this_sel.attr('subject'),
$(this).text(), this_sel.text(),
$(this).attr('status'), this_sel.attr('status'),
$(this).attr('id'), this_sel.attr('id'),
$(this).attr('date'), this_sel.attr('date'),
[ [
$(this).attr('file_title'), this_sel.attr('file_title'),
$(this).attr('file_href'), this_sel.attr('file_href'),
$(this).attr('file_type'), this_sel.attr('file_type'),
$(this).attr('file_length') this_sel.attr('file_length')
] ]
); );
}); });
// Parse the bookmarks xml // Parse the bookmarks xml
bookmarks.find('conference').each(function() { bookmarks.find('conference').each(function() {
var this_sel = $(this);
// We retrieve the informations // We retrieve the informations
var xid = $(this).attr('jid'); var xid = this_sel.attr('jid');
var name = $(this).attr('name'); var name = this_sel.attr('name');
var autojoin = $(this).attr('autojoin'); var autojoin = this_sel.attr('autojoin');
var password = $(this).find('password').text(); var password = this_sel.find('password').text();
var nick = $(this).find('nick').text(); var nick = this_sel.find('nick').text();
// Filter autojoin (compatibility) // Filter autojoin (compatibility)
autojoin = ((autojoin == 'true') || (autojoin == '1')) ? 'true' : 'false'; autojoin = ((autojoin == 'true') || (autojoin == '1')) ? 'true' : 'false';
@ -116,13 +123,21 @@ var Storage = (function () {
Favorites.display(xid, name, nick, autojoin, password); Favorites.display(xid, name, nick, autojoin, password);
// Join the chat if autojoin is enabled // Join the chat if autojoin is enabled
if(autojoin == 'true') if(autojoin == 'true') {
Chat.checkCreate(xid, 'groupchat', nick, password, name); Chat.checkCreate(xid, 'groupchat', nick, password, name);
}
}); });
// Parse the roster notes xml // Parse the roster notes xml
rosternotes.find('note').each(function() { 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 // Options received

View file

@ -31,14 +31,18 @@ var System = (function () {
var url = window.location.href; var url = window.location.href;
// If the URL has variables, remove them // If the URL has variables, remove them
if(url.indexOf('?') != -1) if(url.indexOf('?') != -1) {
url = url.split('?')[0]; url = url.split('?')[0];
if(url.indexOf('#') != -1) }
if(url.indexOf('#') != -1) {
url = url.split('#')[0]; url = url.split('#')[0];
}
// No "/" at the end // No "/" at the end
if(!url.match(/(.+)\/$/)) if(!url.match(/(.+)\/$/)) {
url += '/'; url += '/';
}
return url; return url;
} catch(e) { } catch(e) {

View file

@ -51,8 +51,9 @@ var Talk = (function () {
try { try {
// Talkpage exists? // Talkpage exists?
if(Common.exists('#talk')) if(Common.exists('#talk')) {
return false; return false;
}
// Anonymous detector // Anonymous detector
var anonymous = Utils.isAnonymous(); var anonymous = Utils.isAnonymous();
@ -116,14 +117,14 @@ var Talk = (function () {
if(!anonymous) html += if(!anonymous) html +=
'<div class="tools-all">' + '<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="streaming-items">' +
'<span class="counter" data-default="00:00:00">00:00:00</span>' + '<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>' + '</span>' +
'</div>' + '</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-subarrow talk-images"></div>' +
'<div class="tools-content-subitem"></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>' + '<a href="#" class="groupchat talk-images" title="' + Common._e("Your groupchats") + '"></a>' +
'</div>' + '</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">' + '<div class="roster-more roster-icon">' +
'<a href="#" class="more talk-images" title="' + Common._e("More stuff") + '"></a>' + '<a href="#" class="more talk-images" title="' + Common._e("More stuff") + '"></a>' +
'</div>' + '</div>' +

View file

@ -37,8 +37,9 @@ var Tooltip = (function () {
var path_bubble = path_tooltip + ' .bubble-' + type; var path_bubble = path_tooltip + ' .bubble-' + type;
// Yet exists? // Yet exists?
if(Common.exists(path_bubble)) if(Common.exists(path_bubble)) {
return false; return false;
}
// Generates special tooltip HTML code // Generates special tooltip HTML code
var title = ''; var title = '';
@ -211,47 +212,52 @@ var Tooltip = (function () {
// Click event on style bubble // Click event on style bubble
$(bubble_style).click(function() { $(bubble_style).click(function() {
// Hide font selector if opened // Hide font selector if opened
if($(font_list).is(':visible')) if($(font_list).is(':visible')) {
$(font_current).click(); $(font_current).click();
}
// Hide font-size selector if opened // Hide font-size selector if opened
if($(fontsize_list).is(':visible')) if($(fontsize_list).is(':visible')) {
$(fontsize_current).click(); $(fontsize_current).click();
}
// Hide color selector if opened // Hide color selector if opened
if($(color_hex).is(':visible')) if($(color_hex).is(':visible')) {
$(color_more).click(); $(color_more).click();
}
}); });
// Click event on font picker // Click event on font picker
$(font_current).click(function() { $(font_current).click(function() {
var this_sel = $(this);
// The clicked color is yet selected // The clicked color is yet selected
if($(font_list).is(':visible')) if($(font_list).is(':visible')) {
$(this).parent().removeClass('listed'); this_sel.parent().removeClass('listed');
else } else {
$(this).parent().addClass('listed'); this_sel.parent().addClass('listed');
}
return false; return false;
}); });
// Click event on a new font in the picker // Click event on a new font in the picker
$(font_select).click(function() { $(font_select).click(function() {
var this_sel = $(this);
// No font selected // No font selected
if(!$(this).attr('data-value')) { if(!this_sel.attr('data-value')) {
$(font_current).removeAttr('data-font') $(font_current).removeAttr('data-font')
.removeAttr('data-value') .removeAttr('data-value')
.text(Common._e("None")); .text(Common._e("None"));
$(message_area).removeAttr('data-font'); $(message_area).removeAttr('data-font');
} } else {
$(font_current).attr('data-font', this_sel.attr('data-font'))
// A font is defined .attr('data-value', this_sel.attr('data-value'))
else { .text($(font_list).find('a[data-value="' + this_sel.attr('data-value') + '"]').text());
$(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());
$(message_area).attr('data-font', $(this).attr('data-value')); $(message_area).attr('data-font', this_sel.attr('data-value'));
} }
return false; return false;
@ -259,28 +265,33 @@ var Tooltip = (function () {
// Click event on font-size picker // Click event on font-size picker
$(fontsize_current).click(function() { $(fontsize_current).click(function() {
var this_sel = $(this);
// The clicked color is yet selected // The clicked color is yet selected
if($(fontsize_list).is(':visible')) if($(fontsize_list).is(':visible')) {
$(this).parent().removeClass('listed'); this_sel.parent().removeClass('listed');
else } else {
$(this).parent().addClass('listed'); this_sel.parent().addClass('listed');
}
return false; return false;
}); });
// Click event on a new font-size in the picker // Click event on a new font-size in the picker
$(fontsize_select).click(function() { $(fontsize_select).click(function() {
var this_sel = $(this);
// No font-size selected // No font-size selected
if(!$(this).attr('data-value')) { if(!this_sel.attr('data-value')) {
$(fontsize_current).removeAttr('data-value').text(Common._e("16")); $(fontsize_current).removeAttr('data-value').text(Common._e("16"));
$(message_area).removeAttr('data-fontsize'); $(message_area).removeAttr('data-fontsize');
} }
// A font-size is defined // A font-size is defined
else { else {
$(fontsize_current).attr('data-value', $(this).attr('data-value')) $(fontsize_current).attr('data-value', this_sel.attr('data-value'))
.text($(this).attr('data-value')); .text(this_sel.attr('data-value'));
$(message_area).attr('data-fontsize', $(this).attr('data-value')); $(message_area).attr('data-fontsize', this_sel.attr('data-value'));
} }
return false; return false;
@ -288,19 +299,21 @@ var Tooltip = (function () {
// Click event on color picker // Click event on color picker
$(colors).click(function() { $(colors).click(function() {
var this_sel = $(this);
// Reset the manual picker // Reset the manual picker
$(color_hex).find('input').val(''); $(color_hex).find('input').val('');
// The clicked color is yet selected // The clicked color is yet selected
if($(this).hasClass('selected')) { if(this_sel.hasClass('selected')) {
$(message_area).removeAttr('data-color'); $(message_area).removeAttr('data-color');
$(this).removeClass('selected'); this_sel.removeClass('selected');
} }
else { else {
$(message_area).attr('data-color', $(this).attr('data-color')); $(message_area).attr('data-color', this_sel.attr('data-color'));
$(colors).removeClass('selected'); $(colors).removeClass('selected');
$(this).addClass('selected'); this_sel.addClass('selected');
} }
return false; return false;
@ -308,12 +321,13 @@ var Tooltip = (function () {
// Click event on color picker // Click event on color picker
$(color_more).click(function() { $(color_more).click(function() {
var this_sel = $(this);
// The clicked color is yet selected // The clicked color is yet selected
if($(color_hex).is(':visible')) if($(color_hex).is(':visible')) {
$(this).parent().removeClass('opened'); this_sel.parent().removeClass('opened');
} else {
else { this_sel.parent().addClass('opened');
$(this).parent().addClass('opened');
// Focus // Focus
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
@ -331,6 +345,8 @@ var Tooltip = (function () {
// Keyup event on color picker // Keyup event on color picker
$(color_hex).find('input').keyup(function(e) { $(color_hex).find('input').keyup(function(e) {
var this_sel = $(this);
// Submit // Submit
if(e.keyCode == 13) { if(e.keyCode == 13) {
if($(color_hex).is(':visible')) { if($(color_hex).is(':visible')) {
@ -350,32 +366,37 @@ var Tooltip = (function () {
$(colors).removeClass('selected'); $(colors).removeClass('selected');
// Change value // Change value
var new_value = $(this).val().replace(/([^a-z0-9]+)/gi, ''); var new_value = this_sel.val().replace(/([^a-z0-9]+)/gi, '');
$(this).val(new_value); this_sel.val(new_value);
if(new_value) if(new_value) {
$(message_area).attr('data-color', new_value); $(message_area).attr('data-color', new_value);
}
// Regenerate style // Regenerate style
var style = Message.generateStyle(hash); var style = Message.generateStyle(hash);
// Any style to apply? // Any style to apply?
if(style) if(style) {
$(message_area).attr('style', style); $(message_area).attr('style', style);
else } else {
$(message_area).removeAttr('style'); $(message_area).removeAttr('style');
}
}).placeholder(); }).placeholder();
// Change event on text style checkboxes // Change event on text style checkboxes
$(style).change(function() { $(style).change(function() {
var this_sel = $(this);
// Get current type // Get current type
var style_data = 'data-' + $(this).attr('class'); var style_data = 'data-' + this_sel.attr('class');
// Checked checkbox? // Checked checkbox?
if($(this).filter(':checked').size()) if(this_sel.filter(':checked').size()) {
$(message_area).attr(style_data, true); $(message_area).attr(style_data, true);
else } else {
$(message_area).removeAttr(style_data); $(message_area).removeAttr(style_data);
}
}); });
// Update the textarea style when it is changed // Update the textarea style when it is changed
@ -383,10 +404,11 @@ var Tooltip = (function () {
var style = Message.generateStyle(hash); var style = Message.generateStyle(hash);
// Any style to apply? // Any style to apply?
if(style) if(style) {
$(message_area).attr('style', style); $(message_area).attr('style', style);
else } else {
$(message_area).removeAttr('style'); $(message_area).removeAttr('style');
}
// Focus again on the message textarea // Focus again on the message textarea
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
@ -410,24 +432,31 @@ var Tooltip = (function () {
// Upload form submit event // Upload form submit event
$(path_tooltip + ' #oob-upload').submit(function() { $(path_tooltip + ' #oob-upload').submit(function() {
if($(path_tooltip + ' #oob-upload input[type="file"]').val()) var this_sel = $(this);
$(this).ajaxSubmit(oob_upload_options);
if($(path_tooltip + ' #oob-upload input[type="file"]').val()) {
this_sel.ajaxSubmit(oob_upload_options);
}
return false; return false;
}); });
// Upload input change event // Upload input change event
$(path_tooltip + ' #oob-upload input[type="file"]').change(function() { $(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); $(path_tooltip + ' #oob-upload').ajaxSubmit(oob_upload_options);
}
return false; return false;
}); });
// Input click event // Input click event
$(path_tooltip + ' #oob-upload input[type="file"], ' + path_tooltip + ' #oob-upload input[type="submit"]').click(function() { $(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; return;
}
// Lock the bubble // Lock the bubble
$(path_bubble).addClass('locked'); $(path_bubble).addClass('locked');
@ -569,17 +598,21 @@ var Tooltip = (function () {
// Apply the options to the style selector // Apply the options to the style selector
$(bubble_style + ' input[type="checkbox"]').each(function() { $(bubble_style + ' input[type="checkbox"]').each(function() {
var this_sel = $(this);
// Current input enabled? // Current input enabled?
if(message_area.attr('data-' + $(this).attr('class'))) if(message_area.attr('data-' + this_sel.attr('class'))) {
$(this).attr('checked', true); this_sel.attr('checked', true);
}
}); });
// Apply message color // Apply message color
if(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'); $(bubble_style + ' a.color[data-color="' + color + '"]').addClass('selected');
else } else {
$(bubble_style + ' div.color-hex input.hex-value').val(color); $(bubble_style + ' div.color-hex input.hex-value').val(color);
}
} }
} catch(e) { } catch(e) {
Console.error('Tooltip.loadStyleSelector', e); Console.error('Tooltip.loadStyleSelector', e);

View file

@ -298,8 +298,9 @@ var UserInfos = (function () {
var path = '#userinfos[data-last="' + id + '"]'; var path = '#userinfos[data-last="' + id + '"]';
// End if session does not exist // End if session does not exist
if(!Common.exists(path)) if(!Common.exists(path)) {
return; return;
}
if(iq && (iq.getType() == 'result')) { if(iq && (iq.getType() == 'result')) {
// Get the values // Get the values
@ -313,8 +314,9 @@ var UserInfos = (function () {
seconds = parseInt(seconds); seconds = parseInt(seconds);
// Active user // Active user
if(seconds <= 60) if(seconds <= 60) {
last = Common._e("User currently active"); last = Common._e("User currently active");
}
// Inactive user // Inactive user
else { else {
@ -325,12 +327,14 @@ var UserInfos = (function () {
var date = date_last.toLocaleString(); var date = date_last.toLocaleString();
// Offline user // Offline user
if(from.indexOf('/') == -1) if(from.indexOf('/') == -1) {
last = Common.printf(Common._e("Last seen: %s"), date); last = Common.printf(Common._e("Last seen: %s"), date);
}
// Online user // Online user
else else {
last = Common.printf(Common._e("Inactive since: %s"), date); last = Common.printf(Common._e("Inactive since: %s"), date);
}
} }
// Append this text // Append this text
@ -363,8 +367,9 @@ var UserInfos = (function () {
var path = '#userinfos[data-version="' + id + '"]'; var path = '#userinfos[data-version="' + id + '"]';
// End if session does not exist // End if session does not exist
if(!Common.exists(path)) if(!Common.exists(path)) {
return; return;
}
// Extract the reply data // Extract the reply data
if(iq && (iq.getType() == 'result')) { if(iq && (iq.getType() == 'result')) {
@ -375,14 +380,18 @@ var UserInfos = (function () {
var os = $(xml).find('os').text(); var os = $(xml).find('os').text();
// Put the values together // Put the values together
if(name && version) if(name && version) {
name = name + ' ' + version; name = name + ' ' + version;
}
// Display the values // Display the values
if(name) if(name) {
$(path + ' #BUDDY-CLIENT').text(name); $(path + ' #BUDDY-CLIENT').text(name);
if(os) }
if(os) {
$(path + ' #BUDDY-SYSTEM').text(os); $(path + ' #BUDDY-SYSTEM').text(os);
}
Console.log('Software version received: ' + Common.fullXID(Common.getStanzaFrom(iq))); Console.log('Software version received: ' + Common.fullXID(Common.getStanzaFrom(iq)));
} }
@ -410,8 +419,9 @@ var UserInfos = (function () {
var path = '#userinfos[data-time="' + id + '"]'; var path = '#userinfos[data-time="' + id + '"]';
// End if session does not exist // End if session does not exist
if(!Common.exists(path)) if(!Common.exists(path)) {
return; return;
}
if(iq && (iq.getType() == 'result')) { if(iq && (iq.getType() == 'result')) {
// Get the values // Get the values
@ -422,8 +432,9 @@ var UserInfos = (function () {
// Any UTC? // Any UTC?
if(utc) { if(utc) {
// Add the TZO if there's no one // Add the TZO if there's no one
if(tzo && utc.match(/^(.+)Z$/)) if(tzo && utc.match(/^(.+)Z$/)) {
utc = RegExp.$1 + tzo; utc = RegExp.$1 + tzo;
}
// Get the local date string // Get the local date string
var local_string = Date.hrTime(utc); var local_string = Date.hrTime(utc);
@ -454,8 +465,9 @@ var UserInfos = (function () {
try { try {
var selector = $('#userinfos .content'); 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(); $('#userinfos .wait').hide();
}
} catch(e) { } catch(e) {
Console.error('UserInfos.wait', e); Console.error('UserInfos.wait', e);
} }
@ -478,8 +490,9 @@ var UserInfos = (function () {
// Necessary to update? // Necessary to update?
var old_value = DataStore.getDB(Connection.desktop_hash, 'rosternotes', xid); 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; return false;
}
// Update the database // Update the database
DataStore.setDB(Connection.desktop_hash, 'rosternotes', xid, value); DataStore.setDB(Connection.desktop_hash, 'rosternotes', xid, value);
@ -502,8 +515,9 @@ var UserInfos = (function () {
var cur_xid = RegExp.$1; var cur_xid = RegExp.$1;
var cur_value = DataStore.storageDB.getItem(current); 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)); storage.appendChild(iq.buildNode('note', {'jid': cur_xid, 'xmlns': NS_ROSTERNOTES}, cur_value));
}
} }
} }
@ -526,10 +540,15 @@ var UserInfos = (function () {
self.switchTab = function(id) { self.switchTab = function(id) {
try { try {
$('#userinfos .content .one-lap').hide(); var userinfos_sel = $('#userinfos');
$('#userinfos .content .info' + id).show(); var content_sel = userinfos_sel.find('.content');
$('#userinfos .tab a').removeClass('tab-active'); var tab_link_sel = userinfos_sel.find('.tab a');
$('#userinfos .tab a[data-key="' + id + '"]').addClass('tab-active');
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) { } catch(e) {
Console.error('UserInfos.switchTab', e); Console.error('UserInfos.switchTab', e);
} finally { } finally {
@ -582,12 +601,15 @@ var UserInfos = (function () {
try { try {
// Click events // Click events
$('#userinfos .tab a').click(function() { $('#userinfos .tab a').click(function() {
var this_sel = $(this);
// Yet active? // Yet active?
if($(this).hasClass('tab-active')) if(this_sel.hasClass('tab-active')) {
return false; return false;
}
// Switch to the good tab // Switch to the good tab
var key = parseInt($(this).attr('data-key')); var key = parseInt(this_sel.attr('data-key'));
return self.switchTab(key); return self.switchTab(key);
}); });

View file

@ -52,8 +52,9 @@ var Utils = (function () {
try { try {
// HTTPS not allowed // HTTPS not allowed
if((HTTPS_STORAGE != 'on') && url.match(/^https(.+)/)) if((HTTPS_STORAGE != 'on') && url.match(/^https(.+)/)) {
url = 'http' + RegExp.$1; url = 'http' + RegExp.$1;
}
return url; return url;
} catch(e) { } catch(e) {
@ -217,28 +218,34 @@ var Utils = (function () {
var browser_version = BrowserDetect.version; var browser_version = BrowserDetect.version;
// No DOM storage // No DOM storage
if(!DataStore.hasDB() || !DataStore.hasPersistent()) if(!DataStore.hasDB() || !DataStore.hasPersistent()) {
return true; return true;
}
// Obsolete IE // Obsolete IE
if((browser_name == 'Explorer') && (browser_version < 8)) if((browser_name == 'Explorer') && (browser_version < 8)) {
return true; return true;
}
// Obsolete Chrome // Obsolete Chrome
if((browser_name == 'Chrome') && (browser_version < 7)) if((browser_name == 'Chrome') && (browser_version < 7)) {
return true; return true;
}
// Obsolete Safari // Obsolete Safari
if((browser_name == 'Safari') && (browser_version < 4)) if((browser_name == 'Safari') && (browser_version < 4)) {
return true; return true;
}
// Obsolete Firefox // Obsolete Firefox
if((browser_name == 'Firefox') && (browser_version < 3.5)) if((browser_name == 'Firefox') && (browser_version < 3.5)) {
return true; return true;
}
// Obsolete Opera // Obsolete Opera
if((browser_name == 'Opera') && (browser_version < 9)) if((browser_name == 'Opera') && (browser_version < 9)) {
return true; return true;
}
return false; return false;
} catch(e) { } 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 * Converts a string to an array
* @public * @public
@ -603,10 +637,11 @@ var Utils = (function () {
var string_split = string.split(','); var string_split = string.split(',');
for(var i in string_split) { for(var i in string_split) {
if(string_split[i]) if(string_split[i]) {
array.push(string_split[i]); array.push(string_split[i]);
else } else {
array.push(''); array.push('');
}
} }
} }
@ -634,8 +669,9 @@ var Utils = (function () {
try { try {
// Nothing? // Nothing?
if(!array || !array.length) if(!array || !array.length) {
return 0; return 0;
}
// Read the index of the value // Read the index of the value
var index = 0; var index = 0;

View file

@ -272,7 +272,7 @@ var vCard = (function () {
$('#USER-PHOTO-TYPE').val(aType); $('#USER-PHOTO-TYPE').val(aType);
$('#USER-PHOTO-BINVAL').val(aBinval); $('#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>'); $('#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 // Send the IQ
con.send(iq, self.handleUser); con.send(iq, self.handleUser);
} } else {
else {
// Show the wait icon // Show the wait icon
$('#userinfos .wait').show(); $('#userinfos .wait').show();
@ -456,12 +454,14 @@ var vCard = (function () {
var values_yet = []; var values_yet = [];
$(iqNode).find('vCard').children().each(function() { $(iqNode).find('vCard').children().each(function() {
var this_sel = $(this);
// Read the current parent node name // Read the current parent node name
var tokenname = (this).nodeName.toUpperCase(); var tokenname = (this).nodeName.toUpperCase();
// Node with a parent // Node with a parent
if($(this).children().size()) { if(this_sel.children().size()) {
$(this).children().each(function() { this_sel.children().each(function() {
// Get the node values // Get the node values
var currentID = tokenname + '-' + (this).nodeName.toUpperCase(); var currentID = tokenname + '-' + (this).nodeName.toUpperCase();
var currentText = $(this).text(); var currentText = $(this).text();
@ -473,10 +473,11 @@ var vCard = (function () {
// Userinfos viewer popup // Userinfos viewer popup
if((type == 'buddy') && currentText) { 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>'); $(path_userInfos + ' #BUDDY-' + currentID).html('<a href="mailto:' + currentText.htmlEnc() + '" target="_blank">' + currentText.htmlEnc() + '</a>');
else } else {
$(path_userInfos + ' #BUDDY-' + currentID).text(currentText.htmlEnc()); $(path_userInfos + ' #BUDDY-' + currentID).text(currentText.htmlEnc());
}
} }
// Profile editor popup // Profile editor popup
@ -505,8 +506,9 @@ var vCard = (function () {
// URL modification // URL modification
if(tokenname == 'URL') { if(tokenname == 'URL') {
// No http:// or https:// prefix, we should add it // No http:// or https:// prefix, we should add it
if(!currentText.match(/^https?:\/\/(.+)/)) if(!currentText.match(/^https?:\/\/(.+)/)) {
currentText = 'http://' + currentText; currentText = 'http://' + currentText;
}
currentText = '<a href="' + currentText + '" target="_blank">' + currentText.htmlEnc() + '</a>'; currentText = '<a href="' + currentText + '" target="_blank">' + currentText.htmlEnc() + '</a>';
} }
@ -525,8 +527,9 @@ var vCard = (function () {
} }
// Profile editor popup // Profile editor popup
else if(type == 'user') else if(type == 'user') {
$(path_vcard + ' #USER-' + tokenname).val(currentText); $(path_vcard + ' #USER-' + tokenname).val(currentText);
}
// Avoid duplicating the value // Avoid duplicating the value
values_yet.push(tokenname); values_yet.push(tokenname);
@ -556,9 +559,7 @@ var vCard = (function () {
aBinval = $('#USER-PHOTO-BINVAL').val(); aBinval = $('#USER-PHOTO-BINVAL').val();
aType = $('#USER-PHOTO-TYPE').val(); aType = $('#USER-PHOTO-TYPE').val();
aContainer = path_vcard + ' .avatar-container'; aContainer = path_vcard + ' .avatar-container';
} } else {
else {
aBinval = $(iqNode).find('BINVAL:first').text(); aBinval = $(iqNode).find('BINVAL:first').text();
aType = $(iqNode).find('TYPE:first').text(); aType = $(iqNode).find('TYPE:first').text();
aContainer = path_userInfos + ' .avatar-container'; aContainer = path_userInfos + ' .avatar-container';
@ -578,8 +579,10 @@ var vCard = (function () {
$(path_vcard + ' .avatar').remove(); $(path_vcard + ' .avatar').remove();
} }
var avatar_src = ('data:' + aType + ';base64,' + aBinval);
// We display the avatar we have just received // 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') { else if(type == 'buddy') {
@ -668,10 +671,11 @@ var vCard = (function () {
var tagname = Common.explodeThis('-', item_id, 0); var tagname = Common.explodeThis('-', item_id, 0);
var cur_node; var cur_node;
if(node.getElementsByTagName(tagname).length > 0) if(node.getElementsByTagName(tagname).length > 0) {
cur_node = node.getElementsByTagName(tagname).item(0); cur_node = node.getElementsByTagName(tagname).item(0);
else } else {
cur_node = node.appendChild(stanza.buildNode(tagname, {'xmlns': namespace})); cur_node = node.appendChild(stanza.buildNode(tagname, {'xmlns': namespace}));
}
cur_node.appendChild( cur_node.appendChild(
stanza.buildNode( stanza.buildNode(
@ -874,18 +878,22 @@ var vCard = (function () {
// Keyboard events // Keyboard events
$('#vcard input[type="text"]').keyup(function(e) { $('#vcard input[type="text"]').keyup(function(e) {
// Enter pressed: send the vCard // 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(); return self.send();
}
}); });
// Click events // Click events
$('#vcard .tab a').click(function() { $('#vcard .tab a').click(function() {
var this_sel = $(this);
// Yet active? // Yet active?
if($(this).hasClass('tab-active')) if(this_sel.hasClass('tab-active')) {
return false; return false;
}
// Switch to the good tab // Switch to the good tab
var key = parseInt($(this).attr('data-key')); var key = parseInt(this_sel.attr('data-key'));
return self.switchTab(key); return self.switchTab(key);
}); });
@ -895,10 +903,15 @@ var vCard = (function () {
}); });
$('#vcard .bottom .finish').click(function() { $('#vcard .bottom .finish').click(function() {
if($(this).is('.cancel')) var this_sel = $(this);
if(this_sel.is('.cancel')) {
return self.close(); return self.close();
if($(this).is('.save') && !$(this).hasClass('disabled')) }
if(this_sel.is('.save') && !this_sel.hasClass('disabled')) {
return self.send(); return self.send();
}
return false; return false;
}); });
@ -912,16 +925,22 @@ var vCard = (function () {
// Avatar upload form submit event // Avatar upload form submit event
$('#vcard-avatar').submit(function() { $('#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); $(this).ajaxSubmit(avatar_options);
}
return false; return false;
}); });
// Avatar upload input change event // Avatar upload input change event
$('#vcard-avatar input[type="file"]').change(function() { $('#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); $('#vcard-avatar').ajaxSubmit(avatar_options);
}
return false; return false;
}); });

View file

@ -203,6 +203,7 @@ var Welcome = (function () {
// Update the "save" button if all is okay // Update the "save" button if all is okay
if(!Common.exists(tab + '.tab-missing')) { if(!Common.exists(tab + '.tab-missing')) {
var finish = welcome + '.finish.'; var finish = welcome + '.finish.';
$(finish + 'save').show(); $(finish + 'save').show();
$(finish + 'next').hide(); $(finish + 'next').hide();
} }
@ -280,19 +281,22 @@ var Welcome = (function () {
$('#welcome a.box').each(function() { $('#welcome a.box').each(function() {
var current = '0'; var current = '0';
if($(this).hasClass('enabled')) if($(this).hasClass('enabled')) {
current = '1'; current = '1';
}
array.push(current); array.push(current);
}); });
// If XMPP links is enabled // If XMPP links is enabled
if(array[2] == '1') if(array[2] == '1') {
Utils.xmppLinksHandler(); Utils.xmppLinksHandler();
}
// If offline buddies showing is enabled // If offline buddies showing is enabled
if(array[4] == '1') if(array[4] == '1') {
Interface.showAllBuddies('welcome'); Interface.showAllBuddies('welcome');
}
// If archiving is supported by the server // If archiving is supported by the server
if(Features.enabledMAM()) { if(Features.enabledMAM()) {
@ -336,8 +340,9 @@ var Welcome = (function () {
var next = 1; var next = 1;
var missing = '#welcome .tab a.tab-missing'; var missing = '#welcome .tab a.tab-missing';
if(Common.exists(missing)) if(Common.exists(missing)) {
next = parseInt($(missing + ':first').attr('data-step')); next = parseInt($(missing + ':first').attr('data-step'));
}
// Switch to the next step // Switch to the next step
self.switchTab(next); self.switchTab(next);
@ -360,26 +365,36 @@ var Welcome = (function () {
try { try {
// Click events // Click events
$('#welcome .tab a').click(function() { $('#welcome .tab a').click(function() {
var this_sel = $(this);
// Switch to the good tab // Switch to the good tab
var key = parseInt($(this).attr('data-step')); var key = parseInt(this_sel.attr('data-step'));
return self.switchTab(key); return self.switchTab(key);
}); });
$('#welcome a.box:not(.share)').click(function() { $('#welcome a.box:not(.share)').click(function() {
if($(this).hasClass('enabled')) var this_sel = $(this);
$(this).removeClass('enabled').attr('title', Common._e("Click to enable"));
else if(this_sel.hasClass('enabled')) {
$(this).addClass('enabled').attr('title', Common._e("Click to disable")); 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; return false;
}); });
$('#welcome .bottom .finish').click(function() { $('#welcome .bottom .finish').click(function() {
if($(this).is('.next')) var this_sel = $(this);
if(this_sel.is('.next')) {
return self.next(); return self.next();
if($(this).is('.save')) }
if(this_sel.is('.save')) {
return self.save(); return self.save();
}
return false; return false;
}); });

View file

@ -35,11 +35,9 @@ var XMPPLinks = (function () {
link = Common.explodeThis(':', link, 1); link = Common.explodeThis(':', link, 1);
// The XMPP URI has no "?" // The XMPP URI has no "?"
if(link.indexOf('?') == -1) if(link.indexOf('?') == -1) {
Chat.checkCreate(link, 'chat'); Chat.checkCreate(link, 'chat');
} else {
// Parse the URI
else {
var xid = Common.explodeThis('?', link, 0); var xid = Common.explodeThis('?', link, 0);
var action = Common.explodeThis('?', link, 1); var action = Common.explodeThis('?', link, 1);
@ -88,11 +86,13 @@ var XMPPLinks = (function () {
* Gets the links vars (get parameters in URL) * Gets the links vars (get parameters in URL)
*/ */
self.links_var = (function() { self.links_var = (function() {
var hash;
var vars = []; var vars = [];
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&'); var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for(var i = 0; i < hashes.length; i++) { for(var i = 0; i < hashes.length; i++) {
var hash = hashes[i].split('='); hash = hashes[i].split('=');
vars.push(hash[0]); vars.push(hash[0]);
vars[hash[0]] = $.trim(decodeURIComponent(hash[1])); vars[hash[0]] = $.trim(decodeURIComponent(hash[1]));
} }

Binary file not shown.

Binary file not shown.

View 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%;
}

View file

@ -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-gradient(linear, left top, left bottom, from(#e4eef9), to(#c5e1ff));
background: -webkit-linear-gradient(top, #e4eef9 0%, #c5e1ff 100%); background: -webkit-linear-gradient(top, #e4eef9 0%, #c5e1ff 100%);
background: -o-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; position: absolute;
top: 0; top: 0;
bottom: 0; bottom: 0;
@ -693,6 +694,22 @@ html[dir="rtl"] #home .right .navigation a {
left: 10px; 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 { #home .friendsview .friends a.group.refer {
width: 81px; width: 81px;
padding-left: 10px; padding-left: 10px;

View file

@ -56,8 +56,8 @@ Author: Valérian Saliou
background-repeat: no-repeat; background-repeat: no-repeat;
} }
.jingle-images { .call-images {
background-image: url(../images/sprites/jingle.png); background-image: url(../images/sprites/call.png);
background-repeat: no-repeat; background-repeat: no-repeat;
} }

View file

@ -1,7 +1,7 @@
/* /*
Jappix - An open social platform 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 { #jingle .videobox .topbar .card {
margin: 4px 0 0 12px; margin: 4px 0 0 12px;
} }
@ -62,17 +21,13 @@ html[dir="rtl"] #jingle .videobox .topbar .card {
#jingle .videobox .topbar .card, #jingle .videobox .topbar .card,
#jingle .videobox .topbar .card .avatar-container, #jingle .videobox .topbar .card .avatar-container,
#jingle .videobox .topbar .card .identity, #jingle .videobox .topbar .card .identity {
#jingle .videobox .topbar .controls,
#jingle .videobox .topbar .elapsed {
float: left; float: left;
} }
html[dir="rtl"] #jingle .videobox .topbar .card, html[dir="rtl"] #jingle .videobox .topbar .card,
html[dir="rtl"] #jingle .videobox .topbar .card .avatar-container, html[dir="rtl"] #jingle .videobox .topbar .card .avatar-container,
html[dir="rtl"] #jingle .videobox .topbar .card .identity, html[dir="rtl"] #jingle .videobox .topbar .card .identity {
html[dir="rtl"] #jingle .videobox .topbar .controls,
html[dir="rtl"] #jingle .videobox .topbar .elapsed {
float: right; float: right;
} }
@ -115,192 +70,8 @@ html[dir="rtl"] #jingle .videobox .topbar .card .identity {
margin-left: 50px; 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 { #jingle .videobox .remote_video {
background-color: #000000;
width: 100%; width: 100%;
height: 100%; height: 100%;
position: absolute; position: absolute;
@ -311,6 +82,11 @@ html[dir="rtl"] #jingle .videobox .local_video {
z-index: 1; z-index: 1;
} }
#jingle .videobox .remote_video video {
width: 100%;
height: 100%;
}
#jingle .videobox .branding { #jingle .videobox .branding {
background-position: 0 0; background-position: 0 0;
width: 39px; width: 39px;

View file

@ -114,6 +114,19 @@ input[type="radio"] {
border: 0 none !important; 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,
.please-complete:hover, .please-complete:hover,
.please-complete:focus { .please-complete:focus {
@ -129,4 +142,5 @@ input[type="radio"] {
.clear { .clear {
clear: both !important; clear: both !important;
display: block !important;
} }

View file

@ -143,7 +143,7 @@ a {
} }
#talk a.one-buddy { #talk a.one-buddy {
display: none; display: block;
background-color: #87a5ab; background-color: #87a5ab;
border-bottom: 1px solid #5b8088; border-bottom: 1px solid #5b8088;
text-shadow: 1px 1px 1px #5b8088; text-shadow: 1px 1px 1px #5b8088;
@ -154,6 +154,7 @@ a {
} }
#talk a.one-buddy:hover { #talk a.one-buddy:hover {
background-color: #8fb0b7;
cursor: pointer; cursor: pointer;
} }
@ -248,7 +249,7 @@ a {
border-bottom: 1px solid #cbcbcb; border-bottom: 1px solid #cbcbcb;
top: 23px; top: 23px;
left: 0; left: 0;
bottom: 25px; bottom: 37px;
overflow: auto; overflow: auto;
text-align: left; text-align: left;
} }

View 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%;
}

View file

@ -108,7 +108,8 @@ html[dir="rtl"] .general-wait-content {
.mam-hidable, .mam-hidable,
.commands-hidable, .commands-hidable,
.privacy-hidable, .privacy-hidable,
.xmpplinks-hidable { .xmpplinks-hidable,
.muji-hidable {
display: none; display: none;
} }

View file

@ -327,6 +327,93 @@ html[dir="rtl"] #page-engine .list .user .user-details .avatar-container {
margin-bottom: 10px; 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-line,
#page-engine .one-group b.name { #page-engine .one-group b.name {
padding-left: 50px; padding-left: 50px;
@ -339,6 +426,10 @@ html[dir="rtl"] #page-engine .one-group b.name {
padding-right: 50px; padding-right: 50px;
} }
#page-engine .one-line.correction-active {
opacity: 0.5;
}
#page-engine .one-group b.name { #page-engine .one-group b.name {
display: block; display: block;
margin-bottom: 4px; 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-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; opacity: 0.35;
cursor: default; cursor: default;
} }
@ -834,22 +927,67 @@ body.in_jingle_call #page-engine .text .tools-jingle-audio {
} }
#page-engine .text .compose, #page-engine .text .compose,
#page-engine .muc-ask { #page-engine .muc-ask,
#page-engine .correction-toolbox {
position: absolute; position: absolute;
left: 0; left: 0;
} }
#page-engine .text .compose { #page-engine .text .compose,
#page-engine .correction-toolbox {
top: 29px; top: 29px;
right: 12px;
bottom: 12px; bottom: 12px;
} }
#page-engine .text .compose {
right: 12px;
}
html[dir="rtl"] #page-engine .text .compose { html[dir="rtl"] #page-engine .text .compose {
right: 0; right: 0;
left: 12px; 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 { #page-engine .muc-ask {
right: 0; right: 0;
bottom: 0; bottom: 0;
@ -872,6 +1010,21 @@ html[dir="rtl"] #page-engine .text .compose {
border-top-left-radius: 0; 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 { #page-engine .muc-ask {
background-color: #e8f1f3; background-color: #e8f1f3;
height: 64px; height: 64px;

View file

@ -356,7 +356,10 @@ html[dir="rtl"] .manage-infos p.bm-group input {
background-position: 1px -2047px; 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; opacity: 0.35;
} }
@ -367,7 +370,10 @@ body.in_jingle_call .call-jingle {
display: none; 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; cursor: default;
} }
@ -455,7 +461,7 @@ html[dir="rtl"] #roster .roster-icon {
width: 16px; width: 16px;
display: block; display: block;
} }
#roster .add, #roster .add,
#page-engine .text .tools-add { #page-engine .text .tools-add {
background-position: 0 -1047px; background-position: 0 -1047px;
@ -469,7 +475,11 @@ html[dir="rtl"] #roster .roster-icon {
#page-switch .groupchat-default { #page-switch .groupchat-default {
background-position: 0 -1082px; background-position: 0 -1082px;
} }
#roster .muji {
background-position: 0 -2047px;
}
#roster .more { #roster .more {
background-position: 0 -1100px; background-position: 0 -1100px;
} }
@ -520,7 +530,15 @@ html[dir="rtl"] .buddy-conf-subarrow {
margin-right: 9px; margin-right: 9px;
float: right; 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 { .buddy-conf-subitem {
background-color: rgb(0,0,0); background-color: rgb(0,0,0);
background-color: rgba(0,0,0,0.8); background-color: rgba(0,0,0,0.8);

View file

@ -61,46 +61,51 @@ html[dir="rtl"] #top-content .tools-all {
float: left; float: left;
} }
#top-content .jingle { #top-content .call {
background-position: 7px -2114px; background-position: 7px -2114px;
display: none; display: none;
} }
#top-content .jingle.video { #top-content .call .notify {
margin-left: 0;
left: -2px;
}
#top-content .call.video {
background-position: 7px -2205px; background-position: 7px -2205px;
} }
#top-content .jingle.active, #top-content .call.active,
#top-content .jingle.streaming { #top-content .call.streaming {
display: block; display: block;
} }
#top-content .jingle.active { #top-content .call.active {
-webkit-animation: tool_active 1.5s infinite ease-in-out; -webkit-animation: tool_active 1.5s infinite ease-in-out;
-moz-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; -o-animation: tool_active 1.5s infinite ease-in-out;
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; padding-left: 30px;
} }
#top-content .jingle .streaming-items { #top-content .call .streaming-items {
display: none; display: none;
} }
#top-content .jingle.streaming .streaming-items { #top-content .call.streaming .streaming-items {
display: block; display: block;
} }
#top-content .jingle.streaming .streaming-items .counter { #top-content .call.streaming .streaming-items .counter {
font-size: 11px; font-size: 11px;
font-style: italic; font-style: italic;
font-weight: bold; font-weight: bold;
} }
#top-content .jingle.streaming .streaming-items a.stop { #top-content .call.streaming .streaming-items a.stop {
background: #cc283f; background: #cc283f;
border-left: 1px solid #a12032; border-left: 1px solid #a12032;
color: #ffffff; color: #ffffff;
@ -116,7 +121,7 @@ html[dir="rtl"] #top-content .tools-all {
border-bottom-right-radius: 4px; 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; background: #a92134;
padding-top: 6px; padding-top: 6px;
padding-bottom: 6px; padding-bottom: 6px;
@ -135,23 +140,27 @@ html[dir="rtl"] #top-content .tools-all {
#top-content .notifications:hover, #top-content .notifications:hover,
#top-content .music: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; cursor: pointer;
} }
#top-content .music:hover, #top-content .music:hover,
#top-content .notifications: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 .music:focus,
#top-content .notifications: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: rgb(232,241,243);
background-color: rgba(232,241,243,0.7); background-color: rgba(232,241,243,0.7);
} }
#top-content .music:active, #top-content .music:active,
#top-content .notifications: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: rgb(232,241,243);
background-color: rgba(232,241,243,0.8); background-color: rgba(232,241,243,0.8);
} }
@ -485,25 +494,25 @@ html[dir="rtl"] .music-content .list {
height: 15px; height: 15px;
} }
.jingle-content { .call-content {
text-shadow: none; text-shadow: none;
width: 230px; width: 230px;
right: -102px; right: -102px;
} }
html[dir="rtl"] .jingle-content { html[dir="rtl"] .call-content {
left: -102px; left: -102px;
} }
.jingle-content .tools-content-subitem { .call-content .tools-content-subitem {
position: relative; position: relative;
} }
.jingle-content .jingle-notify { .call-content .call-notify {
height: 90px; height: 90px;
} }
.jingle-content .jingle-notify .avatar-pane { .call-content .call-notify .avatar-pane {
width: 100px; width: 100px;
position: absolute; position: absolute;
left: 0; left: 0;
@ -517,12 +526,12 @@ html[dir="rtl"] .jingle-content {
border-top-left-radius: 4px; 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; left: auto;
right: 0; right: 0;
} }
.jingle-content .jingle-notify .avatar-pane .avatar-container { .call-content .call-notify .avatar-pane .avatar-container {
overflow: hidden; overflow: hidden;
position: absolute; position: absolute;
left: 0; left: 0;
@ -531,7 +540,7 @@ html[dir="rtl"] .jingle-content .jingle-notify .avatar-pane {
top: 0; top: 0;
} }
.jingle-content .jingle-notify .avatar-pane .avatar-container .avatar { .call-content .call-notify .avatar-pane .avatar-container .avatar {
min-height: 100%; min-height: 100%;
max-height: 100%; max-height: 100%;
min-width: 100%; min-width: 100%;
@ -543,7 +552,7 @@ html[dir="rtl"] .jingle-content .jingle-notify .avatar-pane {
border-bottom-left-radius: 5px; 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; -moz-border-radius: 0;
-webkit-border-radius: 0; -webkit-border-radius: 0;
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; border-bottom-right-radius: 5px;
} }
.jingle-content .jingle-notify .avatar-pane .icon { .call-content .call-notify .avatar-pane .icon {
opacity: 0.75; opacity: 0.75;
position: absolute; position: absolute;
left: 8px; left: 8px;
bottom: 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; background-position: 0 -120px;
width: 33px; width: 33px;
height: 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; background-position: 0 -154px;
width: 33px; width: 33px;
height: 22px; height: 22px;
} }
.jingle-content .jingle-notify.notify-connecting .avatar-pane .icon { .call-content .call-notify.notify-connecting .avatar-pane .icon {
background-position: 0 -175px; background-position: 0 -175px;
width: 33px; width: 33px;
height: 32px; height: 32px;
} }
.jingle-content .jingle-notify.notify-error .avatar-pane .icon { .call-content .call-notify.notify-error .avatar-pane .icon {
background-position: 0 -207px; background-position: 0 -207px;
width: 33px; width: 33px;
height: 31px; height: 31px;
} }
.jingle-content .jingle-notify.notify-local_ended .avatar-pane .icon, .call-content .call-notify.notify-local_ended .avatar-pane .icon,
.jingle-content .jingle-notify.notify-remote_ended .avatar-pane .icon { .call-content .call-notify.notify-remote_ended .avatar-pane .icon {
background-position: 0 -238px; background-position: 0 -238px;
width: 33px; width: 33px;
height: 34px; height: 34px;
} }
.jingle-content .jingle-notify .notification-content { .call-content .call-notify .notification-content {
color: #ffffff; color: #ffffff;
text-align: left; text-align: left;
text-shadow: 0 1px 1px rgb(0,0,0); 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; left: 100px;
} }
html[dir="rtl"] .jingle-content .jingle-notify .notification-content { html[dir="rtl"] .call-content .call-notify .notification-content {
text-align: right; text-align: right;
right: 100px; right: 100px;
left: 0; left: 0;
} }
.jingle-content .jingle-notify .notification-content .fullname, .call-content .call-notify .notification-content .fullname,
.jingle-content .jingle-notify .notification-content .text { .call-content .call-notify .notification-content .text {
display: block; display: block;
} }
.jingle-content .jingle-notify .notification-content .fullname { .call-content .call-notify .notification-content .fullname {
font-weight: bold; font-weight: bold;
} }
.jingle-content .jingle-notify .notification-content .text { .call-content .call-notify .notification-content .text {
font-size: 12px; font-size: 12px;
text-transform: lowercase; text-transform: lowercase;
margin-top: 2px; margin-top: 2px;
} }
.jingle-content .jingle-notify .notification-content .reply-buttons { .call-content .call-notify .notification-content .reply-buttons {
text-align: center; text-align: center;
padding-left: 10px; padding-left: 10px;
position: absolute; position: absolute;
@ -636,31 +645,31 @@ html[dir="rtl"] .jingle-content .jingle-notify .notification-content {
bottom: 20px; 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-left: 0;
padding-right: 10px; 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; margin-left: 4px;
float: left; 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-left: 0;
margin-right: 4px; margin-right: 4px;
float: right; 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; 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; 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; margin-right: 0;
} }

Some files were not shown because too many files have changed in this diff Show more