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.
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)
------------------------

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
# XMPP Extensions
# XMPP Extensions (Standardized)
* XEP-0045: Multi-User Chat *v1.25*
* XEP-0004: Data Forms *v2.9*
* XEP-0012: Last Activity *v2.0*
* XEP-0016: Privacy Lists *v1.6*
* XEP-0030: Service Discovery *v2.4*
* XEP-0045: Multi-User Chat *v1.25*
* XEP-0049: Private XML Storage *v1.2*
* XEP-0050: Ad-Hoc Commands *v1.2*
* XEP-0054: vcard-temp *v1.2*
* XEP-0055: Jabber Search *v1.3*
* XEP-0060: Publish-Subscribe *v1.13*
* XEP-0124: Bidirectional-streams Over Synchronous HTTP (BOSH) *v1.10*
* XEP-0115: Entity Capabilities *v1.5*
* XEP-0066: Out of Band Data *v1.5*
* XEP-0071: XHTML-IM *v1.5*
* XEP-0072: SOAP Over XMPP *v1.0*
* XEP-0077: In-Band Registration *v2.4*
* XEP-0080: User Location *v1.7*
* XEP-0084: User Avatar *v1.1*
* XEP-0085: Chat State Notifications *v2.1*
* XEP-0092: Software Version *v1.1*
* XEP-0107: User Mood *v1.2*
* XEP-0108: User Activity *v1.3*
* XEP-0115: Entity Capabilities *v1.5*
* XEP-0118: User Tune *v1.2*
* XEP-0080: User Location *v1.7*
* XEP-0172: User Nickname *v1.1*
* XEP-0084: User Avatar *v1.1*
* XEP-0277: Microblogging over XMPP *v0.6*
* XEP-xxxx: Notification Inbox *v0.1*
* Alternate URL: http://xmpp.org/extensions/inbox/notification-inbox.html
* XEP-0203: Delayed Delivery *v2.0*
* XEP-0124: Bidirectional-streams Over Synchronous HTTP (BOSH) *v1.10*
* XEP-0144: Roster Item Exchange *v1.0*
* XEP-0072: SOAP Over XMPP *v1.0*
* XEP-0085: Chat State Notifications *v2.1*
* XEP-0071: XHTML-IM *v1.5*
* XEP-0313: Message Archive Management *v0.3*
* Alternate URL: https://demo.frenchtouch.pro/valerian.saliou/xmpp/extensions/xep-0313.html
* XEP-0012: Last Activity *v2.0*
* XEP-0049: Private XML Storage *v1.2*
* XEP-0077: In-Band Registration *v2.4*
* XEP-0055: Jabber Search *v1.3*
* XEP-0050: Ad-Hoc Commands *v1.2*
* XEP-0092: Software Version *v1.1*
* XEP-0004: Data Forms *v2.9*
* XEP-0054: vcard-temp *v1.2*
* XEP-0202: Entity Time *v2.0*
* XEP-0199: XMPP Ping *v2.0*
* XEP-0184: Message Delivery Receipts *v1.2*
* XEP-0016: Privacy Lists *v1.6*
* XEP-0066: Out of Band Data *v1.5*
* XEP-0280: Message Carbons *v0.9*
* XEP-0292: vCard4 Over XMPP *v0.10*
* XEP-0152: Reachability Addresses *v1.0*
* XEP-0166: Jingle *v1.1*
* XEP-0167: Jingle RTP Sessions *v1.1*
* XEP-0172: User Nickname *v1.1*
* XEP-0176: Jingle ICE-UDP Transport Method *v1.0*
* XEP-0177: Jingle Raw UDP Transport Method *v1.1*
* XEP-0184: Message Delivery Receipts *v1.2*
* XEP-0199: XMPP Ping *v2.0*
* XEP-0202: Entity Time *v2.0*
* XEP-0203: Delayed Delivery *v2.0*
* XEP-0224: Attention *v1.0*
* XEP-0215: External Service Discovery *v0.5*
* XEP-0249: Direct MUC Invitations *v1.2*
* XEP-0262: Use of ZRTP in Jingle RTP Sessions *v1.0*
* XEP-0266: Codecs for Jingle Audio *v1.0*
* XEP-0269: Jingle Early Media *v0.1*
* XEP-0277: Microblogging over XMPP *v0.6*
* XEP-0278: Jingle Relay Nodes *v0.2*
* XEP-0280: Message Carbons *v0.9*
* XEP-0292: vCard4 Over XMPP *v0.10*
* XEP-0293: Jingle RTP Feedback Negotiation *v0.1*
* XEP-0294: Jingle RTP Header Extensions Negotiation *v0.1*
* XEP-0299: Codecs for Jingle Video *v0.1*
* XEP-0308: Last Message Correction *v1.0*
* XEP-0319: Last User Interaction in Presence *v0.2*
* XEP-0320: Use of DTLS-SRTP in Jingle Sessions *v0.2*
* XEP-0333: Chat Markers *v0.2*
* XEP-0334: Message Processing Hints *v0.1*
* XEP-0338: Jingle Grouping Framework *v0.1*
* XEP-0339: Source-Specific Media Attributes in Jingle *v0.1*
# XMPP Extensions (Updated)
* XEP-0272: Multiparty Jingle (Muji) *v0.2*
* Alternate URL: https://demo.frenchtouch.pro/valerian.saliou/xmpp/extensions/xep-0272.html
* XEP-0313: Message Archive Management *v0.3*
* Alternate URL: https://demo.frenchtouch.pro/valerian.saliou/xmpp/extensions/xep-0313.html
# XMPP Extensions (Proposed)
* XEP-xxxx: Notification Inbox *v0.1*
* Alternate URL: http://xmpp.org/extensions/inbox/notification-inbox.html
# Others

View file

@ -32,9 +32,9 @@ Start translating on https://www.transifex.com/projects/p/jappix/ (new translato
Links
-----
* Jappix project website: http://jappix.org/
* Jappix project website: https://jappix.org/
* Jappix project dev panel: https://github.com/jappix/jappix
* Jappix nodes list: http://jappix.net/
* Jappix nodes list: https://jappix.net/
* Jappix main service: https://jappix.com/
* Jappix commercial support: https://jappix.pro/

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" ?>
<jappix xmlns="jappix:file:get">
<css>fonts.css~main.css~images.css~board.css~home.css~others.css~tools.css~roster.css~myinfos.css~pageengine.css~channel.css~pageswitch.css~smileys.css~popup.css~vcard.css~options.css~favorites.css~discovery.css~directory.css~adhoc.css~privacy.css~inbox.css~mucadmin.css~integratebox.css~userinfos.css~search.css~welcome.css~me.css~rosterx.css~jingle.css</css>
<js>origin.js~jxhr.js~datejs.js~jquery.js~jquery.ui.js~jquery.json.js~jquery.form.js~jquery.timers.js~jquery.placeholder.js~jquery.textrange.js~base64.js~jsjac.js~jsjac.jingle.js~system.js~constants.js~datastore.js~browser-detect.js~home.js~talk.js~popup.js~audio.js~board.js~bubble.js~chat.js~groupchat.js~smileys.js~oob.js~avatar.js~mucadmin.js~connection.js~dataform.js~discovery.js~directory.js~adhoc.js~privacy.js~errors.js~name.js~favorites.js~features.js~interface.js~xmpplinks.js~iq.js~message.js~chatstate.js~receipts.js~tooltip.js~filter.js~links.js~inbox.js~microblog.js~music.js~notification.js~httpreply.js~options.js~integratebox.js~pubsub.js~pep.js~presence.js~roster.js~jingle.js~storage.js~console.js~common.js~utilities.js~date.js~caps.js~vcard.js~userinfos.js~search.js~autocompletion.js~welcome.js~me.js~rosterx.js~mam.js~carbons.js</js>
<css>fonts.css~main.css~images.css~board.css~home.css~others.css~tools.css~roster.css~myinfos.css~pageengine.css~channel.css~pageswitch.css~smileys.css~popup.css~vcard.css~options.css~favorites.css~discovery.css~directory.css~adhoc.css~privacy.css~inbox.css~mucadmin.css~integratebox.css~userinfos.css~search.css~welcome.css~me.css~rosterx.css~call.css~jingle.css~muji.css</css>
<js>origin.js~jxhr.js~datejs.js~jquery.js~jquery.ui.js~jquery.json.js~jquery.form.js~jquery.timers.js~jquery.placeholder.js~jquery.textrange.js~jquery.scrollto.js~base64.js~jsjac.js~jsjac.jingle.js~system.js~constants.js~datastore.js~browser-detect.js~home.js~talk.js~popup.js~audio.js~board.js~bubble.js~chat.js~groupchat.js~smileys.js~oob.js~avatar.js~mucadmin.js~connection.js~dataform.js~discovery.js~directory.js~adhoc.js~privacy.js~errors.js~name.js~favorites.js~features.js~interface.js~xmpplinks.js~iq.js~message.js~chatstate.js~receipts.js~tooltip.js~filter.js~links.js~inbox.js~microblog.js~music.js~notification.js~httpreply.js~options.js~integratebox.js~pubsub.js~pep.js~presence.js~roster.js~call.js~jingle.js~muji.js~storage.js~console.js~common.js~utilities.js~date.js~caps.js~vcard.js~userinfos.js~search.js~autocompletion.js~welcome.js~me.js~rosterx.js~mam.js~carbons.js~correction.js~markers.js~attention.js</js>
</jappix>

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 {
// Click event
$('#adhoc .bottom .finish').click(
self.close()
);
$('#adhoc .bottom .finish').click(self.close);
} catch(e) {
Console.error('AdHoc.launch', e);
}

View file

@ -20,6 +20,28 @@ var Anonymous = (function () {
var self = {};
/**
* Registers connection handlers
* @private
* @param {object} con
* @return {undefined}
*/
self._registerHandlers = function(con) {
try {
con.registerHandler('message', Message.handle);
con.registerHandler('presence', Presence.handle);
con.registerHandler('iq', IQ.handle);
con.registerHandler('onconnect', self.connected);
con.registerHandler('onerror', Errors.handle);
con.registerHandler('ondisconnect', self.disconnected);
} catch(e) {
Console.error('Anonymous._registerHandlers', e);
}
};
/**
* Connected to an anonymous session
* @public
@ -115,12 +137,7 @@ var Anonymous = (function () {
}
// And we handle everything that happen
con.registerHandler('message', Message.handle);
con.registerHandler('presence', Presence.handle);
con.registerHandler('iq', IQ.handle);
con.registerHandler('onconnect', self.connected);
con.registerHandler('onerror', Errors.handle);
con.registerHandler('ondisconnect', self.disconnected);
self._registerHandlers(con);
// We set the anonymous connection parameters
oArgs = {};
@ -165,10 +182,13 @@ var Anonymous = (function () {
Interface.showGeneralWait();
// Get the vars
if(XMPPLinks.links_var.r)
if(XMPPLinks.links_var.r) {
ANONYMOUS_ROOM = XMPPLinks.links_var.r;
if(XMPPLinks.links_var.n)
}
if(XMPPLinks.links_var.n) {
ANONYMOUS_NICK = XMPPLinks.links_var.n;
}
// Fire the login action
self.login(HOST_ANONYMOUS);

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
* @return {boolean}
*/
self._is_supported = function() {
self._isSupported = function() {
is_supported = true;
@ -38,7 +38,7 @@ var Audio = (function () {
is_supported = false;
}
} catch(e) {
Console.error('Audio._is_supported', e);
Console.error('Audio._isSupported', e);
} finally {
return is_supported;
}
@ -47,23 +47,13 @@ var Audio = (function () {
/**
* Plays the given sound ID
* @public
* @param {string} name
* @return {boolean}
* Append audio DOM code
* @private
* @return {undefined}
*/
self.play = function(name, repeat) {
self._appendDOM = function() {
try {
repeat = (typeof repeat === 'boolean') ? repeat : false;
// Not supported?
if(!self._is_supported()) {
return false;
}
// If the sounds are enabled
if(DataStore.getDB(Connection.desktop_hash, 'options', 'sounds') === '1') {
// If the audio elements aren't yet in the DOM
if(!Common.exists('#audio')) {
$('body').append(
@ -83,6 +73,11 @@ var Audio = (function () {
'<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' + '" />' +
@ -95,6 +90,32 @@ var Audio = (function () {
'</div>'
);
}
} catch(e) {
Console.error('Audio._appendDOM', e);
}
};
/**
* Plays the given sound ID
* @public
* @param {string} name
* @return {boolean}
*/
self.play = function(name, repeat) {
try {
repeat = (typeof repeat === 'boolean') ? repeat : false;
// Not supported?
if(!self._isSupported()) {
return false;
}
// If the sounds are enabled
if(DataStore.getDB(Connection.desktop_hash, 'options', 'sounds') === '1') {
self._appendDOM();
// We play the target sound
var audio_raw_sel = $('#audio audio').filter('#' + name);
@ -146,7 +167,7 @@ var Audio = (function () {
try {
// Not supported?
if(!self._is_supported()) {
if(!self._isSupported()) {
return false;
}

View file

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

View file

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

View file

@ -20,21 +20,21 @@ var Board = (function () {
var self = {};
/* Contants */
self.NOTIFICATION = (window.Notification || window.mozNotification || window.webkitNotification);
/**
* Creates a board panel
* @public
* @param {string} type
* Generate board info message
* @private
* @param {string} id
* @return {boolean}
* @return {string}
*/
self.create = function(type, id) {
self._generateBoardInfo = function(id) {
var text = null;
try {
// Text var
var text = '';
// Info
if(type == 'info') {
switch(id) {
// Password change
case 1:
@ -72,10 +72,26 @@ var Board = (function () {
break;
}
} catch(e) {
Console.error('Board._generateBoardInfo', e);
} finally {
return text;
}
// Error
else {
};
/**
* Generate board error message
* @private
* @param {string} id
* @return {string}
*/
self._generateBoardError = function(id) {
var text = null;
try {
switch(id) {
// Custom error
case 1:
@ -101,27 +117,74 @@ var Board = (function () {
break;
}
} catch(e) {
Console.error('Board._generateBoardError', e);
} finally {
return text;
}
};
/**
* Attaches board events
* @private
* @param {object} board_sel
* @return {undefined}
*/
self._attachEvents = function(board_sel) {
try {
board_sel.click(function() {
self.closeThis(this);
});
board_sel.oneTime('5s', function() {
self.closeThis(this);
});
board_sel.slideDown();
} catch(e) {
Console.error('Board._attachEvents', e);
}
};
/**
* Creates a board panel
* @public
* @param {string} type
* @param {string} id
* @return {boolean}
*/
self.create = function(type, id) {
try {
// Text var
var text = '';
// Info
if(type == 'info') {
text = self._generateBoardInfo(id);
} else {
text = self._generateBoardError(id);
}
// No text?
if(!text)
if(!text) {
return false;
}
// Append the content
$('#board').append('<div class="one-board ' + type + '" data-id="' + id + '">' + text + '</div>');
$('#board').append(
'<div class="one-board ' + type + '" data-id="' + id + '">' + text + '</div>'
);
// Events (click and auto-hide)
self._attachEvents(
$('#board .one-board.' + type + '[data-id="' + id + '"]')
.click(function() {
self.closeThis(this);
})
.oneTime('5s', function() {
self.closeThis(this);
})
.slideDown();
);
return true;
} catch(e) {
@ -235,7 +298,7 @@ var Board = (function () {
try {
// Cannot process?
if(Common.isFocused() || !content || !(window.webkitNotifications || window.Notification)) {
if(Common.isFocused() || !content || !self.NOTIFICATION) {
return;
}
@ -248,21 +311,32 @@ var Board = (function () {
var avatar_xml = Common.XMLFromString(
DataStore.getPersistent('global', 'avatar', xid)
);
var avatar_type = $(avatar_xml).find('type').text() || 'image/png';
var avatar_binval = $(avatar_xml).find('binval').text();
if(avatar_binval && avatar_type)
if(avatar_binval && avatar_type) {
icon = 'data:' + avatar_type + ';base64,' + avatar_binval;
}
}
}
// Default title?
if(!title) {
title = Common._e("New event!");
}
// Click callback
var cb_click_fn = function() {
// Create notification
var notification = new self.NOTIFICATION(title, {
dir: 'auto',
lang: '',
body: content,
tag: type,
icon: icon
});
// Click event
notification.onclick = function() {
// Click action?
switch(type) {
case 'chat':
@ -281,53 +355,17 @@ var Board = (function () {
window.focus();
// Remove notification
this.cancel();
this.close();
};
// Check for notification permission
try {
if(Notification.permission == 'granted' || Notification.permission === undefined) {
var notification = new Notification(title, {
dir: 'auto',
lang: '',
body: content,
tag: type,
icon: icon
});
notification.onclick = cb_click_fn;
// Show event
notification.onshow = function() {
setTimeout(function() {
notification.close();
}, 10000);
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) {
Console.error('Board.quick', e);
}
@ -343,21 +381,7 @@ var Board = (function () {
self.quickPermission = function() {
try {
try {
// W3C Notification API (still a draft!)
if(Notification.permission !== 'granted') {
// Ask for permission
Notification.requestPermission();
}
} catch (_e) {
// WebKit Notification API (fallback)
if(!window.webkitNotifications || (window.webkitNotifications.checkPermission() === 0)) {
return;
}
// Ask for permission
window.webkitNotifications.requestPermission();
}
self.NOTIFICATION.requestPermission();
} catch(e) {
Console.error('Board.quickPermission', e);
}
@ -376,8 +400,9 @@ var Board = (function () {
// Fires quickPermission() on document click
$(document).click(function() {
// Ask for permission to use quick boards
if((typeof con != 'undefined') && con.connected())
if((typeof con != 'undefined') && con.connected()) {
self.quickPermission();
}
});
} catch(e) {
Console.error('Board.launch', e);

View file

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

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,34 +20,15 @@ var Caps = (function () {
var self = {};
/**
* Reads a stored Caps
* @public
* @param {string} caps
* @return {object}
*/
self.read = function(caps) {
/* Constants */
self.disco_infos = {
'identity': {
'category': 'client',
'type': 'web',
'name': 'Jappix'
},
try {
return Common.XMLFromString(
DataStore.getPersistent('global', 'caps', caps)
);
} catch(e) {
Console.error('Caps.read', e);
}
};
/**
* Returns an array of the Jappix disco#infos
* @public
* @return {object}
*/
self.myDiscoInfos = function() {
try {
var disco_base = [
'items': [
NS_MUC,
NS_MUC_USER,
NS_MUC_ADMIN,
@ -96,13 +77,420 @@ var Caps = (function () {
NS_PRIVACY,
NS_IQOOB,
NS_XOOB,
NS_URN_CARBONS
];
NS_URN_CARBONS,
NS_URN_CORRECT,
NS_URN_MARKERS,
NS_URN_IDLE,
NS_URN_ATTENTION,
NS_URN_REACH,
NS_URN_HINTS
]
};
var disco_jingle = JSJaCJingle_disco();
/**
* Parse identities from disco infos query response
* @private
* @param {object} query
* @return {object}
*/
self._parseDiscoIdentities = function(query) {
var identities = [];
try {
var cur_category, cur_type, cur_lang, cur_name;
$(query).find('identity').each(function() {
cur_category = $(this).attr('category') || '';
cur_type = $(this).attr('type') || '';
cur_lang = $(this).attr('xml:lang') || '';
cur_name = $(this).attr('name') || '';
identities.push(cur_category + '/' + cur_type + '/' + cur_lang + '/' + cur_name);
});
} catch(e) {
Console.error('Caps._parseDiscoIdentities', e);
} finally {
return identities;
}
};
/**
* Parse features from disco infos query response
* @private
* @param {object} query
* @return {object}
*/
self._parseDiscoFeatures = function(query) {
var features = [];
try {
var cur_var;
$(query).find('feature').each(function() {
cur_var = $(this).attr('var');
// Add the current value to the array
if(cur_var) {
features.push(cur_var);
}
});
} catch(e) {
Console.error('Caps._parseDiscoFatures', e);
} finally {
return features;
}
};
/**
* Parse data form from disco infos query response
* @private
* @param {object} query
* @return {object}
*/
self._parseDiscoDataForms = function(query) {
var data_forms = [];
try {
var cur_string, cur_sort_var,
cur_text, cur_var, cur_sort_val;
$(query).find('x[xmlns="' + NS_XDATA + '"]').each(function() {
// Initialize some stuffs
cur_string = '';
cur_sort_var = [];
// Add the form type field
$(this).find('field[var="FORM_TYPE"] value').each(function() {
cur_text = $(this).text();
if(cur_text) {
cur_string += cur_text + '<';
}
});
// Add the var attributes into an array
$(this).find('field:not([var="FORM_TYPE"])').each(function() {
cur_var = $(this).attr('var');
if(cur_var) {
cur_sort_var.push(cur_var);
}
});
// Sort the var attributes
cur_sort_var = cur_sort_var.sort();
// Loop this sorted var attributes
$.each(cur_sort_var, function(i) {
// Initialize the value sorting
cur_sort_val = [];
// Append it to the string
cur_string += cur_sort_var[i] + '<';
// Add each value to the array
$(this).find('field[var=' + cur_sort_var[i] + '] value').each(function() {
cur_sort_val.push($(this).text());
});
// Sort the values
cur_sort_val = cur_sort_val.sort();
// Append the values to the string
for(var j in cur_sort_val) {
cur_string += cur_sort_val[j] + '<';
}
});
// Any string?
if(cur_string) {
// Remove the undesired double '<' from the string
if(cur_string.match(/(.+)(<)+$/)) {
cur_string = cur_string.substring(0, cur_string.length - 1);
}
// Add the current string to the array
data_forms.push(cur_string);
}
});
} catch(e) {
Console.error('Caps._parseDiscoDataForms', e);
} finally {
return data_forms;
}
};
/**
* Apply XHTML-IM features from disco infos
* @private
* @param {string} xid
* @param {object} features
* @param {object} style_sel
* @param {object} message_area_sel
* @return {undefined}
*/
self._applyDiscoXHTMLIM = function(xid, features, style_sel, message_area_sel) {
try {
// Apply
if(NS_XHTML_IM in features) {
style_sel.show();
} else {
// Remove the tooltip elements
style_sel.hide();
style_sel.find('.bubble-style').remove();
// Reset the markers
message_area_sel.removeAttr('style')
.removeAttr('data-font')
.removeAttr('data-fontsize')
.removeAttr('data-color')
.removeAttr('data-bold')
.removeAttr('data-italic')
.removeAttr('data-underline');
}
} catch(e) {
Console.error('Caps._applyDiscoXHTMLIM', e);
}
};
/**
* Apply Jingle features from disco infos
* @private
* @param {string} xid
* @param {object} path_sel
* @param {object} roster_sel
* @return {undefined}
*/
self._applyDiscoJingle = function(xid, path_sel, roster_sel) {
try {
// Selectors
var roster_jingle_sel = roster_sel.find('.buddy-infos .call-jingle');
var jingle_audio = path_sel.find('.tools-jingle-audio');
var roster_jingle_audio = roster_jingle_sel.find('a.audio');
var jingle_video = path_sel.find('.tools-jingle-video');
var roster_jingle_video = roster_jingle_sel.find('a.video');
var roster_jingle_separator = roster_jingle_sel.find('span.separator');
// Apply
var jingle_local_supported = JSJAC_JINGLE_AVAILABLE;
var jingle_audio_xid = self.getFeatureResource(xid, NS_JINGLE_APPS_RTP_AUDIO);
var jingle_video_xid = self.getFeatureResource(xid, NS_JINGLE_APPS_RTP_VIDEO);
if(jingle_audio_xid && jingle_local_supported) {
jingle_audio.show();
roster_jingle_audio.show();
} else {
jingle_audio.hide();
roster_jingle_audio.hide();
}
if(jingle_video_xid && jingle_local_supported) {
jingle_video.show();
roster_jingle_video.show();
} else {
jingle_video.hide();
roster_jingle_video.hide();
}
if(jingle_audio_xid && jingle_video_xid && jingle_local_supported) {
roster_jingle_separator.show();
} else {
roster_jingle_separator.hide();
}
if((jingle_audio_xid || jingle_video_xid) && jingle_local_supported) {
roster_jingle_sel.show();
} else {
roster_jingle_sel.hide();
}
} catch(e) {
Console.error('Caps._applyDiscoJingle', e);
}
};
/**
* Apply Out of Band Data features from disco infos
* @private
* @param {string} xid
* @param {object} features
* @param {object} file_sel
* @return {undefined}
*/
self._applyDiscoOOB = function(xid, features, file_sel) {
try {
// Apply
var iq_oob_xid = self.getFeatureResource(xid, NS_IQOOB);
if(iq_oob_xid || NS_XOOB in features) {
file_sel.show();
// Set a marker
file_sel.attr(
'data-oob',
iq_oob_xid ? 'iq' : 'x'
);
} else {
// Remove the tooltip elements
file_sel.hide();
file_sel.find('.bubble-style').remove();
// Reset the marker
file_sel.removeAttr('data-oob');
}
} catch(e) {
Console.error('Caps._applyDiscoOOB', e);
}
};
/**
* Apply Receipts features from disco infos
* @private
* @param {string} xid
* @param {object} features
* @param {object} message_area_sel
* @return {undefined}
*/
self._applyDiscoReceipts = function(xid, features, message_area_sel) {
try {
// Apply
if(NS_URN_RECEIPTS in features) {
message_area_sel.attr('data-receipts', 'true');
} else {
message_area_sel.removeAttr('data-receipts');
}
} catch(e) {
Console.error('Caps._applyDiscoReceipts', e);
}
};
/**
* Apply Last Message Correction features from disco infos
* @private
* @param {string} xid
* @param {object} features
* @param {object} path_sel
* @return {undefined}
*/
self._applyDiscoCorrection = function(xid, features, path_sel) {
try {
// Apply
if(NS_URN_CORRECT in features) {
path_sel.attr('data-correction', 'true');
} else {
path_sel.removeAttr('data-correction');
}
} catch(e) {
Console.error('Caps._applyDiscoCorrection', e);
}
};
/**
* Apply Chat Markers features from disco infos
* @private
* @param {string} xid
* @param {object} features
* @param {object} path_sel
* @return {undefined}
*/
self._applyDiscoMarkers = function(xid, features, path_sel) {
try {
// Apply
if(NS_URN_MARKERS in features) {
path_sel.attr('data-markers', 'true');
} else {
path_sel.removeAttr('data-markers');
}
} catch(e) {
Console.error('Caps._applyDiscoMarkers', e);
}
};
/**
* Apply Attention features from disco infos
* @private
* @param {string} xid
* @param {object} features
* @param {object} path_sel
* @return {undefined}
*/
self._applyDiscoAttention = function(xid, features, path_sel) {
try {
// Apply
if(NS_URN_ATTENTION in features) {
path_sel.attr('data-attention', 'true');
} else {
path_sel.removeAttr('data-attention');
}
} catch(e) {
Console.error('Caps._applyDiscoAttention', e);
}
};
/**
* Reads a stored Caps
* @public
* @param {string} caps
* @return {object}
*/
self.read = function(caps) {
try {
return Common.XMLFromString(
DataStore.getPersistent('global', 'caps', caps)
);
} catch(e) {
Console.error('Caps.read', e);
}
};
/**
* Returns an array of the Jappix disco#infos
* @public
* @return {object}
*/
self.myDiscoInfos = function() {
try {
var disco_base = self.disco_infos.items;
var disco_jingle = JSJaCJingle.disco();
var disco_all = disco_base.concat(disco_jingle);
return disco_all;
return Utils.uniqueArrayValues(disco_all);
} catch(e) {
Console.error('Caps.myDiscoInfos', e);
}
@ -169,103 +557,17 @@ var Caps = (function () {
self.handleDiscoInfos = function(iq) {
try {
if(!iq || (iq.getType() == 'error'))
if(!iq || (iq.getType() == 'error')) {
return;
}
// IQ received, get some values
var from = Common.fullXID(Common.getStanzaFrom(iq));
var query = iq.getQuery();
// Generate the CAPS-processing values
var identities = [];
var features = [];
var data_forms = [];
// Identity values
$(query).find('identity').each(function() {
var pCategory = $(this).attr('category');
var pType = $(this).attr('type');
var pLang = $(this).attr('xml:lang');
var pName = $(this).attr('name');
if(!pCategory)
pCategory = '';
if(!pType)
pType = '';
if(!pLang)
pLang = '';
if(!pName)
pName = '';
identities.push(pCategory + '/' + pType + '/' + pLang + '/' + pName);
});
// Feature values
$(query).find('feature').each(function() {
var pVar = $(this).attr('var');
// Add the current value to the array
if(pVar)
features.push(pVar);
});
// Data-form values
$(query).find('x[xmlns="' + NS_XDATA + '"]').each(function() {
// Initialize some stuffs
var pString = '';
var sortVar = [];
// Add the form type field
$(this).find('field[var="FORM_TYPE"] value').each(function() {
var cText = $(this).text();
if(cText)
pString += cText + '<';
});
// Add the var attributes into an array
$(this).find('field:not([var="FORM_TYPE"])').each(function() {
var cVar = $(this).attr('var');
if(cVar)
sortVar.push(cVar);
});
// Sort the var attributes
sortVar = sortVar.sort();
// Loop this sorted var attributes
$.each(sortVar, function(i) {
// Initialize the value sorting
var sortVal = [];
// Append it to the string
pString += sortVar[i] + '<';
// Add each value to the array
$(this).find('field[var=' + sortVar[i] + '] value').each(function() {
sortVal.push($(this).text());
});
// Sort the values
sortVal = sortVal.sort();
// Append the values to the string
for(var j in sortVal) {
pString += sortVal[j] + '<';
}
});
// Any string?
if(pString) {
// Remove the undesired double '<' from the string
if(pString.match(/(.+)(<)+$/))
pString = pString.substring(0, pString.length - 1);
// Add the current string to the array
data_forms.push(pString);
}
});
// Parse values
var identities = self._parseDiscoIdentities(query);
var features = self._parseDiscoFeatures(query);
var data_forms = self._parseDiscoDataForms(query);
// Process the CAPS
var caps = self.process(identities, features, data_forms);
@ -309,8 +611,9 @@ var Caps = (function () {
var xid = Common.bareXID(from);
// This comes from a private groupchat chat?
if(Utils.isPrivate(xid))
if(Utils.isPrivate(xid)) {
xid = from;
}
hash = hex_md5(xid);
@ -326,96 +629,20 @@ var Caps = (function () {
});
// Paths
var path = $('#' + hash);
var roster_path = $('#roster .buddy.' + hash);
var roster_jingle_path = roster_path.find('.buddy-infos .call-jingle');
var path_sel = $('#' + hash);
var roster_sel = $('#roster .buddy.' + hash);
var message_area_sel = path_sel.find('.message-area');
var style_sel = path_sel.find('.chat-tools-style');
var file_sel = path_sel.find('.chat-tools-file');
var message_area = path.find('.message-area');
var style = path.find('.chat-tools-style');
var jingle_audio = path.find('.tools-jingle-audio');
var roster_jingle_audio = roster_jingle_path.find('a.audio');
var jingle_video = path.find('.tools-jingle-video');
var roster_jingle_video = roster_jingle_path.find('a.video');
var roster_jingle_separator = roster_jingle_path.find('span.separator');
var file = path.find('.chat-tools-file');
// Apply xHTML-IM
if(NS_XHTML_IM in features) {
style.show();
} else {
// Remove the tooltip elements
style.hide();
style.find('.bubble-style').remove();
// Reset the markers
message_area.removeAttr('style')
.removeAttr('data-font')
.removeAttr('data-fontsize')
.removeAttr('data-color')
.removeAttr('data-bold')
.removeAttr('data-italic')
.removeAttr('data-underline');
}
// Apply Jingle
var jingle_local_supported = JSJAC_JINGLE_AVAILABLE;
var jingle_audio_xid = self.getFeatureResource(xid, NS_JINGLE_APPS_RTP_AUDIO);
var jingle_video_xid = self.getFeatureResource(xid, NS_JINGLE_APPS_RTP_VIDEO);
if(jingle_audio_xid && jingle_local_supported) {
jingle_audio.show();
roster_jingle_audio.show();
} else {
jingle_audio.hide();
roster_jingle_audio.hide();
}
if(jingle_video_xid && jingle_local_supported) {
jingle_video.show();
roster_jingle_video.show();
} else {
jingle_video.hide();
roster_jingle_video.hide();
}
if(jingle_audio_xid && jingle_video_xid && jingle_local_supported) {
roster_jingle_separator.show();
} else {
roster_jingle_separator.hide();
}
if((jingle_audio_xid || jingle_video_xid) && jingle_local_supported) {
roster_jingle_path.show();
} else {
roster_jingle_path.hide();
}
// Apply Out of Band Data
var iq_oob_xid = self.getFeatureResource(xid, NS_IQOOB);
if(iq_oob_xid || NS_XOOB in features) {
file.show();
// Set a marker
file.attr(
'data-oob',
iq_oob_xid ? 'iq' : 'x'
);
} else {
// Remove the tooltip elements
file.hide();
file.find('.bubble-style').remove();
// Reset the marker
file.removeAttr('data-oob');
}
// Apply receipts
if(NS_URN_RECEIPTS in features) {
message_area.attr('data-receipts', 'true');
} else {
message_area.removeAttr('data-receipts');
}
// Apply Features
self._applyDiscoXHTMLIM(xid, features, style_sel, message_area_sel);
self._applyDiscoJingle(xid, path_sel, roster_sel);
self._applyDiscoOOB(xid, features, file_sel);
self._applyDiscoReceipts(xid, features, message_area_sel);
self._applyDiscoCorrection(xid, features, path_sel);
self._applyDiscoMarkers(xid, features, path_sel);
self._applyDiscoAttention(xid, features, path_sel);
} catch(e) {
Console.error('Caps.displayDiscoInfos', e);
}
@ -426,39 +653,39 @@ var Caps = (function () {
/**
* Generates the CAPS hash
* @public
* @param {object} cIdentities
* @param {object} cFeatures
* @param {object} cDataForms
* @param {object} identities
* @param {object} features
* @param {object} dataforms
* @return {string}
*/
self.process = function(cIdentities, cFeatures, cDataForms) {
self.process = function(identities, features, dataforms) {
try {
// Initialize
var cString = '';
var caps_str = '';
// Sort the arrays
cIdentities = cIdentities.sort();
cFeatures = cFeatures.sort();
cDataForms = cDataForms.sort();
identities = identities.sort();
features = features.sort();
dataforms = dataforms.sort();
// Process the sorted identity string
for(var a in cIdentities) {
cString += cIdentities[a] + '<';
for(var a in identities) {
caps_str += identities[a] + '<';
}
// Process the sorted feature string
for(var b in cFeatures) {
cString += cFeatures[b] + '<';
for(var b in features) {
caps_str += features[b] + '<';
}
// Process the sorted data-form string
for(var c in cDataForms) {
cString += cDataForms[c] + '<';
for(var c in dataforms) {
caps_str += dataforms[c] + '<';
}
// Process the SHA-1 hash
var cHash = b64_sha1(cString);
var cHash = b64_sha1(caps_str);
return cHash;
} catch(e) {
@ -477,7 +704,12 @@ var Caps = (function () {
try {
return self.process(
['client/web//Jappix'],
[
self.disco_infos.identity.category + '/' +
self.disco_infos.identity.type + '//' +
self.disco_infos.identity.name
],
self.myDiscoInfos(),
[]
);
@ -507,8 +739,14 @@ var Caps = (function () {
var max_priority = null;
var cur_xid_full, cur_presence_sel, cur_caps, cur_features, cur_priority;
for(var cur_resource in Presence.resources(xid)) {
cur_xid_full = xid + '/' + cur_resource;
var resources_obj = Presence.resources(xid);
var fn_parse_resource = function(cur_resource) {
cur_xid_full = xid;
if(cur_resource) {
cur_xid_full += '/' + cur_resource;
}
cur_presence_sel = $(Presence.readStanza(cur_xid_full));
cur_priority = parseInt((cur_presence_sel.find('priority').text() || 0), 10);
@ -523,6 +761,14 @@ var Caps = (function () {
selected_xid = cur_xid_full;
}
}
};
if(resources_obj.bare === 1) {
fn_parse_resource(null);
}
for(var cur_resource in resources_obj.list) {
fn_parse_resource(cur_resource);
}
} catch(e) {
Console.error('Caps.getFeatureResource', e);

View file

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

View file

@ -20,6 +20,289 @@ var Chat = (function () {
var self = {};
/**
* Apply generate events
* @private
* @param {string} path
* @param {string} id
* @param {string} xid
* @return {undefined}
*/
self._generateEvents = function(path, id, xid) {
try {
// Click event: chat cleaner
$(path + 'tools-clear').click(function() {
self.clean(id);
});
// Click event: call (audio)
$(path + 'tools-jingle-audio').click(function() {
Jingle.start(xid, 'audio');
});
// Click event: call (video)
$(path + 'tools-jingle-video').click(function() {
Jingle.start(xid, 'video');
});
// Click event: user-infos
$(path + 'tools-infos').click(function() {
UserInfos.open(xid);
});
} catch(e) {
Console.error('Chat._generateEvents', e);
}
};
/**
* Apply generate events
* @private
* @param {object} input_sel
* @param {string} xid
* @param {string} hash
* @return {undefined}
*/
self._createEvents = function(input_sel, xid, hash) {
try {
self._createEventsInput(input_sel, hash);
self._createEventsKey(input_sel, xid, hash);
self._createEventsMouse(xid, hash);
} catch(e) {
Console.error('Chat._createEvents', e);
}
};
/**
* Apply generate events (input)
* @private
* @param {object} input_sel
* @param {string} hash
* @return {undefined}
*/
self._createEventsInput = function(input_sel, hash) {
try {
input_sel.focus(function() {
// Clean notifications for this chat
Interface.chanCleanNotify(hash);
// Store focus on this chat!
Interface.chat_focus_hash = hash;
});
input_sel.blur(function() {
// Reset storage about focus on this chat!
if(Interface.chat_focus_hash == hash) {
Interface.chat_focus_hash = null;
}
});
} catch(e) {
Console.error('Chat._createEventsInput', e);
}
};
/**
* Apply generate events (key)
* @private
* @param {object} input_sel
* @param {string} xid
* @param {string} hash
* @return {undefined}
*/
self._createEventsKey = function(input_sel, xid, hash) {
try {
input_sel.keydown(function(e) {
if(e.keyCode == 13) {
// Enter key
if(e.shiftKey || e.ctrlKey) {
// Add a new line
input_sel.val(input_sel.val() + '\n');
} else {
if(Correction.isIn(xid) === true) {
var corrected_value = input_sel.val().trim();
if(corrected_value) {
// Send the corrected message
Correction.send(xid, 'chat', corrected_value);
}
Correction.leave(xid);
} else {
// Send the message
Message.send(hash, 'chat');
}
// Reset the composing database entry
DataStore.setDB(Connection.desktop_hash, 'chatstate', xid, 'off');
}
return false;
} else if(e.keyCode == 8) {
// Leave correction mode? (another way, by flushing input value progressively)
if(Correction.isIn(xid) === true && !input_sel.val()) {
Correction.leave(xid);
}
}
});
input_sel.keyup(function(e) {
if(e.keyCode == 27) {
// Escape key
input_sel.val('');
// Leave correction mode? (simple escape way)
if(Correction.isIn(xid) === true) {
Correction.leave(xid);
}
} else {
Correction.detect(xid, input_sel);
}
});
} catch(e) {
Console.error('Chat._createEventsKey', e);
}
};
/**
* Apply generate events (mouse)
* @private
* @param {string} xid
* @param {string} hash
* @return {undefined}
*/
self._createEventsMouse = function(xid, hash) {
try {
// Scroll in chat content
$('#page-engine #' + hash + ' .content').scroll(function() {
var self = this;
if(Features.enabledMAM() && !(xid in MAM.map_pending)) {
var has_state = xid in MAM.map_states;
var rsm_count = has_state ? MAM.map_states[xid].rsm.count : 1;
var rsm_before = has_state ? MAM.map_states[xid].rsm.first : '';
// Request more archives?
if(rsm_count > 0 && $(this).scrollTop() < MAM.SCROLL_THRESHOLD) {
var was_scroll_top = $(self).scrollTop() <= 32;
var wait_mam = $('#' + hash).find('.wait-mam');
wait_mam.show();
MAM.getArchives({
'with': xid
}, {
'max': MAM.REQ_MAX,
'before': rsm_before
}, function() {
var wait_mam_height = was_scroll_top ? 0 : wait_mam.height();
wait_mam.hide();
// Restore scroll?
if($(self).scrollTop() < MAM.SCROLL_THRESHOLD) {
var sel_mam_chunk = $(self).find('.mam-chunk:first');
var cont_padding_top = parseInt($(self).css('padding-top').replace(/[^-\d\.]/g, ''));
var cont_one_group_margin_bottom = parseInt(sel_mam_chunk.find('.one-group:last').css('margin-bottom').replace(/[^-\d\.]/g, ''));
var cont_mam_chunk_height = sel_mam_chunk.height();
$(self).scrollTop(wait_mam_height + cont_padding_top + cont_one_group_margin_bottom + cont_mam_chunk_height);
}
});
}
}
});
} catch(e) {
Console.error('Chat._createEventsMouse', e);
}
};
/**
* Apply generate events
* @private
* @param {string} type
* @param {string} id
* @return {object}
*/
self._generateChatCode = function(type, id) {
var code_args = {};
try {
// Groupchat special code
if(type == 'groupchat') {
code_args.attributes = ' data-type="groupchat" data-correction="true"';
code_args.avatar = '';
code_args.name = '<p class="bc-infos"><b>' + Common._e("Subject") + '</b> <span class="muc-topic">' + Common._e("no subject defined for this room.") + '</span></p>';
code_args.code = '<div class="content groupchat-content" id="chat-content-' + id + '"></div>' +
'<div class="list"><div class="moderator role"><p class="title">' + Common._e("Moderators") + '</p></div>' +
'<div class="participant role"><p class="title">' + Common._e("Participants") + '</p></div>' +
'<div class="visitor role"><p class="title">' + Common._e("Visitors") + '</p></div>' +
'<div class="none role"><p class="title">' + Common._e("Others") + '</p></div></div>';
code_args.link = '<a href="#" class="tools-mucadmin tools-tooltip talk-images chat-tools-content" title="' + Common._e("Administration panel for this room") + '"></a>';
code_args.style = '';
// Is this a gateway?
if(xid.match(/%/)) {
code_args.disabled = '';
} else {
code_args.disabled = ' disabled=""';
}
} else {
code_args.mam = '<div class="wait-mam wait-small"></div>';
code_args.attributes = ' data-type="chat"';
code_args.avatar = '<div class="avatar-container"><img class="avatar" src="' + './images/others/default-avatar.png' + '" alt="" /></div>';
code_args.name = '<div class="bc-pep"></div><p class="bc-infos"><span class="unavailable show talk-images"></span></p>';
code_args.code = '<div class="content" id="chat-content-' + id + '">' + code_args.mam + '</div>';
code_args.link = '<a href="#" class="tools-jingle-audio tools-tooltip talk-images chat-tools-content" title="' + Common._e("Call (audio only)") + '"></a>' +
'<a href="#" class="tools-jingle-video tools-tooltip talk-images chat-tools-content" title="' + Common._e("Call (video)") + '"></a>' +
'<a href="#" class="tools-infos tools-tooltip talk-images chat-tools-content" title="' + Common._e("Show user profile") + '"></a>';
code_args.style = ' style="display: none;"';
code_args.disabled = '';
}
// Not a groupchat private chat, we can use the buddy add icon
if((type == 'chat') || (type == 'groupchat')) {
var title;
if(type == 'chat') {
title = Common._e("Add this contact to your friends");
} else {
title = Common._e("Add this groupchat to your favorites");
}
code_args.link += '<a href="#" class="tools-add tools-tooltip talk-images chat-tools-content" title="' + title + '"></a>';
}
// IE DOM parsing bug fix
code_args.style_picker = '<div class="chat-tools-content chat-tools-style"' + code_args.style + '>' +
'<a href="#" class="tools-style tools-tooltip talk-images"></a>' +
'</div>';
if((BrowserDetect.browser == 'Explorer') && (BrowserDetect.version < 9)) {
code_args.style_picker = '';
}
} catch(e) {
Console.error('Chat._generateChatCode', e);
} finally {
return code_args;
}
};
/**
* Correctly opens a new chat
* @public
@ -34,38 +317,40 @@ var Chat = (function () {
try {
// No XID?
if(!xid)
if(!xid) {
return false;
}
// We generate some stuffs
var hash = hex_md5(xid);
var name;
// Gets the name of the user/title of the room
if(title)
if(title) {
name = title;
else {
} else {
// Private groupchat chat
if(type == 'private')
if(type == 'private') {
name = Common.thisResource(xid);
}
// XMPP-ID
else if(xid.indexOf('@') != -1)
else if(xid.indexOf('@') != -1) {
name = Name.getBuddy(xid);
}
// Gateway
else
else {
name = xid;
}
}
// If the target div does not exist
if(!Common.exists('#' + hash)) {
// We check the type of the chat to open
if((type == 'chat') || (type == 'private'))
if((type == 'chat') || (type == 'private')) {
self.create(hash, xid, name, type);
else if(type == 'groupchat') {
} else if(type == 'groupchat') {
// Try to read the room stored configuration
if(!Utils.isAnonymous() && (!nickname || !password || !title)) {
// Catch the room data
@ -115,71 +400,21 @@ var Chat = (function () {
var escaped_xid = escape(xid);
// Special code
var specialAttributes, specialAvatar, specialName, specialCode, specialLink, specialDisabled, specialStyle, specialMAM;
// Groupchat special code
if(type == 'groupchat') {
specialAttributes = ' data-type="groupchat"';
specialAvatar = '';
specialName = '<p class="bc-infos"><b>' + Common._e("Subject") + '</b> <span class="muc-topic">' + Common._e("no subject defined for this room.") + '</span></p>';
specialCode = '<div class="content groupchat-content" id="chat-content-' + id + '"></div><div class="list"><div class="moderator role"><p class="title">' + Common._e("Moderators") + '</p></div><div class="participant role"><p class="title">' + Common._e("Participants") + '</p></div><div class="visitor role"><p class="title">' + Common._e("Visitors") + '</p></div><div class="none role"><p class="title">' + Common._e("Others") + '</p></div></div>';
specialLink = '<a href="#" class="tools-mucadmin tools-tooltip talk-images chat-tools-content" title="' + Common._e("Administration panel for this room") + '"></a>';
specialStyle = '';
// Is this a gateway?
if(xid.match(/%/))
specialDisabled = '';
else
specialDisabled = ' disabled=""';
}
// Chat (or other things?!) special code
else {
specialMAM = '<div class="wait-mam wait-small"></div>';
specialAttributes = ' data-type="chat"';
specialAvatar = '<div class="avatar-container"><img class="avatar" src="' + './images/others/default-avatar.png' + '" alt="" /></div>';
specialName = '<div class="bc-pep"></div><p class="bc-infos"><span class="unavailable show talk-images"></span></p>';
specialCode = '<div class="content" id="chat-content-' + id + '">' + specialMAM + '</div>';
specialLink = '<a href="#" class="tools-jingle-audio tools-tooltip talk-images chat-tools-content" title="' + Common._e("Call (audio only)") + '"></a>' +
'<a href="#" class="tools-jingle-video tools-tooltip talk-images chat-tools-content" title="' + Common._e("Call (video)") + '"></a>' +
'<a href="#" class="tools-infos tools-tooltip talk-images chat-tools-content" title="' + Common._e("Show user profile") + '"></a>';
specialStyle = ' style="display: none;"';
specialDisabled = '';
}
// Not a groupchat private chat, we can use the buddy add icon
if((type == 'chat') || (type == 'groupchat')) {
var addTitle;
if(type == 'chat')
addTitle = Common._e("Add this contact to your friends");
else
addTitle = Common._e("Add this groupchat to your favorites");
specialLink += '<a href="#" class="tools-add tools-tooltip talk-images chat-tools-content" title="' + addTitle + '"></a>';
}
// IE DOM parsing bug fix
var specialStylePicker = '<div class="chat-tools-content chat-tools-style"' + specialStyle + '>' +
'<a href="#" class="tools-style tools-tooltip talk-images"></a>' +
'</div>';
if((BrowserDetect.browser == 'Explorer') && (BrowserDetect.version < 9))
specialStylePicker = '';
var chat_args = self._generateChatCode(type, id);
// Append the chat HTML code
$('#page-engine').append(
'<div id="' + id + '" class="page-engine-chan chat one-counter"' + specialAttributes + ' data-xid="' + escaped_xid + '">' +
'<div id="' + id + '" class="page-engine-chan chat one-counter"' + chat_args.attributes + ' data-xid="' + escaped_xid + '">' +
'<div class="top ' + id + '">' +
specialAvatar +
chat_args.avatar +
'<div class="name">' +
'<p class="bc-name bc-name-nick">' + nick.htmlEnc() + '</p>' +
specialName +
chat_args.name +
'</div>' +
'</div>' +
specialCode +
chat_args.code +
'<div class="text">' +
'<div class="footer">' +
@ -187,7 +422,7 @@ var Chat = (function () {
'<a href="#" class="tools-smileys tools-tooltip talk-images"></a>' +
'</div>' +
specialStylePicker +
chat_args.style_picker +
'<div class="chat-tools-content chat-tools-file">' +
'<a href="#" class="tools-file tools-tooltip talk-images"></a>' +
@ -199,35 +434,17 @@ var Chat = (function () {
'<a href="#" class="tools-clear tools-tooltip talk-images chat-tools-content" title="' + Common._e("Clean current chat") + '"></a>' +
specialLink +
chat_args.link +
'</div>' +
'<div class="compose">' +
'<textarea class="message-area focusable" ' + specialDisabled + ' data-to="' + escaped_xid + '" /></textarea>' +
'<textarea class="message-area focusable" ' + chat_args.disabled + ' data-to="' + escaped_xid + '" /></textarea>' +
'</div>' +
'</div>' +
'</div>'
);
// Click event: chat cleaner
$(path + 'tools-clear').click(function() {
self.clean(id);
});
// Click event: call (audio)
$(path + 'tools-jingle-audio').click(function() {
Jingle.start(xid, 'audio');
});
// Click event: call (video)
$(path + 'tools-jingle-video').click(function() {
Jingle.start(xid, 'video');
});
// Click event: user-infos
$(path + 'tools-infos').click(function() {
UserInfos.open(xid);
});
self._generateEvents(path, id, xid);
} catch(e) {
Console.error('Chat.generate', e);
}
@ -251,26 +468,32 @@ var Chat = (function () {
var chat_switch = '#page-switch .';
// Special code
var specialClass = ' unavailable';
var special_class = ' unavailable';
var show_close = true;
// Groupchat
if(type == 'groupchat') {
specialClass = ' groupchat-default';
special_class = ' groupchat-default';
if(Utils.isAnonymous() && (xid == Common.generateXID(ANONYMOUS_ROOM, 'groupchat')))
if(Utils.isAnonymous() && (xid == Common.generateXID(ANONYMOUS_ROOM, 'groupchat'))) {
show_close = false;
}
}
// Generate the HTML code
var html = '<div class="' + id + ' switcher chan" onclick="return Interface.switchChan(\'' + Utils.encodeOnclick(id) + '\')">' +
'<div class="icon talk-images' + specialClass + '"></div>' +
'<div class="icon talk-images' + special_class + '"></div>' +
'<div class="name">' + nick.htmlEnc() + '</div>';
// Show the close button if not MUC and not anonymous
if(show_close)
html += '<div class="exit" title="' + Common._e("Close this tab") + '" onclick="return Interface.quitThisChat(\'' + Utils.encodeOnclick(xid) + '\', \'' + Utils.encodeOnclick(id) + '\', \'' + Utils.encodeOnclick(type) + '\');">x</div>';
if(show_close) {
html += '<div class="exit" ' +
'title="' + Common._e("Close this tab") + '" ' +
'onclick="return Interface.quitThisChat(\'' + Utils.encodeOnclick(xid) + '\', \'' + Utils.encodeOnclick(id) + '\', \'' + Utils.encodeOnclick(type) + '\');">' +
'x' +
'</div>';
}
// Close the HTML
html += '</div>';
@ -353,7 +576,7 @@ var Chat = (function () {
// Create the chat switcher
self.generateSwitch(type, hash, xid, nick);
// If the user is not in our roster
// Is this a chat?
if(type == 'chat') {
// MAM? Get archives from there!
if(Features.enabledMAM()) {
@ -373,32 +596,43 @@ var Chat = (function () {
var friend_hash = hex_md5(xid);
// Add chat history HTML
$('#' + hash + ' .content').append(chat_history);
var path_sel = $('#' + hash);
path_sel.find('.content').append(chat_history);
// Filter old groups & messages
$('#' + hash + ' .one-group[data-type="user-message"]').addClass('from-history').attr('data-type', 'old-message');
$('#' + hash + ' .user-message').removeClass('user-message').addClass('old-message');
var one_group_sel = path_sel.find('.one-group');
one_group_sel.filter('[data-type="user-message"]').addClass('from-history').attr('data-type', 'old-message');
path_sel.find('.user-message').removeClass('user-message').addClass('old-message');
// Regenerate user names
$('#' + hash + ' .one-group.' + my_hash + ' b.name').text(Name.getBuddy(Common.getXID()));
$('#' + hash + ' .one-group.' + friend_hash + ' b.name').text(Name.getBuddy(xid));
one_group_sel.filter('.' + my_hash + ' b.name').text(
Name.getBuddy(Common.getXID())
);
one_group_sel.filter('.' + friend_hash + ' b.name').text(
Name.getBuddy(xid)
);
// Regenerate group dates
$('#' + hash + ' .one-group').each(function() {
var current_stamp = parseInt($(this).attr('data-stamp'));
one_group_sel.each(function() {
var current_stamp = parseInt($(this).attr('data-stamp'), 10);
$(this).find('span.date').text(DateUtils.relative(current_stamp));
});
// Regenerate avatars
if(Common.exists('#' + hash + ' .one-group.' + my_hash + ' .avatar-container'))
if(Common.exists('#' + hash + ' .one-group.' + my_hash + ' .avatar-container')) {
Avatar.get(Common.getXID(), 'cache', 'true', 'forget');
if(Common.exists('#' + hash + ' .one-group.' + friend_hash + ' .avatar-container'))
}
if(Common.exists('#' + hash + ' .one-group.' + friend_hash + ' .avatar-container')) {
Avatar.get(xid, 'cache', 'true', 'forget');
}
}
}
// Add button
if(!Roster.isFriend(xid))
if(!Roster.isFriend(xid)) {
$('#' + hash + ' .tools-add').click(function() {
// Hide the icon (to tell the user all is okay)
$(this).hide();
@ -407,6 +641,7 @@ var Chat = (function () {
Roster.addThisContact(xid, nick);
}).show();
}
}
// We catch the user's informations (like this avatar, vcard, and so on...)
UserInfos.get(hash, xid, nick, type);
@ -415,81 +650,12 @@ var Chat = (function () {
Tooltip.icons(xid, hash);
// The event handlers
var inputDetect = $('#page-engine #' + hash + ' .message-area');
var input_sel = $('#page-engine #' + hash + ' .message-area');
self._createEvents(input_sel, xid, hash);
inputDetect.focus(function() {
// Clean notifications for this chat
Interface.chanCleanNotify(hash);
// Store focus on this chat!
Interface.chat_focus_hash = hash;
});
inputDetect.blur(function() {
// Reset storage about focus on this chat!
if(Interface.chat_focus_hash == hash)
Interface.chat_focus_hash = null;
});
inputDetect.keypress(function(e) {
// Enter key
if(e.keyCode == 13) {
// Add a new line
if(e.shiftKey || e.ctrlKey) {
inputDetect.val(inputDetect.val() + '\n');
} else {
// Send the message
Message.send(hash, 'chat');
// Reset the composing database entry
DataStore.setDB(Connection.desktop_hash, 'chatstate', xid, 'off');
}
return false;
}
});
// Scroll in chat content
$('#page-engine #' + hash + ' .content').scroll(function() {
var self = this;
if(Features.enabledMAM() && !(xid in MAM.map_pending)) {
var has_state = xid in MAM.map_states;
var rsm_count = has_state ? MAM.map_states[xid].rsm.count : 1;
var rsm_before = has_state ? MAM.map_states[xid].rsm.first : '';
// Request more archives?
if(rsm_count > 0 && $(this).scrollTop() < MAM.SCROLL_THRESHOLD) {
var was_scroll_top = $(self).scrollTop() <= 32;
var wait_mam = $('#' + hash).find('.wait-mam');
wait_mam.show();
MAM.getArchives({
'with': xid
}, {
'max': MAM.REQ_MAX,
'before': rsm_before
}, function() {
var wait_mam_height = was_scroll_top ? 0 : wait_mam.height();
wait_mam.hide();
// Restore scroll?
if($(self).scrollTop() < MAM.SCROLL_THRESHOLD) {
var sel_mam_chunk = $(self).find('.mam-chunk:first');
var cont_padding_top = parseInt($(self).css('padding-top').replace(/[^-\d\.]/g, ''));
var cont_one_group_margin_bottom = parseInt(sel_mam_chunk.find('.one-group:last').css('margin-bottom').replace(/[^-\d\.]/g, ''));
var cont_mam_chunk_height = sel_mam_chunk.height();
$(self).scrollTop(wait_mam_height + cont_padding_top + cont_one_group_margin_bottom + cont_mam_chunk_height);
}
});
}
}
});
// Chatstate events
ChatState.events(inputDetect, xid, hash, 'chat');
// Input events
ChatState.events(input_sel, xid, hash, 'chat');
Markers.events(input_sel, xid, hash, 'chat');
} catch(e) {
Console.error('Chat.create', e);
}

View file

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

View file

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

View file

@ -29,6 +29,205 @@ var Connection = (function () {
self.resume = false;
/**
* Do registration on Register API
* @private
* @param {string} username
* @param {string} domain
* @param {string} pass
* @param {string} captcha
* @return {boolean}
*/
self._doRegisterAPI = function(username, domain, pass, captcha) {
var is_success = false;
try {
// Show the waiting image
Interface.showGeneralWait();
// Change the page title
Interface.title('wait');
// Send request
$.post('./server/register.php', {username: username, domain: domain, password: pass, captcha: captcha}, function(data) {
// Error registering
Interface.removeGeneralWait();
Interface.title('home');
// In all case, update CAPTCHA
$('#home img.captcha_img').attr('src', './server/captcha.php?id=' + genID());
$('#home input.captcha').val('');
// Registration okay
if($(data).find('query status').text() == '1') {
is_success = true;
self.handleRegistered();
} else {
// Show error message
var error_message = '';
switch($(data).find('query message').text()) {
case 'CAPTCHA Not Matching':
error_message = Common._e("The security code you entered is invalid. Please retry with another one.");
$('#home input.captcha').focus();
break;
case 'Username Unavailable':
error_message = Common._e("The username you picked is not available. Please try another one.");
$('#home input.nick').focus();
break;
default:
error_message = Common._e("There was an error registering your account. Please retry.");
break;
}
if(error_message) {
Errors.show('', error_message, '');
}
}
});
} catch(e) {
Console.error('Connection._doRegisterAPI', e);
} finally {
return is_success;
}
};
/**
* Do registration throug in-band stream
* @private
* @param {string} username
* @param {string} domain
* @param {string} pass
* @return {boolean}
*/
self._doRegisterInBand = function(username, domain, pass) {
var is_success = true;
try {
if(Common.hasWebSocket()) {
// WebSocket supported & configured
con = new JSJaCWebSocketConnection({
httpbase: HOST_WEBSOCKET
});
} else {
var httpbase = (HOST_BOSH_MAIN || HOST_BOSH);
// Check BOSH origin
BOSH_SAME_ORIGIN = Origin.isSame(httpbase);
// We create the new http-binding connection
con = new JSJaCHttpBindingConnection({
httpbase: httpbase
});
}
// We setup the connection !
con.registerHandler('onconnect', self.handleRegistered);
con.registerHandler('onerror', Errors.handle);
con.connect({
'domain': $.trim(domain),
'username': $.trim(username),
'resource': JAPPIX_RESOURCE + ' Register (' + (new Date()).getTime() + ')',
'pass': pass,
'register': true,
'secure': true,
'xmllang': XML_LANG
});
// Show the waiting image
Interface.showGeneralWait();
// Change the page title
Interface.title('wait');
} catch(e) {
Console.error('Connection._doRegisterInBand', e);
is_success = false;
} finally {
return is_success;
}
};
/**
* Attaches reconnect events
* @private
* @param {string} mode
* @return {undefined}
*/
self._eventsReconnect = function(mode) {
try {
// Click events
if(mode == 'normal') {
$('#reconnect a.finish.cancel').click(function() {
return self.cancelReconnect();
});
}
$('#reconnect a.finish.reconnect').click(function() {
return self.acceptReconnect(mode);
});
} catch(e) {
Console.error('Connection._eventsReconnect', e);
}
};
/**
* Schedules the next auto reconnect
* @private
* @param {string} mode
* @return {undefined}
*/
self._scheduleReconnect = function(mode) {
try {
// Try to reconnect automatically after a while
if(self.reconnect_try < 5) {
self.reconnect_timer = 5 + (5 * self.reconnect_try);
} else {
self.reconnect_timer = 120;
}
// Change the try number
self.reconnect_try++;
// Fire the event!
$('#reconnect a.finish.reconnect').everyTime('1s', function() {
// We can reconnect!
if(self.reconnect_timer === 0) {
return self.acceptReconnect(mode);
}
// Button text
if(self.reconnect_timer <= 10) {
$(this).text(Common._e("Reconnect") + ' (' + self.reconnect_timer + ')');
}
// Remove 1 second
self.reconnect_timer--;
});
} catch(e) {
Console.error('Connection._scheduleReconnect', e);
}
};
/**
* Does the user login
* @public
@ -45,7 +244,7 @@ var Connection = (function () {
try {
// get optionnal conn handlers
oExtend = loginOpts || {};
extend_obj = loginOpts || {};
// We remove the not completed class to avoid problems
$('#home .loginer input').removeClass('please-complete');
@ -71,7 +270,7 @@ var Connection = (function () {
}
// And we handle everything that happen
self.setupCon(con, oExtend);
self.setupCon(con, extend_obj);
// Generate a resource
var random_resource = DataStore.getDB(self.desktop_hash, 'session', 'resource');
@ -80,16 +279,16 @@ var Connection = (function () {
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;
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(oArgs.username + '@' + oArgs.domain);
self.desktop_hash = 'jd.' + hex_md5(con_args.username + '@' + con_args.domain);
// Store the resource (for reconnection)
DataStore.setDB(self.desktop_hash, 'session', 'resource', random_resource);
@ -101,7 +300,7 @@ var Connection = (function () {
DataStore.setDB(self.desktop_hash, 'priority', 1, lPriority);
// We connect !
con.connect(oArgs);
con.connect(con_args);
// Change the page title
Interface.title('wait');
@ -169,7 +368,9 @@ var Connection = (function () {
// We change the registered information text
$('#home .homediv.registerer').append(
'<div class="info success">' +
Common._e("You have been registered, here is your XMPP address:") + ' <b>' + username.htmlEnc() + '@' + domain.htmlEnc() + '</b> - <a href="#">' + Common._e("Login") + '</a>' +
Common._e("You have been registered, here is your XMPP address:") +
' <b>' + username.htmlEnc() + '@' + domain.htmlEnc() + '</b> - ' +
'<a href="#">' + Common._e("Login") + '</a>' +
'</div>'
);
@ -179,102 +380,9 @@ var Connection = (function () {
});
if((REGISTER_API == 'on') && (domain == HOST_MAIN) && captcha) {
// Show the waiting image
Interface.showGeneralWait();
// Change the page title
Interface.title('wait');
// Send request
$.post('./server/register.php', {username: username, domain: domain, password: pass, captcha: captcha}, function(data) {
// Error registering
Interface.removeGeneralWait();
Interface.title('home');
// In all case, update CAPTCHA
$('#home img.captcha_img').attr('src', './server/captcha.php?id=' + genID());
$('#home input.captcha').val('');
// Registration okay
if($(data).find('query status').text() == '1') {
self.handleRegistered();
self._doRegisterAPI(username, domain, pass, captcha);
} 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 {
try {
oArgs = {};
if(Common.hasWebSocket()) {
// WebSocket supported & configured
con = new JSJaCWebSocketConnection({
httpbase: HOST_WEBSOCKET
});
} else {
var httpbase = (HOST_BOSH_MAIN || HOST_BOSH);
// Check BOSH origin
BOSH_SAME_ORIGIN = Origin.isSame(httpbase);
// We create the new http-binding connection
con = new JSJaCHttpBindingConnection({
httpbase: httpbase
});
}
// We setup the connection !
con.registerHandler('onconnect', self.handleRegistered);
con.registerHandler('onerror', Errors.handle);
// We retrieve what the user typed in the register inputs
oArgs = {};
oArgs.domain = $.trim(domain);
oArgs.username = $.trim(username);
oArgs.resource = JAPPIX_RESOURCE + ' Register (' + (new Date()).getTime() + ')';
oArgs.pass = pass;
oArgs.register = true;
oArgs.secure = true;
oArgs.xmllang = XML_LANG;
con.connect(oArgs);
// Show the waiting image
Interface.showGeneralWait();
// Change the page title
Interface.title('wait');
}
catch(e) {
// Logs errors
Console.error('doRegister', e);
}
self._doRegisterInBand(username, domain, pass);
}
} catch(e) {
Console.error('Connection.doRegister', e);
@ -295,30 +403,28 @@ var Connection = (function () {
try {
Console.info('Trying to login anonymously...');
var aPath = '#home .anonymouser ';
var room = $(aPath + '.room').val();
var nick = $(aPath + '.nick').val();
var path_sel = $('#home .anonymouser');
var room = path_sel.find('.room').val();
var nick = path_sel.find('.nick').val();
// If the form is correctly completed
// Form correctly completed?
if(room && nick) {
// We remove the not completed class to avoid problems
$('#home .anonymouser input').removeClass('please-complete');
// Redirect the user to the anonymous room
window.location.href = JAPPIX_LOCATION + '?r=' + room + '&n=' + nick;
}
} else {
path_sel.find('input[type="text"]').each(function() {
var this_sel = $(this);
// We check if the form is entirely completed
else {
$(aPath + 'input[type="text"]').each(function() {
var select = $(this);
if(!select.val())
if(!this_sel.val()) {
$(document).oneTime(10, function() {
select.addClass('please-complete').focus();
this_sel.addClass('please-complete').focus();
});
else
select.removeClass('please-complete');
} else {
this_sel.removeClass('please-complete');
}
});
}
} catch(e) {
@ -355,7 +461,7 @@ var Connection = (function () {
Interface.removeGeneralWait();
// Init Jingle
Jingle.init();
Call.init();
} catch(e) {
Console.error('Connection.handleConnected', e);
}
@ -374,8 +480,9 @@ var Connection = (function () {
// Not resumed?
if(!self.resume) {
// Remember the session?
if(DataStore.getDB(self.desktop_hash, 'remember', 'session'))
if(DataStore.getDB(self.desktop_hash, 'remember', 'session')) {
DataStore.setPersistent('global', 'session', 1, self.current_session);
}
// We show the chatting app.
Talk.create();
@ -431,24 +538,32 @@ var Connection = (function () {
* Setups the normal connection
* @public
* @param {object} con
* @param {object} oExtend
* @param {object} extend_obj
* @return {undefined}
*/
self.setupCon = function(con, oExtend) {
self.setupCon = function(con, extend_obj) {
try {
// Setup connection handlers
con.registerHandler('message', Message.handle);
con.registerHandler('presence', Presence.handle);
con.registerHandler('iq', IQ.handle);
con.registerHandler('onconnect', self.handleConnected);
con.registerHandler('onerror', Errors.handle);
con.registerHandler('ondisconnect', self.handleDisconnected);
var connection_handlers = {
'message': Message.handle,
'presence': Presence.handle,
'iq': IQ.handle,
'onconnect': self.handleConnected,
'onerror': Errors.handle,
'ondisconnect': self.handleDisconnected
};
for(var cur_handler in connection_handlers) {
con.registerHandler(
cur_handler,
connection_handlers[cur_handler]
);
}
// Extended handlers
oExtend = oExtend || {};
extend_obj = extend_obj || {};
jQuery.each(oExtend, function(keywd,funct) {
jQuery.each(extend_obj, function(keywd,funct) {
con.registerHandler(keywd, funct);
});
} catch(e) {
@ -563,8 +678,9 @@ var Connection = (function () {
Common._e("Due to a network issue, you were disconnected. What do you want to do now?");
// Can we cancel reconnection?
if(mode == 'normal')
if(mode == 'normal') {
html += '<a href="#" class="finish cancel">' + Common._e("Cancel") + '</a>';
}
html += '<a href="#" class="finish reconnect">' + Common._e("Reconnect") + '</a>' +
'</div></div>';
@ -572,38 +688,11 @@ var Connection = (function () {
// Append the code
$('body').append(html);
// Click events
if(mode == 'normal')
$('#reconnect a.finish.cancel').click(function() {
return self.cancelReconnect();
});
// Attach events
self._eventsReconnect(mode);
$('#reconnect a.finish.reconnect').click(function() {
return self.acceptReconnect(mode);
});
// Try to reconnect automatically after a while
if(self.reconnect_try < 5)
self.reconnect_timer = 5 + (5 * self.reconnect_try);
else
self.reconnect_timer = 120;
// Change the try number
self.reconnect_try++;
// Fire the event!
$('#reconnect a.finish.reconnect').everyTime('1s', function() {
// We can reconnect!
if(self.reconnect_timer === 0)
return self.acceptReconnect(mode);
// Button text
if(self.reconnect_timer <= 10)
$(this).text(Common._e("Reconnect") + ' (' + self.reconnect_timer + ')');
// Remove 1 second
self.reconnect_timer--;
});
// Schedule next reconnect
self._scheduleReconnect(mode);
// Page title
Interface.updateTitle();
@ -634,9 +723,11 @@ var Connection = (function () {
// Reset some various stuffs
var groupchats = '#page-engine .page-engine-chan[data-type="groupchat"]';
$(groupchats + ' .list .role').hide();
$(groupchats + ' .one-group, ' + groupchats + ' .list .user').remove();
$(groupchats).attr('data-initial', 'false');
var groupchats_sel = $(groupchats);
groupchats_sel.find('.list .role').hide();
groupchats_sel.find('.one-group, ' + groupchats + ' .list .user').remove();
groupchats_sel.attr('data-initial', 'false');
// Stop the timer
$('#reconnect a.finish.reconnect').stopTime();
@ -645,10 +736,11 @@ var Connection = (function () {
$('#reconnect').remove();
// Try to login again
if(mode == 'normal')
if(mode == 'normal') {
self.loginFromSession(Common.XMLFromString(self.current_session));
else if(mode == 'anonymous')
} else if(mode == 'anonymous') {
Anonymous.login(HOST_ANONYMOUS);
}
} catch(e) {
Console.error('Connection.acceptReconnect', e);
} finally {
@ -817,7 +909,14 @@ var Connection = (function () {
try {
// Generate a session XML to be stored
session_xml = '<session><stored>true</stored><domain>' + lServer.htmlEnc() + '</domain><username>' + lNick.htmlEnc() + '</username><resource>' + lResource.htmlEnc() + '</resource><password>' + lPass.htmlEnc() + '</password><priority>' + lPriority.htmlEnc() + '</priority></session>';
session_xml = '<session>' +
'<stored>true</stored>' +
'<domain>' + lServer.htmlEnc() + '</domain>' +
'<username>' + lNick.htmlEnc() + '</username>' +
'<resource>' + lResource.htmlEnc() + '</resource>' +
'<password>' + lPass.htmlEnc() + '</password>' +
'<priority>' + lPriority.htmlEnc() + '</priority>' +
'</session>';
// Save the session parameters (for reconnect if network issue)
self.current_session = session_xml;
@ -848,8 +947,9 @@ var Connection = (function () {
$(window).bind('beforeunload', Connection.terminate);
// Nothing to do when anonymous!
if(Utils.isAnonymous())
if(Utils.isAnonymous()) {
return;
}
// Connection params submitted in URL?
if(XMPPLinks.links_var.u && XMPPLinks.links_var.q) {
@ -865,7 +965,15 @@ var Connection = (function () {
// Must store session?
if(XMPPLinks.links_var.h && (XMPPLinks.links_var.h === '1')) {
// Store session
var session_xml = self.storeSession(login_nick, login_server, login_pwd, login_resource, login_priority, true);
var session_xml = self.storeSession(
login_nick,
login_server,
login_pwd,
login_resource,
login_priority,
true
);
DataStore.setPersistent('global', 'session', 1, session_xml);
// Redirect to a clean URL
@ -900,10 +1008,7 @@ var Connection = (function () {
self.loginFromSession(session);
Console.info('Saved session found, resuming it...');
}
// Not connected, maybe a XMPP link is submitted?
else if((parent.location.hash != '#OK') && XMPPLinks.links_var.x) {
} else if((parent.location.hash != '#OK') && XMPPLinks.links_var.x) {
Home.change('loginer');
Console.info('A XMPP link is set, switch to login page.');

View file

@ -79,6 +79,12 @@ var NS_URN_MAM = NS_XMPP + 'mam:tmp';
var NS_URN_DELAY = NS_XMPP + 'delay';
var NS_URN_RECEIPTS = NS_XMPP + 'receipts';
var NS_URN_CARBONS = NS_XMPP + 'carbons:2';
var NS_URN_CORRECT = NS_XMPP + 'message-correct:0';
var NS_URN_IDLE = NS_XMPP + 'idle:1';
var NS_URN_REACH = NS_XMPP + 'reach:0';
var NS_URN_MARKERS = NS_XMPP + 'chat-markers:0';
var NS_URN_ATTENTION = NS_XMPP + 'attention:0';
var NS_URN_HINTS = NS_XMPP + 'hints';
var NS_RSM = NS_PROTOCOL + 'rsm';
var NS_IPV6 = 'ipv6';
var NS_XHTML = 'http://www.w3.org/1999/xhtml';

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

View file

@ -62,8 +62,9 @@ var DataForm = (function () {
else if(type == 'browse') {
var iqQuery = iq.setQuery(NS_DISCO_ITEMS);
if(node)
if(node) {
iqQuery.setAttribute('node', node);
}
con.send(iq, self.handleBrowse);
}
@ -72,8 +73,9 @@ var DataForm = (function () {
else if(type == 'command') {
var items;
if(node)
if(node) {
items = iq.appendNode('command', {'node': node, 'xmlns': NS_COMMANDS});
}
else {
items = iq.setQuery(NS_DISCO_ITEMS);
@ -102,8 +104,9 @@ var DataForm = (function () {
// Join
else if(type == 'join') {
if(target == 'discovery')
if(target == 'discovery') {
Discovery.close();
}
Chat.checkCreate(host, 'groupchat');
}
@ -144,14 +147,15 @@ var DataForm = (function () {
// Set the correct query
var query;
if(type == 'subscribe')
if(type == 'subscribe') {
iqQuery = iq.setQuery(NS_REGISTER);
else if(type == 'search')
} else if(type == 'search') {
iqQuery = iq.setQuery(NS_SEARCH);
else if(type == 'command')
} else if(type == 'command') {
iqQuery = iq.appendNode('command', {'xmlns': NS_COMMANDS, 'node': node, 'sessionid': sessionid, 'action': action});
else if(type == 'x')
} else if(type == 'x') {
iqQuery = iq.setQuery(NS_MUC_OWNER);
}
// Build the XML document
if(action != 'cancel') {
@ -181,11 +185,12 @@ var DataForm = (function () {
// Boolean input?
if(iType == 'boolean') {
if($(this).filter(':checked').size())
if($(this).filter(':checked').size()) {
iValue = '1';
else
} else {
iValue = '0';
}
}
// JID-multi input?
if(iType == 'jid-multi') {
@ -194,8 +199,9 @@ var DataForm = (function () {
var xid_check = [];
// Try to split it
if(iValue.indexOf(',') != -1)
if(iValue.indexOf(',') != -1) {
xid_arr = iValue.split(',');
}
// Append each value to the XML document
for(var i in xid_arr) {
@ -203,8 +209,9 @@ var DataForm = (function () {
xid_current = $.trim(xid_arr[i]);
// No current value?
if(!xid_current)
if(!xid_current) {
continue;
}
// Add the current value
if(!Utils.existArrayValue(xid_check, xid_current)) {
@ -225,8 +232,9 @@ var DataForm = (function () {
}
// Other inputs?
else
else {
field.appendChild(iq.buildNode('value', {'xmlns': NS_XDATA}, iValue));
}
});
}
}
@ -243,14 +251,15 @@ var DataForm = (function () {
iq.setID(iqID);
// Send the IQ
if(type == 'subscribe')
if(type == 'subscribe') {
con.send(iq, self.handleSubscribe);
else if(type == 'search')
} else if(type == 'search') {
con.send(iq, self.handleSearch);
else if(type == 'command')
} else if(type == 'command') {
con.send(iq, self.handleCommand);
else
} else {
con.send(iq);
}
} catch(e) {
Console.error('DataForm.send', e);
} finally {
@ -277,8 +286,9 @@ var DataForm = (function () {
try {
// No need to use buttons?
if(type == 'muc')
if(type == 'muc') {
return;
}
// Override the "undefined" output
if(!id)
@ -295,7 +305,7 @@ var DataForm = (function () {
if(action == 'submit') {
if((target == 'adhoc') && (type == 'command')) {
buttonsCode += '<a href="#" class="submit" onclick="return self.send(\'' + Utils.encodeOnclick(type) + '\', \'execute\', \'submit\', \'' + Utils.encodeOnclick(id) + '\', \'' + Utils.encodeOnclick(xid) + '\', \'' + Utils.encodeOnclick(node) + '\', \'' + Utils.encodeOnclick(sessionid) + '\', \'' + Utils.encodeOnclick(target) + '\');">' + Common._e("Submit") + '</a>';
buttonsCode += '<a href="#" class="submit" onclick="return DataForm.send(\'' + Utils.encodeOnclick(type) + '\', \'execute\', \'submit\', \'' + Utils.encodeOnclick(id) + '\', \'' + Utils.encodeOnclick(xid) + '\', \'' + Utils.encodeOnclick(node) + '\', \'' + Utils.encodeOnclick(sessionid) + '\', \'' + Utils.encodeOnclick(target) + '\');">' + Common._e("Submit") + '</a>';
// When keyup on one text input
$(pathID + ' input').keyup(function(e) {
@ -305,10 +315,8 @@ var DataForm = (function () {
return false;
}
});
}
else {
buttonsCode += '<a href="#" class="submit" onclick="return self.send(\'' + Utils.encodeOnclick(type) + '\', \'submit\', \'submit\', \'' + Utils.encodeOnclick(id) + '\', \'' + Utils.encodeOnclick(xid) + '\', \'' + Utils.encodeOnclick(node) + '\', \'' + Utils.encodeOnclick(sessionid) + '\', \'' + Utils.encodeOnclick(target) + '\');">' + Common._e("Submit") + '</a>';
} else {
buttonsCode += '<a href="#" class="submit" onclick="return DataForm.send(\'' + Utils.encodeOnclick(type) + '\', \'submit\', \'submit\', \'' + Utils.encodeOnclick(id) + '\', \'' + Utils.encodeOnclick(xid) + '\', \'' + Utils.encodeOnclick(node) + '\', \'' + Utils.encodeOnclick(sessionid) + '\', \'' + Utils.encodeOnclick(target) + '\');">' + Common._e("Submit") + '</a>';
// When keyup on one text input
$(pathID + ' input').keyup(function(e) {
@ -321,17 +329,21 @@ var DataForm = (function () {
}
}
if((action == 'submit') && (type != 'subscribe') && (type != 'search'))
buttonsCode += '<a href="#" class="submit" onclick="return self.send(\'' + Utils.encodeOnclick(type) + '\', \'cancel\', \'cancel\', \'' + Utils.encodeOnclick(id) + '\', \'' + Utils.encodeOnclick(xid) + '\', \'' + Utils.encodeOnclick(node) + '\', \'' + Utils.encodeOnclick(sessionid) + '\', \'' + Utils.encodeOnclick(target) + '\');">' + Common._e("Cancel") + '</a>';
if((action == 'submit') && (type != 'subscribe') && (type != 'search')) {
buttonsCode += '<a href="#" class="submit" onclick="return DataForm.send(\'' + Utils.encodeOnclick(type) + '\', \'cancel\', \'cancel\', \'' + Utils.encodeOnclick(id) + '\', \'' + Utils.encodeOnclick(xid) + '\', \'' + Utils.encodeOnclick(node) + '\', \'' + Utils.encodeOnclick(sessionid) + '\', \'' + Utils.encodeOnclick(target) + '\');">' + Common._e("Cancel") + '</a>';
}
if(((action == 'back') || (type == 'subscribe') || (type == 'search')) && (target == 'discovery'))
if(((action == 'back') || (type == 'subscribe') || (type == 'search')) && (target == 'discovery')) {
buttonsCode += '<a href="#" class="back" onclick="return Discovery.start();">' + Common._e("Close") + '</a>';
}
if((action == 'back') && ((target == 'welcome') || (target == 'directory')))
if((action == 'back') && ((target == 'welcome') || (target == 'directory'))) {
buttonsCode += '<a href="#" class="back" onclick="return DataForm.go(HOST_VJUD, \'search\', \'\', \'\', \'' + target + '\');">' + Common._e("Previous") + '</a>';
}
if((action == 'back') && (target == 'adhoc'))
if((action == 'back') && (target == 'adhoc')) {
buttonsCode += '<a href="#" class="back" onclick="return DataForm.go(\'' + Utils.encodeOnclick(xid) + '\', \'command\', \'\', \'\', \'adhoc\');">' + Common._e("Previous") + '</a>';
}
buttonsCode += '</div>';
@ -339,8 +351,9 @@ var DataForm = (function () {
$(pathID).append(buttonsCode);
// If no submit link, lock the form
if(!Common.exists(pathID + ' a.submit'))
if(!Common.exists(pathID + ' a.submit')) {
$(pathID + ' input, ' + pathID + ' textarea').attr('readonly', true);
}
} catch(e) {
Console.error('DataForm.buttons', e);
}
@ -459,8 +472,9 @@ var DataForm = (function () {
var pathID = '#' + target + ' .results[data-session="' + sessionID + '"]';
// If an error occured
if(!iq || (iq.getType() != 'result'))
if(!iq || (iq.getType() != 'result')) {
self.noResult(pathID);
}
// If we got something okay
else {
@ -479,20 +493,22 @@ var DataForm = (function () {
var itemHash = hex_md5(itemHost);
// Node
if(itemNode)
if(itemNode) {
$(pathID).append(
'<div class="oneresult ' + target + '-oneresult" onclick="return DataForm.go(\'' + Utils.encodeOnclick(itemHost) + '\', \'browse\', \'' + Utils.encodeOnclick(itemNode) + '\', \'\', \'' + Utils.encodeOnclick(target) + '\');">' +
'<div class="one-name">' + itemNode.htmlEnc() + '</div>' +
'</div>'
);
}
// Item
else if(queryNode && itemName)
else if(queryNode && itemName) {
$(pathID).append(
'<div class="oneresult ' + target + '-oneresult">' +
'<div class="one-name">' + itemName.htmlEnc() + '</div>' +
'</div>'
);
}
// Item with children
else {
@ -544,9 +560,9 @@ var DataForm = (function () {
var bCountry;
var doneName, doneCountry;
$.each($(this).find('field'), function(i, item)
{
$.each($(this).find('field'), function(i, item) {
var $item = $(item);
if($(item).attr('var').match(/^(fn|name|[^n][^i][^c][^k]name)$/gi) && doneName !== true) {
bName = $item.children('value:first').text();
doneName = true;
@ -581,16 +597,19 @@ var DataForm = (function () {
'<div class="buttons-container">';
// The buddy is not in our buddy list?
if(!Common.exists('#roster .buddy[data-xid="' + escape(bXID) + '"]'))
if(!Common.exists('#roster .buddy[data-xid="' + escape(bXID) + '"]')) {
bHTML += '<a href="#" class="one-add one-vjud one-button talk-images">' + Common._e("Add") + '</a>';
}
// Chat button, if not in welcome/directory mode
if(target == 'discovery')
if(target == 'discovery') {
bHTML += '<a href="#" class="one-chat one-vjud one-button talk-images">' + Common._e("Chat") + '</a>';
}
// Profile button, if not in discovery mode
else
else {
bHTML += '<a href="#" class="one-profile one-vjud one-button talk-images">' + Common._e("Profile") + '</a>';
}
// Close the HTML element
bHTML += '</div></div>';
@ -615,15 +634,17 @@ var DataForm = (function () {
}
// Buddy profile
if($(this).is('.one-profile'))
if($(this).is('.one-profile')) {
UserInfos.open(bXID);
}
return false;
});
// Get the user's avatar
if(bXID)
if(bXID) {
Avatar.get(bXID, 'cache', 'true', 'forget');
}
});
// No result?
@ -640,11 +661,12 @@ var DataForm = (function () {
self.fill(handleXML, sessionID);
// We display the buttons
if(bStatus != 'completed')
if(bStatus != 'completed') {
self.buttons(type, 'submit', sessionID, from, bNode, bSession, target, pathID);
else
} else {
self.buttons(type, 'back', sessionID, from, bNode, bSession, target, pathID);
}
}
// Command completed or subscription done
else if(((bStatus == 'completed') && (type == 'command')) || (!xRegister && (type == 'subscribe'))) {
@ -661,24 +683,27 @@ var DataForm = (function () {
}
// Default text
else
else {
$(pathID).append('<div class="oneinstructions ' + target + '-oneresult">' + Common._e("Your form has been sent.") + '</div>');
}
// Display the back button
self.buttons(type, 'back', sessionID, from, '', '', target, pathID);
// Add the gateway to our roster if subscribed
if(type == 'subscribe')
if(type == 'subscribe') {
Roster.addThisContact(from);
}
}
// Command canceled
else if((bStatus == 'canceled') && (type == 'command')) {
if(target == 'discovery')
if(target == 'discovery') {
Discovery.start();
else if(target == 'adhoc')
} else if(target == 'adhoc') {
dataForm(from, 'command', '', '', 'adhoc');
}
}
// No items for this query
else
@ -706,10 +731,11 @@ var DataForm = (function () {
}
// Else, there are no items for this query
else
else {
self.noResult(pathID);
}
}
}
// Focus on the first input
$(document).oneTime(10, function() {
@ -743,16 +769,18 @@ var DataForm = (function () {
var selector, is_dataform;
// Is it a dataform?
if($(xml).find('x[xmlns="' + NS_XDATA + '"]').size())
if($(xml).find('x[xmlns="' + NS_XDATA + '"]').size()) {
is_dataform = true;
else
} else {
is_dataform = false;
}
// Determines the good selector to use
if(is_dataform)
if(is_dataform) {
selector = $(xml).find('x[xmlns="' + NS_XDATA + '"]');
else
} else {
selector = $(xml);
}
// Form title
selector.find('title').each(function() {
@ -799,29 +827,32 @@ var DataForm = (function () {
var required = '';
// No value?
if(!field)
if(!field) {
return;
}
// Required input?
if($(this).find('required').size())
if($(this).find('required').size()) {
required = ' required=""';
}
// Compatibility fix
if(!label)
if(!label) {
label = field;
}
if(!type)
if(!type) {
type = '';
}
// Generate some values
var input;
var hideThis = '';
// Fixed field
if(type == 'fixed')
if(type == 'fixed') {
$(pathID).append('<div class="oneinstructions">' + value.htmlEnc() + '</div>');
else {
} else {
// Hidden field
if(type == 'hidden') {
hideThis = ' style="display: none;"';
@ -845,8 +876,9 @@ var DataForm = (function () {
var multiple = '';
// Multiple options?
if(type == 'list-multi')
if(type == 'list-multi') {
multiple = ' multiple=""';
}
// Append the select field
input = '<select name="' + Common.encodeQuotes(field) + '" data-type="' + Common.encodeQuotes(type) + '" class="dataform-i"' + required + multiple + '>';
@ -858,14 +890,16 @@ var DataForm = (function () {
var nValue = $(this).find('value').text();
// No label?
if(!nLabel)
if(!nLabel) {
nLabel = nValue;
}
// If this is the selected value
if(nValue == value)
if(nValue == value) {
selected = 'selected';
else
} else {
selected = '';
}
input += '<option ' + selected + ' value="' + Common.encodeQuotes(nValue) + '">' + nLabel.htmlEnc() + '</option>';
});
@ -874,8 +908,9 @@ var DataForm = (function () {
}
// Text-multi field
else if(type == 'text-multi')
else if(type == 'text-multi') {
input = '<textarea rows="8" cols="60" data-type="' + Common.encodeQuotes(type) + '" name="' + Common.encodeQuotes(field) + '" class="dataform-i"' + required + '>' + value.htmlEnc() + '</textarea>';
}
// JID-multi field
else if(type == 'jid-multi') {
@ -885,8 +920,9 @@ var DataForm = (function () {
$(this).find('value').each(function() {
var cValue = $(this).text();
if(!Utils.existArrayValue(xid_arr, cValue))
if(!Utils.existArrayValue(xid_arr, cValue)) {
xid_arr.push(cValue);
}
});
// Sort the array
@ -898,8 +934,9 @@ var DataForm = (function () {
if(xid_arr.length) {
for(var i in xid_arr) {
// Any pre-value
if(xid_value)
if(xid_value) {
xid_value += ', ';
}
// Add the current XID
xid_value += xid_arr[i];
@ -915,12 +952,14 @@ var DataForm = (function () {
var iType = 'text';
// Text-private field
if(type == 'text-private')
if(type == 'text-private') {
iType = 'password';
}
// JID-single field
else if(type == 'jid-single')
else if(type == 'jid-single') {
iType = 'email';
}
input = '<input name="' + Common.encodeQuotes(field) + '" data-type="' + Common.encodeQuotes(type) + '" type="' + iType + '" class="dataform-i" value="' + Common.encodeQuotes(value) + '"' + required + ' />';
}
@ -1001,10 +1040,11 @@ var DataForm = (function () {
var type = $(handleXML).find('identity').attr('type');
var named = $(handleXML).find('identity').attr('name');
if(named)
if(named) {
gName = named;
else
} else {
gName = '';
}
var one, two, three, four, five;

View file

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

View file

@ -84,8 +84,9 @@ var DateUtils = (function () {
try {
// Last activity not yet initialized?
if(self.last_activity === 0)
if(self.last_activity === 0) {
return 0;
}
return self.getTimeStamp() - self.last_activity;
} catch(e) {
@ -95,6 +96,27 @@ var DateUtils = (function () {
};
/**
* Gets the last user activity as a date
* @public
* @return {string}
*/
self.getLastActivityDate = function() {
try {
var last_activity = self.last_activity || self.getTimeStamp();
var last_date = new Date();
last_date.setTime(last_activity * 1000);
return self.getDatetime(last_date, 'utc');
} catch(e) {
Console.error('DateUtils.getLastActivityDate', e);
}
};
/**
* Gets the last user available presence in seconds
* @public
@ -104,8 +126,9 @@ var DateUtils = (function () {
try {
// Last presence stamp not yet initialized?
if(self.presence_last_activity === 0)
if(self.presence_last_activity === 0) {
return 0;
}
return self.getTimeStamp() - self.presence_last_activity;
} catch(e) {
@ -115,6 +138,56 @@ var DateUtils = (function () {
};
/**
* Generates a normalized datetime
* @public
* @param {Date} date
* @param {string} location
* @return {string}
*/
self.getDatetime = function(date, location) {
/* FROM : http://trac.jwchat.org/jsjac/browser/branches/jsjac_1.0/jsextras.js?rev=221 */
var year, month, day, hours, minutes, seconds;
var date_string = null;
try {
if(location == 'utc') {
// UTC date
year = date.getUTCFullYear();
month = date.getUTCMonth();
day = date.getUTCDate();
hours = date.getUTCHours();
minutes = date.getUTCMinutes();
seconds = date.getUTCSeconds();
} else {
// Local date
year = date.getFullYear();
month = date.getMonth();
day = date.getDate();
hours = date.getHours();
minutes = date.getMinutes();
seconds = date.getSeconds();
}
// Generates the date string
date_string = year + '-';
date_string += Common.padZero(month + 1) + '-';
date_string += Common.padZero(day) + 'T';
date_string += Common.padZero(hours) + ':';
date_string += Common.padZero(minutes) + ':';
date_string += Common.padZero(seconds) + 'Z';
// Returns the date string
return date_string;
} catch(e) {
Console.error('DateUtils.getDatetime', e);
}
};
/**
* Generates the time for XMPP
* @public
@ -123,43 +196,11 @@ var DateUtils = (function () {
*/
self.getXMPPTime = function(location) {
/* FROM : http://trac.jwchat.org/jsjac/browser/branches/jsjac_1.0/jsextras.js?rev=221 */
try {
// Initialize
var jInit = new Date();
var year, month, day, hours, minutes, seconds;
// Gets the UTC date
if(location == 'utc') {
year = jInit.getUTCFullYear();
month = jInit.getUTCMonth();
day = jInit.getUTCDate();
hours = jInit.getUTCHours();
minutes = jInit.getUTCMinutes();
seconds = jInit.getUTCSeconds();
}
// Gets the local date
else {
year = jInit.getFullYear();
month = jInit.getMonth();
day = jInit.getDate();
hours = jInit.getHours();
minutes = jInit.getMinutes();
seconds = jInit.getSeconds();
}
// Generates the date string
var jDate = year + '-';
jDate += Common.padZero(month + 1) + '-';
jDate += Common.padZero(day) + 'T';
jDate += Common.padZero(hours) + ':';
jDate += Common.padZero(minutes) + ':';
jDate += Common.padZero(seconds) + 'Z';
// Returns the date string
return jDate;
return self.getDatetime(
(new Date()),
location
);
} catch(e) {
Console.error('DateUtils.getXMPPTime', e);
}
@ -176,6 +217,7 @@ var DateUtils = (function () {
try {
var init = new Date();
var time = Common.padZero(init.getHours()) + ':';
time += Common.padZero(init.getMinutes()) + ':';
time += Common.padZero(init.getSeconds());
@ -332,20 +374,24 @@ var DateUtils = (function () {
var days = Math.round((current_stamp - old_stamp) / 86400000);
// Invalid date?
if(isNaN(old_stamp) || isNaN(days))
if(isNaN(old_stamp) || isNaN(days)) {
return self.getCompleteTime();
}
// Is it today?
if(current_day == old_day)
if(current_day == old_day) {
return old_time;
}
// It is yesterday?
if(days <= 1)
if(days <= 1) {
return Common._e("Yesterday") + ' - ' + old_time;
}
// Is it less than a week ago?
if(days <= 7)
if(days <= 7) {
return Common.printf(Common._e("%s days ago"), days) + ' - ' + old_time;
}
// Another longer period
return old_date.toLocaleDateString() + ' - ' + old_time;
@ -371,13 +417,12 @@ var DateUtils = (function () {
// Read the delay
d_delay = jQuery(node).find('delay[xmlns="' + NS_URN_DELAY + '"]:first').attr('stamp');
// Get delay
if(d_delay) {
// New delay (valid XEP)
if(d_delay)
delay = d_delay;
} else {
// 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');
if(x_delay)

View file

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

View file

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

View file

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

View file

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

View file

@ -103,7 +103,7 @@ var Features = (function () {
};
// Markers
var namespaces = [NS_PUBSUB, NS_PUBSUB_CN, NS_URN_MAM, NS_COMMANDS, NS_URN_CARBONS];
var namespaces = [NS_PUBSUB, NS_PUBSUB_CN, NS_URN_MAM, NS_COMMANDS, NS_URN_CARBONS, NS_URN_CORRECT];
var identity = selector.find('identity');
@ -219,6 +219,11 @@ var Features = (function () {
$(path + 'mam-purge-hidable').show();
}
// Message correction features
if(self.enabledCorrection()) {
$(path + 'correction-hidable').show();
}
// Commands features
if(self.enabledCommands()) {
$(path + 'commands-hidable').show();
@ -385,6 +390,22 @@ var Features = (function () {
};
/**
* Returns the XMPP server correction support
* @public
* @return {boolean}
*/
self.enabledCorrection = function() {
try {
return self.isEnabled(NS_URN_CORRECT);
} catch(e) {
Console.error('Features.enabledCorrection', e);
}
};
/**
* Normalizes the XMPP server name
* @private

View file

@ -20,123 +20,236 @@ var Filter = (function () {
var self = {};
/**
* Generates a given emoticon HTML code
* @public
* @param {string} image
* @param {string} text
* @param {string} after
* @return {string}
*/
self.emoteImage = function(image, text, after) {
/* Constants */
self.message_regex = {
'commands': {
'me': /((^)|((.+)(>)))(\/me )([^<]+)/
},
try {
return ' <img class="emoticon emoticon-' + image + ' smileys-images" alt="' + Common.encodeQuotes(text) + '" src="' + './images/others/blank.gif' + '" /> ' + after;
} catch(e) {
Console.error('Filter.emoteImage', e);
'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'
]
}
};
/**
* Filters a given message
* @public
* @param {string} neutralMessage
* @param {string} nick
* @param {string} html_escape
* @return {string}
*/
self.message = function(neutralMessage, nick, html_escape) {
try {
var filteredMessage = neutralMessage;
// 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) {
filteredMessage = Links.apply(filteredMessage, 'desktop');
}
// Filter integratebox links
filteredMessage = IntegrateBox.filter(filteredMessage);
return filteredMessage;
} catch(e) {
Console.error('Filter.message', e);
}
};
/**
* Filters a xHTML message to be displayed in Jappix
* @public
* @param {string} code
* @return {string}
*/
self.xhtml = function(code) {
try {
// Allowed elements array
var elements = new Array(
self.xhtml_allow = {
'elements': [
'a',
'abbr',
'acronym',
@ -171,10 +284,9 @@ var Filter = (function () {
'title',
'ul',
'var'
);
],
// Allowed attributes array
var attributes = new Array(
'attributes': [
'accesskey',
'alt',
'charset',
@ -198,22 +310,123 @@ var Filter = (function () {
'width',
'xml:lang',
'xmlns'
]
};
/**
* Generates a given emoticon HTML code
* @public
* @param {string} image
* @param {string} text
* @param {string} after
* @return {string}
*/
self.emoteImage = function(image, text, after) {
try {
return ' <img class="emoticon emoticon-' + image + ' smileys-images" alt="' + Common.encodeQuotes(text) + '" src="' + './images/others/blank.gif' + '" /> ' + after;
} catch(e) {
Console.error('Filter.emoteImage', e);
}
};
/**
* Filters a given message
* @public
* @param {string} message
* @param {string} nick
* @param {string} html_escape
* @return {string}
*/
self.message = function(message, nick, html_escape) {
try {
var filtered = message;
// We encode the HTML special chars
if(html_escape) {
filtered = filtered.htmlEnc();
}
// Security: don't filter huge messages (avoids crash attacks)
if(filtered.length < 10000) {
// /me command
filtered = filtered.replace(self.message_regex.commands.me, nick + ' $7');
// We replace the smilies text into images
var cur_emote;
for(var cur_emote_name in self.message_regex.emotes) {
cur_emote = self.message_regex.emotes[cur_emote_name];
filtered = filtered.replace(
cur_emote[0],
self.emoteImage(
cur_emote_name,
'$1',
cur_emote[1]
)
);
}
// Text formatting
var cur_formatting;
for(var cur_formatting_name in self.message_regex.formatting) {
cur_formatting = self.message_regex.formatting[cur_formatting_name];
filtered = filtered.replace(
cur_formatting[0],
cur_formatting[1]
);
}
// Add the links
if(html_escape) {
filtered = Links.apply(filtered, 'desktop');
}
// Filter integratebox links
filtered = IntegrateBox.filter(filtered);
}
return filtered;
} catch(e) {
Console.error('Filter.message', e);
}
};
/**
* Filters a xHTML message to be displayed in Jappix
* @public
* @param {string} code
* @return {string}
*/
self.xhtml = function(code) {
try {
var code_sel = $(code);
// Check if Filter for XHTML-IM images is enabled
if(DataStore.getDB(Connection.desktop_hash, 'options', 'no-xhtml-images') != '1') {
elements.push("img");
self.xhtml_allow.elements.push("img");
}
// Remove forbidden elements
$(code).find('html body *').each(function() {
code_sel.find('html body *').each(function() {
// This element is not authorized
if(!Utils.existArrayValue(elements, (this).nodeName.toLowerCase()))
if(!Utils.existArrayValue(self.xhtml_allow.elements, (this).nodeName.toLowerCase())) {
$(this).remove();
}
});
// Remove forbidden attributes
$(code).find('html body *').each(function() {
code_sel.find('html body *').each(function() {
// Put a pointer on this element (jQuery way & normal way)
var cSelector = $(this);
var cElement = (this);
@ -226,15 +439,17 @@ var Filter = (function () {
var cVal = cAttr.value;
// This attribute is not authorized, or contains JS code
if(!Utils.existArrayValue(attributes, cName.toLowerCase()) || ((cVal.toLowerCase()).match(/(^|"|')javascript:/)))
if(!Utils.existArrayValue(self.xhtml_allow.attributes, cName.toLowerCase()) ||
((cVal.toLowerCase()).match(/(^|"|')javascript:/))) {
cSelector.removeAttr(cName);
}
});
});
// Filter some other elements
$(code).find('a').attr('target', '_blank');
code_sel.find('a').attr('target', '_blank');
return $(code).find('html body').html();
return code_sel.find('html body').html();
} catch(e) {
Console.error('Filter.xhtml', e);
}

View file

@ -24,6 +24,196 @@ var Groupchat = (function () {
var JOIN_SUGGEST = [];
/**
* Apply generate events
* @private
* @param {object} input_sel
* @param {string} hash
* @param {string} room
* @return {undefined}
*/
self._createEvents = function(input_sel, hash, room) {
try {
self._createEventsInput(input_sel, hash);
self._createEventsKey(input_sel, hash, room);
} catch(e) {
Console.error('Groupchat._createEvents', e);
}
};
/**
* Apply generate events (input)
* @private
* @param {object} input_sel
* @param {string} hash
* @return {undefined}
*/
self._createEventsInput = function(input_sel, hash) {
try {
// Focus event
input_sel.focus(function() {
// Clean notifications for this chat
Interface.chanCleanNotify(hash);
// Store focus on this chat!
Interface.chat_focus_hash = hash;
});
// Blur event
input_sel.blur(function() {
// Reset storage about focus on this chat!
if(Interface.chat_focus_hash == hash) {
Interface.chat_focus_hash = null;
}
// Reset autocompletion
Autocompletion.reset(hash);
});
} catch(e) {
Console.error('Groupchat._createEventsInput', e);
}
};
/**
* Apply generate events (key)
* @private
* @param {object} input_sel
* @param {string} hash
* @param {string} room
* @return {undefined}
*/
self._createEventsKey = function(input_sel, hash, room) {
try {
// Lock to the input
input_sel.keydown(function(e) {
// Enter key
if(e.keyCode == 13) {
// If shift key (without any others modifiers) was pressed, add a new line
if(e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey) {
input_sel.val(input_sel.val() + '\n');
} else {
if(Correction.isIn(room) === true) {
var corrected_value = input_sel.val().trim();
if(corrected_value) {
// Send the corrected message
Correction.send(room, 'groupchat', corrected_value);
}
Correction.leave(room);
} else {
// Send the message
Message.send(hash, 'groupchat');
// Reset the composing database entry
DataStore.setDB(Connection.desktop_hash, 'chatstate', room, 'off');
}
}
return false;
}
// Remove chars (leave correction)
else if(e.keyCode == 8) {
// Leave correction mode? (another way, by flushing input value progressively)
if(Correction.isIn(room) === true && !input_sel.val()) {
Correction.leave(room);
}
}
// Tabulation key (without any modifiers)
else if(!e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey && e.keyCode == 9) {
Autocompletion.create(hash);
return false;
}
// Reset the autocompleter
else {
Autocompletion.reset(hash);
}
});
input_sel.keyup(function(e) {
if(e.keyCode == 27) {
// Escape key
input_sel.val('');
// Leave correction mode? (simple escape way)
if(Correction.isIn(room) === true) {
Correction.leave(room);
}
} else {
Correction.detect(room, input_sel);
}
});
} catch(e) {
Console.error('Groupchat._createEventsKey', e);
}
};
/**
* Apply suggest check events
* @private
* @return {undefined}
*/
self._suggestCheckEvents = function() {
try {
// Click events
$('#suggest .content a.one').click(function() {
var this_sel = $(this);
// Add/remove the active class
this_sel.toggleClass('active');
// We require at least one room to be chosen
if(Common.exists('#suggest .content a.one.active')) {
$('#suggest a.next').removeClass('disabled');
} else {
$('#suggest a.next').addClass('disabled');
}
return false;
});
$('#suggest a.next').click(function() {
var this_sel = $(this);
// Disabled?
if(this_sel.hasClass('disabled')) {
return false;
}
// Store groupchats to join?
if(this_sel.is('.continue')) {
$('#suggest .content a.one.active').each(function() {
JOIN_SUGGEST.push(this_sel.attr('data-xid'));
});
}
// Switch to talk UI
$('#suggest').remove();
Connection.triggerConnected();
return false;
});
} catch(e) {
Console.error('Groupchat._suggestCheckEvents', e);
}
};
/**
* Displays the MUC admin elements
* @public
@ -37,16 +227,19 @@ var Groupchat = (function () {
try {
// We must be in the "login" mode
if(Utils.isAnonymous())
if(Utils.isAnonymous()) {
return;
}
// We check if the user is a room owner or administrator to give him privileges
if(affiliation == 'owner' || affiliation == 'admin')
if(affiliation == 'owner' || affiliation == 'admin') {
$('#' + id + ' .tools-mucadmin').show();
}
// We check if the room hasn't been yet created
if(statuscode == 201)
if(statuscode == 201) {
Board.openThisInfo(4);
}
// We add the click event
$('#' + id + ' .tools-mucadmin').click(function() {
@ -80,15 +273,17 @@ var Groupchat = (function () {
// No nickname?
if(!nickname) {
// Get some values
if(!Utils.isAnonymous())
if(!Utils.isAnonymous()) {
nickname = Name.getNick();
else
} else {
nickname = ANONYMOUS_NICK;
}
// If the nickname could not be retrieved, ask it
if(!nickname)
if(!nickname) {
self.generateMUCAsk('nickname', room, hash, nickname, password);
}
}
// Got our nickname?
if(nickname) {
@ -126,10 +321,12 @@ var Groupchat = (function () {
var room = Common.bareXID(from);
var nickname = Common.thisResource(from);
var hash = hex_md5(room);
var id = presence.getID();
// No ID: must fix M-Link bug
if(presence.getID() === null) {
presence.setID(1);
if(id === null) {
id = 1;
presence.setID(id);
}
Console.info('First MUC presence: ' + from);
@ -144,6 +341,12 @@ var Groupchat = (function () {
// Handle my presence
Presence.handle(presence);
// Configure the new room
if(affiliation == 'owner' || affiliation == 'admin') {
console.debug('presence', presence.xml());
self._initialConfiguration(id, room);
}
// Check if I am a room owner
self.openAdmin(affiliation, hash, room, statuscode);
@ -279,65 +482,16 @@ var Groupchat = (function () {
});
// Must show the add button?
if(!DataStore.existDB('favorites', room))
if(!DataStore.existDB(Connection.desktop_hash, 'favorites', room)) {
$('#' + hash + ' .tools-add').show();
}
// The event handlers
var inputDetect = $('#' + hash + ' .message-area');
// Focus event
inputDetect.focus(function() {
// Clean notifications for this chat
Interface.chanCleanNotify(hash);
// Store focus on this chat!
Interface.chat_focus_hash = hash;
});
// Blur event
inputDetect.blur(function() {
// Reset storage about focus on this chat!
if(Interface.chat_focus_hash == hash)
Interface.chat_focus_hash = null;
// Reset autocompletion
Autocompletion.reset(hash);
});
// Lock to the input
inputDetect.keydown(function(e) {
// Enter key
if(e.keyCode == 13) {
// If shift key (without any others modifiers) was pressed, add a new line
if(e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey)
inputDetect.val(inputDetect.val() + '\n');
// Send the message
else {
Message.send(hash, 'groupchat');
// Reset the composing database entry
DataStore.setDB(Connection.desktop_hash, 'chatstate', room, 'off');
}
return false;
}
// Tabulation key (without any modifiers)
else if(!e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey && e.keyCode == 9) {
Autocompletion.create(hash);
return false;
}
// Reset the autocompleter
else {
Autocompletion.reset(hash);
}
});
var input_sel = $('#' + hash + ' .message-area');
self._createEvents(input_sel, hash, room);
// Chatstate events
ChatState.events(inputDetect, room, hash, 'groupchat');
ChatState.events(input_sel, room, hash, 'groupchat');
// Get the current muc informations and content
self.getMUC(room, nickname, password);
@ -361,24 +515,27 @@ var Groupchat = (function () {
var new_arr = [];
// Try to split it
if(GROUPCHATS_JOIN.indexOf(',') != -1)
if(GROUPCHATS_JOIN.indexOf(',') != -1) {
muc_arr = GROUPCHATS_JOIN.split(',');
}
for(var i in muc_arr) {
// Get the current value
var muc_current = $.trim(muc_arr[i]);
// No current value?
if(!muc_current)
if(!muc_current) {
continue;
}
// Filter the current value
muc_current = Common.generateXID(muc_current, 'groupchat');
// Add the current value
if(!Utils.existArrayValue(new_arr, muc_current))
if(!Utils.existArrayValue(new_arr, muc_current)) {
new_arr.push(muc_current);
}
}
return new_arr;
} catch(e) {
@ -397,8 +554,9 @@ var Groupchat = (function () {
try {
// Nothing to join?
if(!JOIN_SUGGEST)
if(!JOIN_SUGGEST) {
return;
}
// Join the chats
if(JOIN_SUGGEST.length) {
@ -425,8 +583,9 @@ var Groupchat = (function () {
// Must suggest the user?
if((GROUPCHATS_SUGGEST == 'on') && groupchat_arr.length) {
if(Common.exists('#suggest'))
if(Common.exists('#suggest')) {
return;
}
// Create HTML code
var html = '<div id="suggest" class="removable">';
@ -452,39 +611,8 @@ var Groupchat = (function () {
// Append HTML code
$('body').append(html);
// Click events
$('#suggest .content a.one').click(function() {
// Add/remove the active class
$(this).toggleClass('active');
// We require at least one room to be chosen
if(Common.exists('#suggest .content a.one.active'))
$('#suggest a.next').removeClass('disabled');
else
$('#suggest a.next').addClass('disabled');
return false;
});
$('#suggest a.next').click(function() {
// Disabled?
if($(this).hasClass('disabled')) {
return false;
}
// Store groupchats to join?
if($(this).is('.continue')) {
$('#suggest .content a.one.active').each(function() {
JOIN_SUGGEST.push($(this).attr('data-xid'));
});
}
// Switch to talk UI
$('#suggest').remove();
Connection.triggerConnected();
return false;
});
// Attach events
self._suggestCheckEvents();
} else {
JOIN_SUGGEST = groupchat_arr;
@ -512,7 +640,7 @@ var Groupchat = (function () {
if(!ban_xid) {
Board.openThisInfo(6);
Console.warning('Could not ban user with XID: ' + ban_xid + ' from room: ' + room_xid);
Console.warn('Could not ban user with XID: ' + ban_xid + ' from room: ' + room_xid);
} else {
// We generate the ban IQ
var iq = new JSJaCIQ();
@ -520,10 +648,16 @@ var Groupchat = (function () {
iq.setType('set');
var iqQuery = iq.setQuery(NS_MUC_ADMIN);
var item = iqQuery.appendChild(iq.buildNode('item', {'affiliation': 'outcast', 'jid': ban_xid, 'xmlns': NS_MUC_ADMIN}));
var item = iqQuery.appendChild(iq.buildNode('item', {
'affiliation': 'outcast',
'jid': ban_xid,
'xmlns': NS_MUC_ADMIN
}));
if(reason) {
item.appendChild(iq.buildNode('reason', {'xmlns': NS_MUC_ADMIN}, reason));
item.appendChild(iq.buildNode('reason', {
'xmlns': NS_MUC_ADMIN
}, reason));
}
con.send(iq, Errors.handleReply);
@ -561,10 +695,16 @@ var Groupchat = (function () {
iq.setType('set');
var iqQuery = iq.setQuery(NS_MUC_ADMIN);
var item = iqQuery.appendChild(iq.buildNode('item', {'nick': nick, 'role': 'none', 'xmlns': NS_MUC_ADMIN}));
var item = iqQuery.appendChild(iq.buildNode('item', {
'nick': nick,
'role': 'none',
'xmlns': NS_MUC_ADMIN
}));
if(reason) {
item.appendChild(iq.buildNode('reason', {'xmlns': NS_MUC_ADMIN}, reason));
item.appendChild(iq.buildNode('reason', {
'xmlns': NS_MUC_ADMIN
}, reason));
}
con.send(iq, Errors.handleReply);
@ -671,6 +811,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);
}
};
/**
* Return class scope

View file

@ -20,6 +20,119 @@ var Home = (function () {
var self = {};
/**
* Apply change events
* @private
* @param {object} current_sel
* @param {string} div
* @return {undefined}
*/
self._eventsChange = function(current_sel, div) {
try {
// Create the attached events
switch(div) {
// Login tool
case 'loginer':
current_sel.find('a.to-anonymous').click(function() {
return self.change('anonymouser');
});
current_sel.find('a.advanced').click(self.showAdvanced);
current_sel.find('form').submit(self.loginForm);
break;
// Anonymous login tool
case 'anonymouser':
current_sel.find('a.to-home').click(function() {
return self.change('loginer');
});
current_sel.find('form').submit(Connection.doAnonymous);
// Keyup event on anonymous join's room input
current_sel.find('input.room').keyup(function() {
var value = $(this).val();
var report_sel = current_sel.find('.report');
var span_sel = current_sel.find('span');
if(!value) {
report_sel.hide();
span_sel.text('');
} else {
report_sel.show();
span_sel.text(JAPPIX_LOCATION + '?r=' + value);
}
});
break;
// Register tool
case 'registerer':
// Server input change
$('#home input.server').keyup(function(e) {
if($.trim($(this).val()) == HOST_MAIN) {
$('#home .captcha_grp').show();
$('#home input.captcha').removeAttr('disabled');
} else {
$('#home .captcha_grp').hide();
$('#home input.captcha').attr('disabled', true);
}
});
// Register input placeholder
// FIXME: breaks IE compatibility
//$('#home input[placeholder]').placeholder();
// Register form submit
current_sel.find('form').submit(self.registerForm);
break;
}
} catch(e) {
Console.error('Home._eventsChange', e);
}
};
/**
* Create obsolete form
* @private
* @param {string} home
* @param {string} locale
* @return {undefined}
*/
self._obsolete = function(home, locale) {
try {
// Add the code
$(locale).after(
'<div class="obsolete">' +
'<p>' + Common._e("Your browser is out of date!") + '</p>' +
'<a class="firefox browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Mozilla Firefox') + '" href="http://www.mozilla.com/firefox/"></a>' +
'<a class="chrome browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Google Chrome') + '" href="http://www.google.com/chrome"></a>' +
'<a class="safari browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Safari') + '" href="http://www.apple.com/safari/"></a>' +
'<a class="opera browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Opera') + '" href="http://www.opera.com/"></a>' +
'<a class="ie browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Internet Explorer') + '" href="http://www.microsoft.com/hk/windows/internet-explorer/"></a>' +
'</div>'
);
// Display it later
$(home + '.obsolete').oneTime('1s', function() {
$(this).slideDown();
});
Console.warn('Jappix does not support this browser!');
} catch(e) {
Console.error('Home._obsolete', e);
}
};
/**
* Allows the user to switch the difference home page elements
* @public
@ -76,7 +189,7 @@ var Home = (function () {
'<legend>' + Common._e("Required") + '</legend>' +
'<label for="lnick">' + Common._e("Address") + '</label>' +
'<input type="text" class="nick" id="lnick" pattern="[^@/]+" required="" /><span class="jid">@</span><input type="text" class="server" id="lserver" value="' + HOST_MAIN + '" ' + lock_host + ' pattern="[^@/]+" required="" />' +
'<input type="text" class="nick" id="lnick" pattern="[^@/]+" required="" /><span class="jid">@</span><input type="text" class="server" id="lserver" value="' + HOST_MAIN + '" ' + lock_host + ' pattern="[^@/]+" required="" list="server" />' +
'<label for="lpassword">' + Common._e("Password") + '</label>' +
'<input type="password" class="password" id="lpassword" required="" />' +
'<label for="lremember">' + Common._e("Remember me") + '</label>' +
@ -112,8 +225,9 @@ var Home = (function () {
disable_form = Utils.disableInput(ANONYMOUS, 'off');
code = '<p>' + Common.printf(Common._e("Enter the groupchat you want to join and the nick you want to have. You can also go back to the %s."), '<a href="#" class="to-home">' + Common._e("login page") + '</a>') + '</p>';
if(LEGAL)
if(LEGAL) {
code += '<p>' + Common.printf(Common._e("By using our service, you accept %s."), '<b><a href="' + Common.encodeQuotes(LEGAL) + '" target="_blank">' + Common._e("our terms of use") + '</a></b>') + '</p>';
}
code += '<form action="#" method="post">' +
'<fieldset>' +
@ -139,27 +253,30 @@ var Home = (function () {
case 'registerer':
disable_form = Utils.disableInput(REGISTRATION, 'off');
if(!disable_form)
if(!disable_form) {
lock_host = Utils.disableInput(LOCK_HOST, 'on');
}
code = '<p>' + Common._e("Register a new XMPP account to join your friends on your own social cloud. That's simple!") + '</p>';
if(LEGAL)
if(LEGAL) {
code += '<p>' + Common.printf(Common._e("By using our service, you accept %s."), '<b><a href="' + Common.encodeQuotes(LEGAL) + '" target="_blank">' + Common._e("our terms of use") + '</a></b>') + '</p>';
}
code += '<form action="#" method="post">' +
'<fieldset>' +
'<legend>' + Common._e("Required") + '</legend>' +
'<label for="rnick">' + Common._e("Address") + '</label>' +
'<input type="text" class="nick" id="rnick" ' + disable_form + ' pattern="[^@/]+" required="" placeholder="' + Common._e("Username") + '" /><span class="jid">@</span><input type="text" class="server" id="rserver" value="' + HOST_MAIN + '" ' + disable_form + lock_host + ' pattern="[^@/]+" required="" placeholder="' + Common._e("Server") + '" />' +
'<input type="text" class="nick" id="rnick" ' + disable_form + ' pattern="[^@/]+" required="" placeholder="' + Common._e("Username") + '" /><span class="jid">@</span><input type="text" class="server" id="rserver" value="' + HOST_MAIN + '" ' + disable_form + lock_host + ' pattern="[^@/]+" required="" list="server" placeholder="' + Common._e("Server") + '" />' +
'<label for="rpassword">' + Common._e("Password") + '</label>' +
'<input type="password" class="password" id="rpassword" ' + disable_form + ' required="" placeholder="' + Common._e("Enter password") + '" /><input type="password" class="spassword" id="spassword" ' + disable_form + ' required="" placeholder="' + Common._e("Once again...") + '" />';
if(REGISTER_API == 'on')
if(REGISTER_API == 'on') {
code += '<div class="captcha_grp">' +
'<label for="captcha">' + Common._e("Code") + '</label><input type="text" class="captcha" id="captcha" ' + disable_form + ' maxlength="6" pattern="[a-zA-Z0-9]{6}" required="" placeholder="' + Common._e("Security code") + '" /><img class="captcha_img" src="./server/captcha.php?id=' + genID() + '" alt="" />' +
'</div>';
}
code += '</fieldset>' +
@ -170,78 +287,22 @@ var Home = (function () {
}
// Form disabled?
if(disable_form)
if(disable_form) {
code += '<div class="info fail">' +
Common._e("This tool has been disabled!") +
'</div>';
}
// Create this HTML code
if(code && !Common.exists(current)) {
// Append it!
$(right + '.homediv.default').after('<div class="' + div + ' homediv">' + code + '</div>');
$(right + '.homediv.default').after(
'<div class="' + div + ' homediv">' + code + '</div>'
);
// Create the attached events
switch(div) {
// Login tool
case 'loginer':
$(current + ' a.to-anonymous').click(function() {
return self.change('anonymouser');
});
$(current + ' a.advanced').click(self.showAdvanced);
$(current + ' form').submit(self.loginForm);
break;
// Anonymous login tool
case 'anonymouser':
$(current + ' a.to-home').click(function() {
return self.change('loginer');
});
$(current + ' form').submit(Connection.doAnonymous);
// Keyup event on anonymous join's room input
$(current + ' input.room').keyup(function() {
var value = $(this).val();
var report = current + ' .report';
var span = report + ' span';
if(!value) {
$(report).hide();
$(span).text('');
}
else {
$(report).show();
$(span).text(JAPPIX_LOCATION + '?r=' + value);
}
});
break;
// Register tool
case 'registerer':
// Server input change
$('#home input.server').keyup(function(e) {
if($.trim($(this).val()) == HOST_MAIN) {
$('#home .captcha_grp').show();
$('#home input.captcha').removeAttr('disabled');
} else {
$('#home .captcha_grp').hide();
$('#home input.captcha').attr('disabled', true);
}
});
// Register input placeholder
// FIXME: breaks IE compatibility
//$('#home input[placeholder]').placeholder();
// Register form submit
$(current + ' form').submit(self.registerForm);
break;
}
self._eventsChange(
$(current),
div
);
}
// We focus on the first input
@ -288,13 +349,14 @@ var Home = (function () {
try {
// We get the values
var lPath = '#home .loginer ';
var lServer = $(lPath + '.server').val();
var lNick = Common.nodeprep($(lPath + '.nick').val());
var lPass = $(lPath + '.password').val();
var lResource = $(lPath + '.resource').val();
var lPriority = $(lPath + '.priority').val();
var lRemember = $(lPath + '.remember').filter(':checked').size();
var path_sel = $('#home .loginer');
var lServer = path_sel.find('.server').val();
var lNick = Common.nodeprep(path_sel.find('.nick').val());
var lPass = path_sel.find('.password').val();
var lResource = path_sel.find('.resource').val();
var lPriority = path_sel.find('.priority').val();
var lRemember = path_sel.find('.remember').filter(':checked').size();
// Enough values?
if(lServer && lNick && lPass && lResource && lPriority) {
@ -303,12 +365,13 @@ var Home = (function () {
$(lPath + 'input[type="text"], ' + lPath + 'input[type="password"]').each(function() {
var select = $(this);
if(!select.val())
if(!select.val()) {
$(document).oneTime(10, function() {
select.addClass('please-complete').focus();
});
else
} else {
select.removeClass('please-complete');
}
});
}
} catch(e) {
@ -328,17 +391,18 @@ var Home = (function () {
self.registerForm = function() {
try {
var rPath = '#home .registerer ';
var path = '#home .registerer';
var path_sel = $(path);
// Remove the success info
$(rPath + '.success').remove();
path_sel.find('.success').remove();
// Get the values
var username = Common.nodeprep($(rPath + '.nick').val());
var domain = $(rPath + '.server').val();
var pass = $(rPath + '.password').val();
var spass = $(rPath + '.spassword').val();
var captcha = $(rPath + '.captcha').val();
var username = Common.nodeprep(path_sel.find('.nick').val());
var domain = path_sel.find('.server').val();
var pass = path_sel.find('.password').val();
var spass = path_sel.find('.spassword').val();
var captcha = path_sel.find('.captcha').val();
// Enough values?
if(domain && username && pass && spass && (pass == spass) && !((REGISTER_API == 'on') && (domain == HOST_MAIN) && !captcha)) {
@ -351,15 +415,16 @@ var Home = (function () {
// Something is missing?
else {
$(rPath + 'input[type="text"], ' + rPath + 'input[type="password"]').each(function() {
$(path + ' input[type="text"], ' + path + ' input[type="password"]').each(function() {
var select = $(this);
if(!select.val() || (select.is('#spassword') && pass && (pass != spass)))
if(!select.val() || (select.is('#spassword') && pass && (pass != spass))) {
$(document).oneTime(10, function() {
select.addClass('please-complete').focus();
});
else
} else {
select.removeClass('please-complete');
}
});
}
} catch(e) {
@ -394,12 +459,14 @@ var Home = (function () {
// Allows the user to switch the home page
$(button).click(function() {
// Login button
if($(this).is('.login'))
if($(this).is('.login')) {
return self.change('loginer');
}
// Register button
else
else {
return self.change('registerer');
}
});
// Allows the user to view the corporation & about infobox
@ -430,31 +497,14 @@ var Home = (function () {
// Disables the browser HTTP-requests stopper
$(document).keydown(function(e) {
if((e.keyCode == 27) && !System.isDeveloper())
if((e.keyCode == 27) && !System.isDeveloper()) {
return false;
}
});
// Warns for an obsolete browser
if(Utils.isObsolete()) {
// Add the code
$(locale).after(
'<div class="obsolete">' +
'<p>' + Common._e("Your browser is out of date!") + '</p>' +
'<a class="firefox browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Mozilla Firefox') + '" href="http://www.mozilla.com/firefox/"></a>' +
'<a class="chrome browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Google Chrome') + '" href="http://www.google.com/chrome"></a>' +
'<a class="safari browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Safari') + '" href="http://www.apple.com/safari/"></a>' +
'<a class="opera browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Opera') + '" href="http://www.opera.com/"></a>' +
'<a class="ie browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Internet Explorer') + '" href="http://www.microsoft.com/hk/windows/internet-explorer/"></a>' +
'</div>'
);
// Display it later
$(home + '.obsolete').oneTime('1s', function() {
$(this).slideDown();
});
Console.warn('Jappix does not support this browser!');
self._obsolete();
}
Console.log('Welcome to Jappix! Happy coding in developer mode!');

View file

@ -35,8 +35,6 @@ var HTTPAuth = (function () {
// We add the login wait div
Interface.showGeneralWait();
oArgs = {};
if(Common.hasWebSocket()) {
// WebSocket supported & configured
con = new JSJaCWebSocketConnection({
@ -67,15 +65,6 @@ var HTTPAuth = (function () {
// Generate a priority
lPriority = lPriority ? lPriority : 10;
// We retrieve what the user typed in the login inputs
oArgs = {};
oArgs.domain = $.trim(lServer);
oArgs.username = $.trim(lNick);
oArgs.resource = random_resource;
oArgs.pass = lPass;
oArgs.secure = true;
oArgs.xmllang = XML_LANG;
// Store the resource (for reconnection)
DataStore.setDB(Connection.desktop_hash, 'session', 'resource', random_resource);
@ -89,7 +78,14 @@ var HTTPAuth = (function () {
DataStore.setDB(Connection.desktop_hash, 'priority', 1, 10);
// We connect !
con.connect(oArgs);
con.connect({
'domain': $.trim(lServer),
'username': $.trim(lNick),
'resource': random_resource,
'pass': lPass,
'secure': true,
'xmllang': XML_LANG
});
// Change the page title
Interface.title('wait');

View file

@ -45,11 +45,19 @@ var HTTPReply = (function () {
// If "no"
if(value == 'no') {
aMsg.setType('error');
aMsg.appendNode('error', {'code': '401', 'type': 'auth'});
aMsg.appendNode('error', {
'code': '401',
'type': 'auth'
});
}
// We set the confirm node
aMsg.appendNode('confirm', {'xmlns': xmlns, 'url': url, 'id': id, 'method': method});
aMsg.appendNode('confirm', {
'xmlns': xmlns,
'url': url,
'id': id,
'method': method
});
// We send the message
con.send(aMsg, Errors.handleReply);

View file

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

View file

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

View file

@ -74,8 +74,9 @@ var Interface = (function () {
try {
// Item exists?
if(Common.exists('#general-wait'))
if(Common.exists('#general-wait')) {
return false;
}
// Generate the HTML code
var html =
@ -178,8 +179,9 @@ var Interface = (function () {
var more_content = '#page-switch .more-content';
// Yet displayed?
if(Common.exists(more_content))
if(Common.exists(more_content)) {
return Bubble.close();
}
// Add the bubble
Bubble.show(more_content);
@ -398,31 +400,47 @@ var Interface = (function () {
var type = $('#' + hash).attr('data-type');
var direction = $('html').attr('dir') || 'ltr';
var content_sel = $(content);
// Filter the content smileys
$(content).find('img.emoticon').each(function() {
content_sel.find('img.emoticon').each(function() {
$(this).replaceWith($(this).attr('alt'));
});
// Remove the useless attributes
$(content).removeAttr('data-type').removeAttr('data-stamp');
content_sel.removeAttr('data-type').removeAttr('data-stamp');
// Remove the content avatars
$(content).find('.avatar-container').remove();
content_sel.find('.avatar-container').remove();
// Remove the content info
content_sel.find('.correction-edit, .message-marker, .corrected-info, .correction-label').remove();
// Remove the content click events
$(content).find('a').removeAttr('onclick');
content_sel.find('a').removeAttr('onclick');
// Extract the content HTML code
content = $(content).parent().html();
content = content_sel.parent().html();
// No avatar?
if(!avatar || !avatar.match(/data:/))
if(!avatar || !avatar.match(/data:/)) {
avatar = 'none';
}
// POST the values to the server
$.post('./server/generate-chat.php', { 'content': content, 'xid': xid, 'nick': nick, 'avatar': avatar, 'date': date, 'type': type, 'direction': direction }, function(data) {
$.post('./server/generate-chat.php', {
'content': content,
'xid': xid,
'nick': nick,
'avatar': avatar,
'date': date,
'type': type,
'direction': direction
}, function(data) {
// Handled!
$(path + 'tooltip-waitlog').replaceWith('<a class="tooltip-actionlog" href="./server/download-chat.php?id=' + data + '" target="_blank">' + Common._e("Download file!") + '</a>');
$(path + 'tooltip-waitlog').replaceWith(
'<a class="tooltip-actionlog" href="./server/download-chat.php?id=' + data + '" target="_blank">' + Common._e("Download file!") + '</a>'
);
});
} catch(e) {
Console.error('Interface.generateChatLog', e);
@ -433,6 +451,31 @@ var Interface = (function () {
};
/**
* Returns whether chan has focus or not
* @public
* @param {string} hash
* @return {boolean}
*/
self.hasChanFocus = function(hash) {
var has_focus = true;
try {
if(!$('#page-switch .' + hash).hasClass('activechan') ||
!Common.isFocused() ||
(self.chat_focus_hash != hash)) {
has_focus = false;
}
} catch(e) {
Console.error('Interface.hasChanFocus', e);
} finally {
return has_focus;
}
};
/**
* Notifies the user from a new incoming message
* @public
@ -449,7 +492,7 @@ var Interface = (function () {
var active = $(tested).hasClass('activechan');
// We notify the user if he has not the focus on the chat
if(!active || !Common.isFocused() || (self.chat_focus_hash != hash)) {
if(self.hasChanFocus(hash) === false) {
if(!active) {
if(type == 'personal') {
$(tested + ', ' + chat_switch + 'more-button').addClass('chan-newmessage');
@ -509,10 +552,11 @@ var Interface = (function () {
try {
// Any pending events?
if(Common.exists('.one-counter[data-counter]'))
if(Common.exists('.one-counter[data-counter]')) {
self.title('new');
else
} else {
self.title('talk');
}
} catch(e) {
Console.error('Interface.updateTitle', e);
}
@ -534,8 +578,9 @@ var Interface = (function () {
$(chat_switch + hash).removeClass('chan-newmessage chan-unread');
// We reset the global notifications if no more unread messages
if(!$(chat_switch + 'chans .chan-newmessage').size())
if(!$(chat_switch + 'chans .chan-newmessage').size()) {
$(chat_switch + 'more-button').removeClass('chan-newmessage');
}
// We reset the chat counter
$('#' + hash).removeAttr('data-counter');
@ -598,8 +643,9 @@ var Interface = (function () {
// We show all the groups
$('#roster .one-group').show();
if(Search.search_filtered)
if(Search.search_filtered) {
Search.funnelFilterBuddy();
}
// Store this in the options
if((from == 'roster') && Options.loaded()) {
@ -687,6 +733,39 @@ var Interface = (function () {
$(document).ready(function() {
// Focus on the first visible input
$(window).focus(self.inputFocus);
// Re-focus to visible chat/groupchat input if typing when input blurred
$(document).keypress(function(evt) {
try {
// Don't trigger if not connected or popup opened
if(Common.isConnected() && !Common.exists('div.lock')) {
// Cannot work if an input/textarea is already focused or chat is not opened
var target_input_sel = $('.page-engine-chan .message-area:visible');
if(!target_input_sel.size() || $('input, textarea').is(':focus')) {
return;
}
// Get key value
var key_value = $.trim(String.fromCharCode(evt.which));
// Re-focus on opened chat?
if(key_value) {
// Get input values
value_input = target_input_sel.val();
// Append pressed key value
target_input_sel.val(value_input + key_value);
target_input_sel.focus();
// Put cursor at the end of input
target_input_sel[0].selectionStart = target_input_sel[0].selectionEnd = value_input.length + 1;
}
}
} catch(e) {
Console.error('Interface.launch[autofocus]', e);
}
});
});
} catch(e) {
Console.error('Interface.launch', e);

View file

@ -21,43 +21,41 @@ var IQ = (function () {
/**
* Handles an incoming IQ packet
* @public
* @param {object} iq
* Handles OOB request
* @private
* @param {string} iqType
* @param {string} iqID
* @param {object} iqNode
* @return {undefined}
*/
self.handle = function(iq) {
self._handleOOBRequest = function(iqFrom, iqID, iqNode) {
try {
// Gets the IQ content
var iqNode = iq.getNode();
var iqFrom = Common.fullXID(Common.getStanzaFrom(iq));
var iqID = iq.getID();
var iqQueryXMLNS = iq.getQueryXMLNS();
var iqQuery = iq.getQuery();
var iqType = iq.getType();
// Handle Jingle packet?
JSJaCJingle_route(iq);
// Build the response
var iqResponse = new JSJaCIQ();
iqResponse.setID(iqID);
iqResponse.setTo(iqFrom);
iqResponse.setType('result');
// OOB request
if((iqQueryXMLNS == NS_IQOOB) && (iqType == 'set')) {
/* REF: http://xmpp.org/extensions/xep-0066.html */
OOB.handle(iqFrom, iqID, 'iq', iqNode);
Console.log('Received IQ OOB request: ' + iqFrom);
} catch(e) {
Console.error('IQ._handleOOBRequest', e);
}
// OOB reply
else if(DataStore.getDB(Connection.desktop_hash, 'send/url', iqID)) {
};
/**
* 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);
@ -79,25 +77,51 @@ var IQ = (function () {
// Success?
Notification.create('send_accept', iqFrom, [iqFrom, oob_url, 'iq', iqID, iqNode], oob_desc, notif_id);
}
} catch(e) {
Console.error('IQ._handleOOBReply', e);
}
// Software version query
else if((iqQueryXMLNS == NS_VERSION) && (iqType == 'get')) {
};
/**
* 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}, 'Jappix'));
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);
}
// Last activity query
else if((iqQueryXMLNS == NS_LAST) && (iqType == 'get')) {
};
/**
* 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);
@ -106,10 +130,24 @@ var IQ = (function () {
con.send(iqResponse);
Console.log('Received last activity query: ' + iqFrom);
} catch(e) {
Console.error('IQ._handleLastActivity', e);
}
// Privacy lists push
else if((iqQueryXMLNS == NS_PRIVACY) && (iqType == 'set') && Common.isSafeStanza(iq)) {
};
/**
* 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
@ -121,10 +159,24 @@ var IQ = (function () {
});
Console.log('Received privacy lists push: ' + iqFrom);
} catch(e) {
Console.error('IQ._handlePrivacyLists', e);
}
// Roster push
else if((iqQueryXMLNS == NS_ROSTER) && (iqType == 'set') && Common.isSafeStanza(iq)) {
};
/**
* 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
@ -136,27 +188,53 @@ var IQ = (function () {
});
Console.log('Received roster push: ' + iqFrom);
} catch(e) {
Console.error('IQ._handleRosterPush', e);
}
// Roster Item Exchange query
else if($(iqNode).find('x[xmlns="' + NS_ROSTERX + '"]').size()) {
};
/**
* 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);
}
// Disco info query
else if((iqQueryXMLNS == NS_DISCO_INFO) && (iqType == 'get')) {
};
/**
* 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': 'client',
'type': 'web',
'name': 'Jappix',
'category': Caps.disco_infos.identity.category,
'type': Caps.disco_infos.identity.type,
'name': Caps.disco_infos.identity.name,
'xmlns': NS_DISCO_INFO
}));
@ -170,41 +248,101 @@ var IQ = (function () {
con.send(iqResponse);
Console.log('Received disco#infos query: ' + iqFrom);
} catch(e) {
Console.error('IQ._handleDiscoInfo', e);
}
// User time query
else if($(iqNode).find('time').size() && (iqType == 'get')) {
};
/**
* 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')));
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);
}
// Ping
else if($(iqNode).find('ping').size() && (iqType == 'get')) {
};
/**
* 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);
}
// Jingle
else if($(iqNode).find('jingle').size()) {
};
/**
* 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)
// Handled via JSJaCJingle.route() (see above)
Console.log('Received a Jingle packet: ' + iqFrom);
} catch(e) {
Console.error('IQ._handleJingle', e);
}
// Not implemented
else if(!$(iqNode).find('error').size() && ((iqType == 'get') || (iqType == 'set'))) {
};
/**
* 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');
@ -221,6 +359,95 @@ var IQ = (function () {
con.send(iqResponse);
Console.log('Received an unsupported IQ query from: ' + iqFrom);
} catch(e) {
Console.error('IQ._raiseNotImplemented', e);
}
};
/**
* Handles an incoming IQ packet
* @public
* @param {object} iq
* @return {undefined}
*/
self.handle = function(iq) {
try {
// Gets the IQ content
var iqNode = iq.getNode();
var iqFrom = Common.fullXID(Common.getStanzaFrom(iq));
var iqID = iq.getID();
var iqQueryXMLNS = iq.getQueryXMLNS();
var iqQuery = iq.getQuery();
var iqType = iq.getType();
// Build the response
var iqResponse = new JSJaCIQ();
iqResponse.setID(iqID);
iqResponse.setTo(iqFrom);
iqResponse.setType('result');
// OOB request
if((iqQueryXMLNS == NS_IQOOB) && (iqType == 'set')) {
self._handleOOBRequest(iqFrom, iqID, iqNode);
}
// OOB reply
else if(DataStore.getDB(Connection.desktop_hash, 'send/url', iqID)) {
self._handleOOBReply(iqResponse, iqFrom, iqType, iqID, iqNode);
}
// Software version query
else if((iqQueryXMLNS == NS_VERSION) && (iqType == 'get')) {
self._handleSoftwareVersion(iqResponse, iqFrom);
}
// Last activity query
else if((iqQueryXMLNS == NS_LAST) && (iqType == 'get')) {
self._handleLastActivity(iqResponse, iqFrom);
}
// Privacy lists push
else if((iqQueryXMLNS == NS_PRIVACY) && (iqType == 'set') && Common.isSafeStanza(iq)) {
self._handlePrivacyLists(iqResponse, iqFrom, iqQuery);
}
// Roster push
else if((iqQueryXMLNS == NS_ROSTER) && (iqType == 'set') && Common.isSafeStanza(iq)) {
self._handleRosterPush(iqResponse, iqFrom, iqQuery);
}
// Roster Item Exchange query
else if($(iqNode).find('x[xmlns="' + NS_ROSTERX + '"]').size()) {
self._handleRosterItemExchange(iqNode, iqFrom);
}
// Disco info query
else if((iqQueryXMLNS == NS_DISCO_INFO) && (iqType == 'get')) {
self._handleDiscoInfo(iqResponse, iqFrom);
}
// User time query
else if($(iqNode).find('time').size() && (iqType == 'get')) {
self._handleUserTime(iqResponse, iqFrom);
}
// Ping
else if($(iqNode).find('ping').size() && (iqType == 'get')) {
self._handlePing(iqResponse, iqFrom);
}
// Jingle
else if($(iqNode).find('jingle').size()) {
self._handleJingle(iqFrom);
}
// Not implemented
else if(!$(iqNode).find('error').size() && ((iqType == 'get') || (iqType == 'set'))) {
self._raiseNotImplemented(iqResponse, iqNode, iqFrom);
}
} catch(e) {
Console.error('IQ.handle', e);

File diff suppressed because it is too large Load diff

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
* and modified to break it.
* @author Stefan Strigler steve@zeank.in-berlin.de
* @version $Revision$
* @version 1.3
*/
var JSJaC = {
Version: '$Rev$',
Version: '1.3',
bind: function(fn, obj, optArg) {
return function(arg) {
return fn.apply(obj, [arg, optArg]);
@ -26,9 +26,6 @@ var JSJaC = {
}
};
if (typeof JSJaCConnection == 'undefined')
JSJaC.load();
/* Copyright 2006 Erik Arvidsson
@ -52,7 +49,7 @@ if (typeof JSJaCConnection == 'undefined')
* this code is taken from
* http://webfx.eae.net/dhtml/xmlextras/xmlextras.html
* @author Stefan Strigler steve@zeank.in-berlin.de
* @version $Revision$
* @version 1.3
*/
/**
@ -282,7 +279,7 @@ if (window.XMLSerializer &&
/**
* @fileoverview Collection of functions to make live easier
* @author Stefan Strigler
* @version $Revision$
* @version 1.3
*/
/**
@ -1381,7 +1378,7 @@ JSJaCJSON.parse = function (str) {
* @fileoverview This file contains all things that make life easier when
* dealing with JIDs
* @author Stefan Strigler
* @version $Revision$
* @version 1.3
*/
/**
@ -1714,7 +1711,7 @@ var JSJaCBuilder = {
/**
* @fileoverview Contains all Jabber/XMPP packet related classes.
* @author Stefan Strigler steve@zeank.in-berlin.de
* @version $Revision$
* @version 1.3
*/
var JSJACPACKET_USE_XMLNS = true;
@ -2567,7 +2564,7 @@ function JSJaCKeys(func,oDbg) {
* @fileoverview Contains all things in common for all subtypes of connections
* supported.
* @author Stefan Strigler steve@zeank.in-berlin.de
* @version $Revision$
* @version 1.3
*/
/**
@ -3601,10 +3598,6 @@ JSJaCConnection.prototype._handlePID = function(packet) {
if (!packet.getID())
return false;
if (packet.pType() != 'iq' ||
(packet.getType() != 'error' && packet.getType() != 'result'))
return false;
var jid = packet.getFrom() || this.jid;
if (packet.getFrom() == this.domain)
@ -3723,7 +3716,7 @@ JSJaCConnection.prototype._parseStreamFeatures = function(doc) {
// Get legacy session capability if available
this.legacy_sessions=null;
if (doc.getElementsByTagName("session")[0]) {
if (doc.getElementsByTagName("session")) {
this.legacy_sessions=true;
}
@ -3955,7 +3948,7 @@ JSJaCConnection.prototype._setStatus = function(status) {
/**
* @fileoverview All stuff related to HTTP Binding
* @author Stefan Strigler steve@zeank.in-berlin.de
* @version $Revision$
* @version 1.3
*/
/**
@ -4865,7 +4858,26 @@ JSJaCWebSocketConnection.prototype._parseXml = function(s) {
this.oDbg.log('Parsing: ' + s, 4);
try {
doc = XmlDocument.create('stream', NS_STREAM);
if(s.indexOf('<stream:stream') === -1) {
if(s.trim() == '</stream:stream>') {
// Consider session as closed
this.oDbg.log("session terminated", 1);
clearTimeout(this._timeout); // remove timer
clearInterval(this._interval);
clearInterval(this._inQto);
try {
DataStore.removeDB(MINI_HASH, 'jsjac', 'state');
} catch (e) {}
this._connected = false;
this._handleEvent('onerror',JSJaCError('503','cancel','session-terminate'));
this.oDbg.log("Disconnected.",1);
this._handleEvent('ondisconnect');
return null;
} else if(s.indexOf('<stream:stream') === -1) {
// Wrap every stanza into stream element, so that XML namespaces work properly.
doc.loadXML("<stream:stream xmlns:stream='" + NS_STREAM + "' xmlns='jabber:client'>" + s + "</stream:stream>");
return doc.documentElement.firstChild;
@ -5018,3 +5030,61 @@ JSJaCWebSocketConnection.prototype._sendRaw = function(xml, cb, arg) {
return true;
};
/*exported JSJaCUtils */
/**
* Various utilities put together so that they don't pollute global
* name space.
* @namespace
*/
var JSJaCUtils = {
/**
* XOR two strings of equal length.
* @param {string} s1 first string to XOR.
* @param {string} s2 second string to XOR.
* @return {string} s1 ^ s2.
*/
xor: function(s1, s2) {
/*jshint bitwise: false */
if(!s1) {
return s2;
}
if(!s2) {
return s1;
}
var result = '';
for(var i = 0; i < s1.length; i++) {
result += String.fromCharCode(s1.charCodeAt(i) ^ s2.charCodeAt(i));
}
return result;
},
/**
* Create nonce value of given size.
* @param {int} size size of the nonce that should be generated.
* @return {string} generated nonce.
*/
cnonce: function(size) {
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
var cnonce = '';
for (var i = 0; i < size; i++) {
cnonce += tab.charAt(Math.round(Math.random(new Date().getTime()) * (tab.length - 1)));
}
return cnonce;
},
/**
* Current timestamp.
* @return Seconds since 1.1.1970.
* @type int
*/
now: function() {
if (Date.now && typeof Date.now == 'function') {
return Date.now();
} else {
return new Date().getTime();
}
}
};

View file

@ -34,22 +34,30 @@ var Links = (function () {
var target;
// Links style
if(!style)
if(!style) {
style = '';
else
} else {
style = ' style="' + style + '"';
}
// Open in new tabs
if(mode != 'xhtml-im')
if(mode != 'xhtml-im') {
target = ' target="_blank"';
else
} else {
target = '';
}
// XMPP address
string = string.replace(/(\s|<br \/>|^)(([a-zA-Z0-9\._-]+)@([a-zA-Z0-9\.\/_-]+))(,|\s|$)/gi, '$1<a href="xmpp:$2" target="_blank"' + style + '>$2</a>$5');
string = string.replace(
/(\s|<br \/>|^)(([a-zA-Z0-9\._-]+)@([a-zA-Z0-9\.\/_-]+))(,|\s|$)/gi,
'$1<a href="xmpp:$2" target="_blank"' + style + '>$2</a>$5'
);
// Simple link
string = string.replace(/(\s|<br \/>|^|\()((https?|ftp|file|xmpp|irc|mailto|vnc|webcal|ssh|ldap|smb|magnet|spotify)(:)([^<>'"\s\)]+))/gim, '$1<a href="$2"' + target + style + '>$2</a>');
string = string.replace(
/(\s|<br \/>|^|\()((https?|ftp|file|xmpp|irc|mailto|vnc|webcal|ssh|ldap|smb|magnet|spotify)(:)([^<>'"\s\)]+))/gim,
'$1<a href="$2"' + target + style + '>$2</a>'
);
return string;
} catch(e) {

View file

@ -35,6 +35,7 @@ var MAM = (function () {
self.map_reqs = {};
self.map_pending = {};
self.map_states = {};
self.map_messages = {};
self.msg_queue = {};
@ -311,11 +312,16 @@ var MAM = (function () {
if(c_message[0]) {
// Re-build a proper JSJaC message stanza
var message = JSJaCPacket.wrapNode(c_message[0]);
var message_node = message.getNode();
// Check message type
var type = message.getType() || 'chat';
if(type == 'chat') {
// Display function
var c_display_fn;
var c_display_msg_bool = false;
// Read message data
var xid = Common.bareXID(Common.getStanzaFrom(message));
var id = message.getID();
@ -331,6 +337,8 @@ var MAM = (function () {
var hash = hex_md5(xid);
var body = message.getBody();
// Content message?
if(body) {
// Read delay (required since we deal w/ a past message!)
var time, stamp;
var delay = c_delay.attr('stamp');
@ -341,9 +349,12 @@ var MAM = (function () {
}
// Last-minute checks before display
if(time && stamp && body) {
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);
@ -355,26 +366,71 @@ var MAM = (function () {
};
// 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);
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);
if(c_target_sel().size()) {
// Display the message in that target
c_msg_display();
c_display_fn = function() {
var is_mam_marker = true;
Markers.handle(
from_xid,
message_node,
is_mam_marker
);
};
c_display_msg_bool = (self.map_messages[marked_message_id] === 1) ? true : false;
}
}
// Display message?
if(typeof c_display_fn == 'function') {
if(c_display_msg_bool === true) {
// Display message now
c_display_fn();
} else {
// Delay display (we may not have received the MAM reply ATM)
if(typeof self.msg_queue[xid] != 'object') {
self.msg_queue[xid] = [];
}
self.msg_queue[xid].push(c_msg_display);
self.msg_queue[xid].push(c_display_fn);
}
}
}

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() {
try {
var me_sel = $('#me');
// Click events
$('#me .content a.go').click(function() {
me_sel.find('.content a.go').click(function() {
self.close();
});
$('#me .bottom .finish').click(self.close);
me_sel.find('.bottom .finish').click(self.close);
} catch(e) {
Console.error('Me.instance', e);
}

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

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

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

View file

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

View file

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

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

View file

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

View file

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

View file

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

View file

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

View file

@ -20,6 +20,51 @@ var Smileys = (function () {
var self = {};
/* Constants */
self.emote_list = {
'biggrin': ':-D',
'devil': ']:->',
'coolglasses': '8-)',
'tongue': ':-P',
'smile': ':-)',
'wink': ';-)',
'blush': ':-$',
'stare': ':-|',
'frowning': ':-/',
'oh': '=-O',
'unhappy': ':-(',
'cry': ':\'-(',
'angry': ':-@',
'puke': ':-!',
'hugright': '({)',
'hugleft': '(})',
'lion': ':3',
'pussy': '(@)',
'bat': ':-[',
'kiss': ':-{}',
'heart': '<3',
'brheart': '</3',
'flower': '@}->--',
'brflower': '(W)',
'thumbup': '(Y)',
'thumbdown': '(N)',
'lamp': '(I)',
'coffee': '(C)',
'drink': '(D)',
'beer': '(B)',
'boy': '(Z)',
'girl': '(X)',
'photo': '(P)',
'phone': '(T)',
'music': '(8)',
'cuffs': '(%)',
'mail': '(E)',
'rainbow': '(R)',
'star': '(*)',
'moon': '(S)'
};
/**
* Generates the correct HTML code for an emoticon insertion tool
* @public
@ -43,101 +88,19 @@ var Smileys = (function () {
* Emoticon links arrays
* @public
* @param {string} hash
* @return {object}
* @return {string}
*/
self.links = function(hash) {
try {
var links = '';
var sArray = [
':-D',
']:->',
'8-)',
':-P',
':-)',
';-)',
':-$',
':-|',
':-/',
'=-O',
':-(',
':\'-(',
':-@',
':-!',
'({)',
'(})',
':3',
'(@)',
':-[',
':-{}',
'<3',
'</3',
'@}->--',
'(W)',
'(Y)',
'(N)',
'(I)',
'(C)',
'(D)',
'(B)',
'(Z)',
'(X)',
'(P)',
'(T)',
'(8)',
'(%)',
'(E)',
'(R)',
'(*)',
'(S)'
];
var cArray = [
'biggrin',
'devil',
'coolglasses',
'tongue',
'smile',
'wink',
'blush',
'stare',
'frowning',
'oh',
'unhappy',
'cry',
'angry',
'puke',
'hugright',
'hugleft',
'lion',
'pussy',
'bat',
'kiss',
'heart',
'brheart',
'flower',
'brflower',
'thumbup',
'thumbdown',
'lamp',
'coffee',
'drink',
'beer',
'boy',
'girl',
'photo',
'phone',
'music',
'cuffs',
'mail',
'rainbow',
'star',
'moon'
];
for(var i in sArray) {
links += self.emoteLink(sArray[i], cArray[i], hash);
for(var cur_emote in self.emote_list) {
links += self.emoteLink(
self.emote_list[cur_emote],
cur_emote,
hash
);
}
return links;

View file

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

View file

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

View file

@ -51,8 +51,9 @@ var Talk = (function () {
try {
// Talkpage exists?
if(Common.exists('#talk'))
if(Common.exists('#talk')) {
return false;
}
// Anonymous detector
var anonymous = Utils.isAnonymous();
@ -116,14 +117,14 @@ var Talk = (function () {
if(!anonymous) html +=
'<div class="tools-all">' +
'<div class="tools jingle talk-images" onclick="return Jingle.open();">' +
'<div class="tools call talk-images" onclick="return Call.open();">' +
'<span class="streaming-items">' +
'<span class="counter" data-default="00:00:00">00:00:00</span>' +
'<a class="stop" href="#" onclick="return Jingle.stop();">' + Common._e("Stop") + '</a>' +
'<a class="stop" href="#" onclick="return Call.stop();">' + Common._e("Stop") + '</a>' +
'</span>' +
'</div>' +
'<div class="jingle-content tools-content">' +
'<div class="call-content tools-content">' +
'<div class="tools-content-subarrow talk-images"></div>' +
'<div class="tools-content-subitem"></div>' +
@ -157,6 +158,10 @@ var Talk = (function () {
'<a href="#" class="groupchat talk-images" title="' + Common._e("Your groupchats") + '"></a>' +
'</div>' +
'<div class="roster-muji roster-icon muji-hidable">' +
'<a href="#" class="muji talk-images" title="' + Common._e("Audio/video conference") + '"></a>' +
'</div>' +
'<div class="roster-more roster-icon">' +
'<a href="#" class="more talk-images" title="' + Common._e("More stuff") + '"></a>' +
'</div>' +

View file

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

View file

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

View file

@ -52,8 +52,9 @@ var Utils = (function () {
try {
// HTTPS not allowed
if((HTTPS_STORAGE != 'on') && url.match(/^https(.+)/))
if((HTTPS_STORAGE != 'on') && url.match(/^https(.+)/)) {
url = 'http' + RegExp.$1;
}
return url;
} catch(e) {
@ -217,28 +218,34 @@ var Utils = (function () {
var browser_version = BrowserDetect.version;
// No DOM storage
if(!DataStore.hasDB() || !DataStore.hasPersistent())
if(!DataStore.hasDB() || !DataStore.hasPersistent()) {
return true;
}
// Obsolete IE
if((browser_name == 'Explorer') && (browser_version < 8))
if((browser_name == 'Explorer') && (browser_version < 8)) {
return true;
}
// Obsolete Chrome
if((browser_name == 'Chrome') && (browser_version < 7))
if((browser_name == 'Chrome') && (browser_version < 7)) {
return true;
}
// Obsolete Safari
if((browser_name == 'Safari') && (browser_version < 4))
if((browser_name == 'Safari') && (browser_version < 4)) {
return true;
}
// Obsolete Firefox
if((browser_name == 'Firefox') && (browser_version < 3.5))
if((browser_name == 'Firefox') && (browser_version < 3.5)) {
return true;
}
// Obsolete Opera
if((browser_name == 'Opera') && (browser_version < 9))
if((browser_name == 'Opera') && (browser_version < 9)) {
return true;
}
return false;
} catch(e) {
@ -585,6 +592,33 @@ var Utils = (function () {
};
/**
* Removes duplicate values from array
* @public
* @param {object} arr
* @return {object}
*/
self.uniqueArrayValues = function(arr) {
try {
var a = arr.concat();
for(var i = 0; i < a.length; ++i) {
for(var j = i + 1; j < a.length; ++j) {
if(a[i] === a[j]) {
a.splice(j--, 1);
}
}
}
return a;
} catch(e) {
Console.error('Utils.uniqueArrayValues', e);
}
};
/**
* Converts a string to an array
* @public
@ -603,12 +637,13 @@ var Utils = (function () {
var string_split = string.split(',');
for(var i in string_split) {
if(string_split[i])
if(string_split[i]) {
array.push(string_split[i]);
else
} else {
array.push('');
}
}
}
// Only one item
else
@ -634,8 +669,9 @@ var Utils = (function () {
try {
// Nothing?
if(!array || !array.length)
if(!array || !array.length) {
return 0;
}
// Read the index of the value
var index = 0;

View file

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

View file

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

View file

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

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-linear-gradient(top, #e4eef9 0%, #c5e1ff 100%);
background: -o-linear-gradient(top, #e4eef9 0%, #c5e1ff 100%);
font-size: 13.4px;
font-size: 11px !important;
overflow: hidden;
position: absolute;
top: 0;
bottom: 0;
@ -693,6 +694,22 @@ html[dir="rtl"] #home .right .navigation a {
left: 10px;
}
#home .friendsview .friends .group.standard br {
display: none;
}
#home .friendsview .friends .group.standard a {
text-align: center;
text-decoration: underline;
margin-bottom: 1px;
float: left;
width: 50%;
}
#home .friendsview .friends .group.standard a:nth-child(even) {
float: right;
}
#home .friendsview .friends a.group.refer {
width: 81px;
padding-left: 10px;

View file

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

View file

@ -1,7 +1,7 @@
/*
Jappix - An open social platform
This is the discovery CSS stylesheet for Jappix
This is the Jingle CSS stylesheet for Jappix
-------------------------------------------------
@ -10,47 +10,6 @@ Author: Valérian Saliou
*/
#jingle {
display: none;
}
#jingle .videobox {
background: #ededed;
border: 1px solid rgb(0,0,0);
border: 1px solid rgba(0,0,0,0.8);
text-shadow: none;
min-width: 550px;
min-height: 420px;
overflow: hidden;
position: absolute;
left: 100px;
right: 100px;
top: 40px;
bottom: 40px;
-moz-box-shadow: 0 0 12px rgba(0,0,0,0.4);
-webkit-box-shadow: 0 0 12px rgba(0,0,0,0.4);
box-shadow: 0 0 12px rgba(0,0,0,0.4);
}
#jingle .videobox .topbar {
background: rgb(0,0,0);
background: rgba(0,0,0,0.5);
border-bottom: 1px solid rgb(0,0,0);
border-bottom: 1px solid rgba(0,0,0,0.15);
color: #ffffff;
text-shadow: 0 1px 1px rgb(0,0,0);
text-shadow: 0 1px 1px rgba(0,0,0,0.5);
height: 40px;
position: absolute;
left: 0;
right: 0;
top: 0;
z-index: 4;
-moz-box-shadow: 0 0 5px rgba(0,0,0,0.25);
-webkit-box-shadow: 0 0 5px rgba(0,0,0,0.25);
box-shadow: 0 0 5px rgba(0,0,0,0.25);
}
#jingle .videobox .topbar .card {
margin: 4px 0 0 12px;
}
@ -62,17 +21,13 @@ html[dir="rtl"] #jingle .videobox .topbar .card {
#jingle .videobox .topbar .card,
#jingle .videobox .topbar .card .avatar-container,
#jingle .videobox .topbar .card .identity,
#jingle .videobox .topbar .controls,
#jingle .videobox .topbar .elapsed {
#jingle .videobox .topbar .card .identity {
float: left;
}
html[dir="rtl"] #jingle .videobox .topbar .card,
html[dir="rtl"] #jingle .videobox .topbar .card .avatar-container,
html[dir="rtl"] #jingle .videobox .topbar .card .identity,
html[dir="rtl"] #jingle .videobox .topbar .controls,
html[dir="rtl"] #jingle .videobox .topbar .elapsed {
html[dir="rtl"] #jingle .videobox .topbar .card .identity {
float: right;
}
@ -115,192 +70,8 @@ html[dir="rtl"] #jingle .videobox .topbar .card .identity {
margin-left: 50px;
}
html[dir="rtl"] #jingle .videobox .topbar .controls {
margin-left: 0;
margin-right: 50px;
}
#jingle .videobox .topbar .controls a {
margin-top: 7px;
float: left;
}
html[dir="rtl"] #jingle .videobox .topbar .controls a {
float: right;
}
#jingle .videobox .topbar .controls a,
.jingle-content .jingle-notify .notification-content .reply-buttons a.reply-button {
border-width: 1px;
border-style: solid;
font-size: 10px;
color: #ffffff;
text-transform: uppercase;
text-decoration: none;
padding: 5px 6px 6px 6px;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
border-radius: 2px;
}
#jingle .videobox .topbar .controls a:active,
.jingle-content .jingle-notify .notification-content .reply-buttons a.reply-button:active {
padding-top: 6px;
padding-bottom: 5px;
-webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.25) inset;
-moz-box-shadow: 0 1px 3px rgba(0,0,0,0.25) inset;
box-shadow: 0 1px 3px rgba(0,0,0,0.25) inset;
}
#jingle .videobox .topbar .controls a .icon {
width: 14px;
height: 14px;
margin: -1px 7px 0 2px;
float: left;
}
#jingle .videobox .topbar .controls a.stop,
.jingle-content .jingle-notify .notification-content .reply-buttons a.reply-button.red {
background: #cc283f;
border-color: #5e121d;
}
#jingle .videobox .topbar .controls a.stop:active,
.jingle-content .jingle-notify .notification-content .reply-buttons a.reply-button.red:active {
background: #a92134;
border-color: #480e16;
}
#jingle .videobox .topbar .controls a.stop .icon {
background-position: 0 -62px;
}
.jingle-content .jingle-notify .notification-content .reply-buttons a.reply-button.green {
background: #5ea45e;
border-color: #1a2e1a;
}
.jingle-content .jingle-notify .notification-content .reply-buttons a.reply-button.green:active {
background: #549253;
border-color: #0f1a0f;
}
#jingle .videobox .topbar .controls a.mute,
#jingle .videobox .topbar .controls a.unmute,
.jingle-content .jingle-notify .notification-content .reply-buttons a.reply-button.blue {
background: #6e8dc5;
border-color: #303d55;
}
#jingle .videobox .topbar .controls a.mute,
#jingle .videobox .topbar .controls a.unmute {
margin-left: 6px;
}
html[dir="rtl"] #jingle .videobox .topbar .controls a.mute,
html[dir="rtl"] #jingle .videobox .topbar .controls a.unmute {
margin-left: 0;
margin-right: 6px;
}
#jingle .videobox .topbar .controls a.mute:active,
#jingle .videobox .topbar .controls a.unmute:active,
.jingle-content .jingle-notify .notification-content .reply-buttons a.reply-button.blue:active {
background: #6480b1;
border-color: #222b3b;
}
#jingle .videobox .topbar .controls a.mute .icon {
background-position: 0 -81px;
}
#jingle .videobox .topbar .controls a.unmute {
display: none;
}
#jingle .videobox .topbar .controls a.unmute .icon {
background-position: 0 -100px;
}
#jingle .videobox .topbar .elapsed {
background: rgb(0,0,0);
background: rgba(0,0,0,0.1);
border: 1px solid rgb(255,255,255);
border: 1px solid rgba(255,255,255,0.25);
outline: 1px solid rgb(0,0,0);
outline: 1px solid rgba(0,0,0,0.2);
font-size: 11px;
font-weight: bold;
letter-spacing: 2px;
margin: 10px 0 0 46px;
padding: 2px 6px;
}
html[dir="rtl"] #jingle .videobox .topbar .elapsed {
margin-left: 0;
margin-right: 46px;
}
#jingle .videobox .topbar .actions {
margin: 7px 15px 0 0;
float: right;
}
html[dir="rtl"] #jingle .videobox .topbar .actions {
margin-right: 0;
margin-left: 15px;
float: left;
}
#jingle .videobox .topbar .actions a {
float: left;
}
#jingle .videobox .topbar .actions a.close {
background-position: 0 -44px;
width: 18px;
height: 12px;
margin-top: 6px;
}
#jingle .videobox .local_video {
background-position: 0 -56px;
border: 1px solid rgb(0,0,0);
border: 1px solid rgba(0,0,0,0.5);
width: 180px;
height: 101px;
opacity: 0.6;
overflow: hidden;
position: absolute;
left: 18px;
bottom: 18px;
z-index: 3;
-moz-box-shadow: 0 0 8px rgba(0,0,0,0.25);
-webkit-box-shadow: 0 0 8px rgba(0,0,0,0.25);
box-shadow: 0 0 8px rgba(0,0,0,0.25);
-webkit-transition: all 0.4s ease-in-out 0.2s;
-moz-transition: all 0.4s ease-in-out 0.2s;
-o-transition: all 0.4s ease-in-out 0.2s;
transition: all 0.4s ease-in-out 0.2s;
}
html[dir="rtl"] #jingle .videobox .local_video {
left: auto;
right: 18px;
}
#jingle .videobox .local_video:disabled {
opacity: 0.2 !important;
}
#jingle .videobox .local_video:hover {
width: 320px;
height: 180px;
opacity: 1;
cursor: pointer;
}
#jingle .videobox .remote_video {
background-color: #000000;
width: 100%;
height: 100%;
position: absolute;
@ -311,6 +82,11 @@ html[dir="rtl"] #jingle .videobox .local_video {
z-index: 1;
}
#jingle .videobox .remote_video video {
width: 100%;
height: 100%;
}
#jingle .videobox .branding {
background-position: 0 0;
width: 39px;

View file

@ -114,6 +114,19 @@ input[type="radio"] {
border: 0 none !important;
}
input.input-reset {
background: transparent;
border: 0 none;
margin: 0;
padding: 0;
-moz-border-radius: 0;
-webkit-border-radius: 0;
border-radius: 0;
-moz-box-shadow: none;
-webkit-box-shadow: none;
box-shadow: none;
}
.please-complete,
.please-complete:hover,
.please-complete:focus {
@ -129,4 +142,5 @@ input[type="radio"] {
.clear {
clear: both !important;
display: block !important;
}

View file

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

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,
.commands-hidable,
.privacy-hidable,
.xmpplinks-hidable {
.xmpplinks-hidable,
.muji-hidable {
display: none;
}

View file

@ -327,6 +327,93 @@ html[dir="rtl"] #page-engine .list .user .user-details .avatar-container {
margin-bottom: 10px;
}
#page-engine .one-line {
position: relative;
}
#page-engine .one-line.is-sending {
opacity: 0.6;
}
#page-engine .one-line .correction-edit,
#page-engine .one-line .correction-label,
#page-engine .one-line.user-message[data-edited] .corrected-info,
#page-engine .one-line .message-marker {
font-size: 0.8em;
position: absolute;
right: 0;
top: 0;
}
html[dir="rtl"] #page-engine .one-line .correction-edit,
html[dir="rtl"] #page-engine .one-line .correction-label,
html[dir="rtl"] #page-engine .one-line.user-message[data-edited] .corrected-info,
html[dir="rtl"] #page-engine .one-line .message-marker {
left: 0;
right: auto;
}
#page-engine .one-line .correction-edit,
#page-engine .one-line .correction-label {
border: 1px solid #7f7f7f;
color: black;
font-size: 0.8em;
text-decoration: none;
margin-top: -1px;
padding: 2px 5px;
position: absolute;
right: 0;
top: 0;
}
#page-engine .one-line .correction-edit {
opacity: 0.4;
display: none;
}
#page-engine .page-engine-chan[data-correction="true"] .one-line .correction-edit:hover,
#page-engine .page-engine-chan[data-correction="true"] .one-line .correction-edit:focus {
opacity: 1;
}
#page-engine .one-line.user-message[data-edited] .corrected-info,
#page-engine .one-line .message-marker {
color: #969696;
margin-top: 2px;
}
#page-engine .one-line .message-marker {
display: none;
}
#page-engine .one-line .message-marker.message-marker-read {
background-position: 0 -2227px;
padding-left: 11px;
}
#page-engine .page-engine-chan[data-correction="true"] .one-line.user-message[data-mode="me"]:last-child:hover .correction-edit {
display: block;
}
#page-engine .one-line.correction-active .corrected-info,
#page-engine .one-line.user-message[data-mode="me"]:last-child:hover .corrected-info {
display: none;
}
#page-engine .one-line.correction-active .message-marker,
#page-engine .one-line.user-message[data-mode="me"]:last-child:hover .message-marker {
display: none !important;
}
#page-engine .one-line .message-content {
margin-right: 80px;
}
html[dir="rtl"] #page-engine .one-line .message-content {
margin-right: 0;
margin-left: 80px;
}
#page-engine .one-line,
#page-engine .one-group b.name {
padding-left: 50px;
@ -339,6 +426,10 @@ html[dir="rtl"] #page-engine .one-group b.name {
padding-right: 50px;
}
#page-engine .one-line.correction-active {
opacity: 0.5;
}
#page-engine .one-group b.name {
display: block;
margin-bottom: 4px;
@ -556,7 +647,9 @@ html[dir="rtl"] #page-engine .text .chat-tools-smileys {
}
body.in_jingle_call #page-engine .text .tools-jingle-video,
body.in_jingle_call #page-engine .text .tools-jingle-audio {
body.in_jingle_call #page-engine .text .tools-jingle-audio,
body.in_muji_call #page-engine .text .tools-jingle-video,
body.in_muji_call #page-engine .text .tools-jingle-audio {
opacity: 0.35;
cursor: default;
}
@ -834,22 +927,67 @@ body.in_jingle_call #page-engine .text .tools-jingle-audio {
}
#page-engine .text .compose,
#page-engine .muc-ask {
#page-engine .muc-ask,
#page-engine .correction-toolbox {
position: absolute;
left: 0;
}
#page-engine .text .compose {
#page-engine .text .compose,
#page-engine .correction-toolbox {
top: 29px;
right: 12px;
bottom: 12px;
}
#page-engine .text .compose {
right: 12px;
}
html[dir="rtl"] #page-engine .text .compose {
right: 0;
left: 12px;
}
#page-engine .text.correction-active .compose {
left: 120px;
}
html[dir="rtl"] #page-engine .text.correction-active .compose {
right: 120px;
}
#page-engine .correction-toolbox {
width: 120px;
}
html[dir="rtl"] #page-engine .correction-toolbox {
right: 0;
left: auto;
}
#page-engine .correction-toolbox .correction-editing,
#page-engine .correction-toolbox .correction-cancel {
display: block;
color: black;
font-size: 0.8em;
text-decoration: none;
text-align: center;
margin: 7px 12px;
padding: 2px 5px;
}
#page-engine .correction-toolbox .correction-editing {
font-weight: bold;
margin-top: 8px;
}
#page-engine .correction-toolbox .correction-cancel {
background: #d15e6b;
border: 1px solid #cc273f;
color: white;
text-shadow: 0 1px 1px rgba(0,0,0,0.5);
}
#page-engine .muc-ask {
right: 0;
bottom: 0;
@ -872,6 +1010,21 @@ html[dir="rtl"] #page-engine .text .compose {
border-top-left-radius: 0;
}
#page-engine .text.correction-active textarea {
-moz-border-radius-bottomleft: 0;
-webkit-border-bottom-left-radius: 0;
border-bottom-left-radius: 0;
}
html[dir="rtl"] #page-engine .text.correction-active textarea {
-moz-border-radius-bottomleft: 3px;
-webkit-border-bottom-left-radius: 3px;
border-bottom-left-radius: 3px;
-moz-border-radius-bottomright: 0;
-webkit-border-bottom-right-radius: 0;
border-bottom-right-radius: 0;
}
#page-engine .muc-ask {
background-color: #e8f1f3;
height: 64px;

View file

@ -356,7 +356,10 @@ html[dir="rtl"] .manage-infos p.bm-group input {
background-position: 1px -2047px;
}
body.in_jingle_call .call-jingle {
body.in_jingle_call .call-jingle,
body.in_muji_call .call-jingle,
body.in_jingle_call .roster-muji,
body.in_muji_call .roster-muji {
opacity: 0.35;
}
@ -367,7 +370,10 @@ body.in_jingle_call .call-jingle {
display: none;
}
body.in_jingle_call .call-jingle a {
body.in_jingle_call .call-jingle a,
body.in_muji_call .call-jingle a,
body.in_jingle_call .roster-muji a,
body.in_muji_call .roster-muji a {
cursor: default;
}
@ -470,6 +476,10 @@ html[dir="rtl"] #roster .roster-icon {
background-position: 0 -1082px;
}
#roster .muji {
background-position: 0 -2047px;
}
#roster .more {
background-position: 0 -1100px;
}
@ -521,6 +531,14 @@ html[dir="rtl"] .buddy-conf-subarrow {
float: right;
}
.buddy-conf-muji .buddy-conf-subarrow {
margin-left: 8px;
}
html[dir="rtl"] .buddy-conf-muji .buddy-conf-subarrow {
margin-right: 8px;
}
.buddy-conf-subitem {
background-color: rgb(0,0,0);
background-color: rgba(0,0,0,0.8);

View file

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

Binary file not shown.

Binary file not shown.

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