1
0
Fork 0
mirror of https://github.com/YunoHost-Apps/jappix_ynh.git synced 2024-09-03 19:26:19 +02:00
This commit is contained in:
mbugeia 2014-11-25 22:43:43 +00:00
commit e7f37e06ac
729 changed files with 72298 additions and 193909 deletions

8
README.markdown Normal file
View file

@ -0,0 +1,8 @@
Jappix for Yunohost
============
[Yunohost project](https://yunohost.org/)
Official website: <https://jappix.org/>
Jappix v1.1.2

View file

@ -1,23 +1,24 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<jappix xmlns="jappix:conf:main"> <jappix xmlns="jappix:conf:main">
<name>YunoJappix</name> <name>CHANGENAME</name>
<desc>a free social network</desc> <desc>a free social network</desc>
<owner_name></owner_name> <owner_name></owner_name>
<owner_website></owner_website> <owner_website></owner_website>
<legal></legal> <legal></legal>
<language>CHANGELANG</language> <language>CHANGELANG</language>
<resource>YunoJappix</resource> <resource>CHANGENAME</resource>
<lock>on</lock> <lock>on</lock>
<anonymous>off</anonymous> <anonymous>off</anonymous>
<http_auth>on</http_auth> <http_auth>on</http_auth>
<registration>off</registration> <registration>off</registration>
<manager_link>on</manager_link> <manager_link>on</manager_link>
<groupchats_join></groupchats_join> <groupchats_join>support@conference.yunohost.org</groupchats_join>
<groupchats_suggest>off</groupchats_suggest> <groupchats_suggest>off</groupchats_suggest>
<encryption>on</encryption> <encryption>on</encryption>
<https_storage>off</https_storage> <https_storage>off</https_storage>
<https_force>off</https_force> <https_force>off</https_force>
<compression>off</compression> <compression>off</compression>
<caching>on</caching>
<analytics_track>off</analytics_track> <analytics_track>off</analytics_track>
<analytics_url></analytics_url> <analytics_url></analytics_url>
<analytics_id></analytics_id> <analytics_id></analytics_id>

View file

@ -5,6 +5,7 @@
"en": "A free social network", "en": "A free social network",
"fr": "Un réseau social libre" "fr": "Un réseau social libre"
}, },
"licence": "AGPL v3",
"developer": { "developer": {
"name": "titoko", "name": "titoko",
"email": "titoko@titoko.fr", "email": "titoko@titoko.fr",
@ -16,26 +17,37 @@
{ {
"name": "domain", "name": "domain",
"ask": { "ask": {
"en": "Choose a domain for Jappix" "en": "Choose a domain for Jappix",
"fr": "Choisissez un domaine pour Jappix"
}, },
"example": "domain.org" "example": "domain.org"
}, },
{ {
"name": "path", "name": "path",
"ask": { "ask": {
"en": "Choose a path for Jappix" "en": "Choose a path for Jappix",
"fr": "Choisissez un chemin pour Jappix"
}, },
"example": "/jappix", "example": "/jappix",
"default": "/jappix" "default": "/jappix"
}, },
{
"name": "name",
"ask": {
"en": "Choose a name for Jappix",
"fr": "Choisissez un nom pour Jappix"
},
"example": "YunoJappix",
"default": "YunoJappix"
},
{ {
"name": "language", "name": "language",
"ask": { "ask": {
"en": "Choose the language of the Jappix", "en": "Choose the language of the Jappix",
"fr": "Choissisez la langue du Jappix" "fr": "Choissisez la langue du Jappix"
}, },
"example": "en", "choices" : ["en", "fr", "es"],
"default": "en" "default" : "en"
} }
] ]
} }

15
scripts/backup Normal file
View file

@ -0,0 +1,15 @@
#!/bin/bash
app=jappix
# The parameter $1 is the backup directory location
# which will be compressed afterward
backup_dir=$1/apps/$app
mkdir -p $backup_dir
# Backup sources & data
sudo cp -a /var/www/$app/. $backup_dir/sources
# Copy Nginx and YunoHost parameters to make the script "standalone"
sudo cp -a /etc/yunohost/apps/$app/. $backup_dir/yunohost
domain=$(sudo yunohost app setting $app domain)
sudo cp -a /etc/nginx/conf.d/$domain.d/$app.conf $backup_dir/nginx.conf

View file

@ -3,7 +3,8 @@
# Retrieve arguments # Retrieve arguments
domain=$1 domain=$1
path=$2 path=$2
language=$3 name=$3
language=$4
# Check domain/path availability # Check domain/path availability
sudo yunohost app checkurl $domain$path -a jappix sudo yunohost app checkurl $domain$path -a jappix
@ -15,10 +16,10 @@ fi
path=${path%/} path=${path%/}
# Copy files to the right place # Copy files to the right place
final_path=/var/www/jappix final_path=/var/www/jappix
sudo mkdir -p $final_path sudo mkdir -p $final_path
sudo cp -r ../source/* $final_path sudo cp -r ../source/* $final_path
sudo cp ../conf/*.xml $final_path/store/conf/ sudo cp ../conf/*.xml $final_path/store/conf/
# Set permissions to jappix directory # Set permissions to jappix directory
sudo chown -R www-data: $final_path sudo chown -R www-data: $final_path
@ -36,6 +37,7 @@ then
language="en" language="en"
fi fi
sudo yunohost app setting jappix name -v $language
sudo yunohost app setting jappix language -v $language sudo yunohost app setting jappix language -v $language
sudo sed -i "s@PATHTOCHANGE@$path@g" ../conf/nginx.conf sudo sed -i "s@PATHTOCHANGE@$path@g" ../conf/nginx.conf
@ -45,6 +47,7 @@ sudo sed -i "s@PATHTOCHANGE@$path@g" $final_path/store/conf/main.xml
sudo sed -i "s@PATHTOCHANGE@$path@g" $final_path/store/conf/hosts.xml sudo sed -i "s@PATHTOCHANGE@$path@g" $final_path/store/conf/hosts.xml
sudo sed -i "s@DOMAINTOCHANGE@$domain@g" $final_path/store/conf/main.xml sudo sed -i "s@DOMAINTOCHANGE@$domain@g" $final_path/store/conf/main.xml
sudo sed -i "s@CHANGELANG@$language@g" $final_path/store/conf/main.xml sudo sed -i "s@CHANGELANG@$language@g" $final_path/store/conf/main.xml
sudo sed -i "s@CHANGENAME@$name@g" $final_path/store/conf/main.xml
sudo sed -i "s@DOMAINTOCHANGE@$domain@g" $final_path/store/conf/hosts.xml sudo sed -i "s@DOMAINTOCHANGE@$domain@g" $final_path/store/conf/hosts.xml
# Reload Nginx and regenerate SSOwat conf # Reload Nginx and regenerate SSOwat conf

View file

@ -3,3 +3,11 @@ domain=$(sudo yunohost app setting jappix domain)
sudo rm -rf /var/www/jappix sudo rm -rf /var/www/jappix
sudo rm -f /etc/nginx/conf.d/$domain.d/jappix.conf sudo rm -f /etc/nginx/conf.d/$domain.d/jappix.conf
sudo yunohost app setting jappix domain -d
sudo yunohost app setting jappix path -d
sudo yunohost app setting jappix name -d
sudo yunohost app setting jappix language -d
sudo service nginx reload
sudo yunohost app ssowatconf

16
scripts/restore Normal file
View file

@ -0,0 +1,16 @@
#!/bin/bash
app=jappix
# The parameter $1 is the uncompressed restore directory location
backup_dir=$1/apps/$app
# Restore sources & data
sudo cp -a $backup_dir/sources/. /var/www/$app
# Restore Nginx and YunoHost parameters
sudo cp -a $backup_dir/yunohost/. /etc/yunohost/apps/$app
domain=$(sudo yunohost app setting $app domain)
sudo cp -a $backup_dir/nginx.conf /etc/nginx/conf.d/$domain.d/$app.conf
# Restart webserver
sudo service nginx reload

View file

@ -3,8 +3,13 @@
# Retrieve arguments # Retrieve arguments
domain=$(sudo yunohost app setting jappix domain) domain=$(sudo yunohost app setting jappix domain)
path=$(sudo yunohost app setting jappix path) path=$(sudo yunohost app setting jappix path)
name=$(sudo yunohost app setting jappix name)
language=$(sudo yunohost app setting jappix language) language=$(sudo yunohost app setting jappix language)
if [[ "$name" = "" ]];
then
name="YunoJappix"
fi
if [[ "$language" = "" ]]; if [[ "$language" = "" ]];
then then
language="en" language="en"
@ -37,6 +42,7 @@ sudo sed -i "s@PATHTOCHANGE@$path@g" $final_path/store/conf/main.xml
sudo sed -i "s@PATHTOCHANGE@$path@g" $final_path/store/conf/hosts.xml sudo sed -i "s@PATHTOCHANGE@$path@g" $final_path/store/conf/hosts.xml
sudo sed -i "s@DOMAINTOCHANGE@$domain@g" $final_path/store/conf/main.xml sudo sed -i "s@DOMAINTOCHANGE@$domain@g" $final_path/store/conf/main.xml
sudo sed -i "s@CHANGELANG@$language@g" $final_path/store/conf/main.xml sudo sed -i "s@CHANGELANG@$language@g" $final_path/store/conf/main.xml
sudo sed -i "s@CHANGENAME@$name@g" $final_path/store/conf/main.xml
sudo sed -i "s@DOMAINTOCHANGE@$domain@g" $final_path/store/conf/hosts.xml sudo sed -i "s@DOMAINTOCHANGE@$domain@g" $final_path/store/conf/hosts.xml
# Reload Nginx and regenerate SSOwat conf # Reload Nginx and regenerate SSOwat conf

View file

@ -4,6 +4,71 @@ Jappix Changelog
Here's the log of what has changed over the Jappix releases. Here's the log of what has changed over the Jappix releases.
Primo, v1.1.2 (October 2014)
----------------------------
* XEP-0353: Jingle Message Initiation @valeriansaliou
* Fixes Jingle calls in Chrome 38+ @valeriansaliou
Primo, v1.1.1 (September 2014)
------------------------------
* Ignore empty XHTML-IM messages @eijebong, @valeriansaliou
* Fix a bug with message markers @valeriansaliou
Primo, v1.1.0 (June 2014)
-------------------------
* XEP-0272: Multiparty Jingle (Muji) @valeriansaliou
* Prevent client crash on huge messages @valeriansaliou
* Beautified client code (JavaScript) @valeriansaliou
* Fix unavailable MUC rooms @emamirazavi
One, v1.0.7 (May 2014)
----------------------
* Fix BackLinks design @valeriansaliou
* Sort Jappix Mobile contacts alphabetically @valeriansaliou
* Display offline contacts in Jappix Mini @valeriansaliou
One, v1.0.6 (May 2014)
----------------------
* XEP-0308: Last Message Correction @valeriansaliou
* XEP-0333: Chat Markers @valeriansaliou
* XEP-0319: Last User Interaction into Presence @valeriansaliou
* XEP-0224: Attention @valeriansaliou
* XEP-0152: Reachability Addresses @valeriansaliou
* XEP-0334: Message Processing Hints @valeriansaliou
* Fix gateway contacts management @valeriansaliou
* Fix sounds in Jappix Mini @aryo, @valeriansaliou
One, v1.0.5 (May 2014)
----------------------
* Fix MUC bookmark shortcut button @valeriansaliou
* Fix HTML5 notifications in Firefox 22+ @valeriansaliou
* Fix server commands tool @valeriansaliou
* New translations added (Uzbek), and a few ones updated @nurkamol, @valeriansaliou
One, v1.0.4 (May 2014)
----------------------
* Fix update tool (on some environments) @valeriansaliou
* Fix MUC room join @maranda, @valeriansaliou
* Fix special chars in JIDs for Jappix Mini @dunger, @valeriansaliou
* Fix WebSocket session termination in JSJaC @sstrigler
* Enhance backend security (verify SSL certificates) @valeriansaliou
* Add assets client cache option @valeriansaliou
* Add SSO support to Jappix Mobile @valeriansaliou
One, v1.0.3 (March 2014) One, v1.0.3 (March 2014)
------------------------ ------------------------

View file

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

View file

@ -6,7 +6,7 @@ Jappix is a fresh new open social platform which enables you to create your own
You can build your own Jappix installation for your own requirements: if you want to use it as a personal social client, you can download it and put it on your webserver. It's easy, fast and free. You can build your own Jappix installation for your own requirements: if you want to use it as a personal social client, you can download it and put it on your webserver. It's easy, fast and free.
[![build status](https://ci.frenchtouch.pro/projects/7/status.png?ref=master)](https://ci.frenchtouch.pro/projects/7?ref=master) [![build status](https://ci.hakuma.holdings/projects/7/status.png?ref=master)](https://ci.hakuma.holdings/projects/7?ref=master)
License License
@ -32,9 +32,9 @@ Start translating on https://www.transifex.com/projects/p/jappix/ (new translato
Links Links
----- -----
* Jappix project website: http://jappix.org/ * Jappix project website: https://jappix.org/
* Jappix project dev panel: https://github.com/jappix/jappix * Jappix project dev panel: https://github.com/jappix/jappix
* Jappix nodes list: http://jappix.net/ * Jappix nodes list: https://jappix.net/
* Jappix main service: https://jappix.com/ * Jappix main service: https://jappix.com/
* Jappix commercial support: https://jappix.pro/ * Jappix commercial support: https://jappix.pro/
@ -45,7 +45,7 @@ Mirrors
In case a master service is down (GitHub for Git access or Jappix.org for project download), here is a list of available mirrors: In case a master service is down (GitHub for Git access or Jappix.org for project download), here is a list of available mirrors:
* Project website mirror: https://project.jappix.com/ * Project website mirror: https://project.jappix.com/
* Development repository mirror: https://code.frenchtouch.pro/jappix/jappix * Development repository mirror: https://code.hakuma.holdings/jappix/jappix
MUC Links MUC Links

View file

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

View file

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

View file

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

View file

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

View file

@ -0,0 +1,216 @@
/*
Jappix - An open social platform
Implementation of XEP-0224: Attention
-------------------------------------------------
License: AGPL
Author: Valérian Saliou
*/
// Bundle
var Attention = (function () {
/**
* Alias of this
* @private
*/
var self = {};
/**
* Displays attention message
* @private
* @param {string} xid
* @param {string} body
* @return {undefined}
*/
self._display = function(xid, body, mode) {
try {
var name = Name.getBuddy(xid).htmlEnc();
var hash = hex_md5(xid);
// Compute some variables
var message = Common._e(Common.printf("You requested %s's attention to the conversation", name));
if(mode == 'him') {
message = Common._e(Common.printf("%s requested your attention to the conversation", name));
}
if(body) {
message += ' (' + body + ')';
}
// Display notification
Message.display(
'chat',
xid,
hash,
name,
message,
DateUtils.getCompleteTime(),
DateUtils.getTimeStamp(),
'system-message',
true,
undefined,
mode
);
// Add a marker to displayed message
$('#' + hash + ' .content .one-line.system-message:last').addClass('attention-notice');
} catch(e) {
Console.error('Attention._display', e);
}
};
/**
* Sends attention stanza
* @private
* @param {string} xid
* @param {string} body
* @return {object}
*/
self._stanza = function(xid, body) {
try {
var message = new JSJaCMessage();
message.setType('headline');
message.setTo(xid);
if(body) {
message.setBody(body);
}
// Attention node
message.appendNode('attention', {
'xmlns': NS_URN_ATTENTION
});
con.send(message);
return message;
} catch(e) {
Console.error('Attention._stanza', e);
}
};
/**
* Returns whether last attention message exists or not
* @private
* @param {string} xid
* @return {boolean}
*/
self._lastExists = function(xid, mode) {
var last_exists = false;
try {
var line_sel = $('#' + hex_md5(xid) + ' .content .one-line[data-mode="' + mode + '"]:last');
last_exists = line_sel.is('.system-message.attention-notice') ? true : false;
} catch(e) {
Console.error('Attention._lastExists', e);
} finally {
return last_exists;
}
};
/**
* Return whether entity supports attention notifications
* @public
* @param {string} xid
* @return {boolean}
*/
self.hasSupport = function(xid) {
var has_support = false;
try {
has_support = true ? $('#' + hex_md5(xid)).attr('data-attention') == 'true' : false;
} catch(e) {
Console.error('Attention.hasSupport', e);
} finally {
return has_support;
}
};
/**
* Send an attention message
* @public
* @param {string} xid
* @param {string} body
* @return {undefined}
*/
self.send = function(xid, body) {
try {
var mode = 'me';
// Don't send attention message twice
if(self._lastExists(xid, mode) === false) {
// Send message stanza
self._stanza(xid, body);
// Display attention notification
self._display(xid, body, mode);
} else {
Console.debug('Attention.send', 'Not sending attention message to: ' + xid + ' because already sent.');
}
} catch(e) {
Console.error('Attention.send', e);
}
};
/**
* Receive an attention notification
* @public
* @param {string} xid
* @return {undefined}
*/
self.receive = function(xid, body) {
try {
var mode = 'him';
var hash = hex_md5(xid);
// Don't receive attention message twice
if((self._lastExists(xid, mode) === false) && Common.exists('#' + hash)) {
// Display attention notification
self._display(xid, body, mode);
// Show a notification
Interface.messageNotify(hash, 'personal');
Audio.play('catch-attention');
Board.quick(
xid,
'chat',
Common._e("Attention to conversation requested."),
Name.getBuddy(xid)
);
}
} catch(e) {
Console.error('Attention.receive', e);
}
};
/**
* Return class scope
*/
return self;
})();

View file

@ -29,7 +29,7 @@ var Audio = (function () {
* @private * @private
* @return {boolean} * @return {boolean}
*/ */
self._is_supported = function() { self._isSupported = function() {
is_supported = true; is_supported = true;
@ -38,7 +38,7 @@ var Audio = (function () {
is_supported = false; is_supported = false;
} }
} catch(e) { } catch(e) {
Console.error('Audio._is_supported', e); Console.error('Audio._isSupported', e);
} finally { } finally {
return is_supported; return is_supported;
} }
@ -47,23 +47,13 @@ var Audio = (function () {
/** /**
* Plays the given sound ID * Append audio DOM code
* @public * @private
* @param {string} name * @return {undefined}
* @return {boolean}
*/ */
self.play = function(name, repeat) { self._appendDOM = function() {
try { 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 the audio elements aren't yet in the DOM
if(!Common.exists('#audio')) { if(!Common.exists('#audio')) {
$('body').append( $('body').append(
@ -83,6 +73,11 @@ var Audio = (function () {
'<source src="' + './sounds/notification.oga' + '" />' + '<source src="' + './sounds/notification.oga' + '" />' +
'</audio>' + '</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">' + '<audio id="incoming-call" preload="auto" data-duration="7">' +
'<source src="' + './sounds/incoming-call.mp3' + '" />' + '<source src="' + './sounds/incoming-call.mp3' + '" />' +
'<source src="' + './sounds/incoming-call.oga' + '" />' + '<source src="' + './sounds/incoming-call.oga' + '" />' +
@ -95,6 +90,32 @@ var Audio = (function () {
'</div>' '</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 // We play the target sound
var audio_raw_sel = $('#audio audio').filter('#' + name); var audio_raw_sel = $('#audio audio').filter('#' + name);
@ -146,7 +167,7 @@ var Audio = (function () {
try { try {
// Not supported? // Not supported?
if(!self._is_supported()) { if(!self._isSupported()) {
return false; return false;
} }

View file

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

View file

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

View file

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

View file

@ -6,9 +6,9 @@
var BrowserDetect = { var BrowserDetect = {
init: function () { init: function () {
this.browser = this.searchString(this.dataBrowser) || "An unknown browser"; this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
this.version = this.searchVersion(navigator.userAgent) this.version = this.searchVersion(navigator.userAgent) ||
|| this.searchVersion(navigator.appVersion) this.searchVersion(navigator.appVersion) ||
|| "an unknown version"; "an unknown version";
this.OS = this.searchString(this.dataOS) || "an unknown OS"; this.OS = this.searchString(this.dataOS) || "an unknown OS";
}, },

View file

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

File diff suppressed because it is too large Load diff

View file

@ -20,34 +20,15 @@ var Caps = (function () {
var self = {}; var self = {};
/** /* Constants */
* Reads a stored Caps self.disco_infos = {
* @public 'identity': {
* @param {string} caps 'category': 'client',
* @return {object} 'type': 'web',
*/ 'name': 'Jappix'
self.read = function(caps) { },
try { 'items': [
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 = [
NS_MUC, NS_MUC,
NS_MUC_USER, NS_MUC_USER,
NS_MUC_ADMIN, NS_MUC_ADMIN,
@ -96,13 +77,420 @@ var Caps = (function () {
NS_PRIVACY, NS_PRIVACY,
NS_IQOOB, NS_IQOOB,
NS_XOOB, 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); var disco_all = disco_base.concat(disco_jingle);
return disco_all; return Utils.uniqueArrayValues(disco_all);
} catch(e) { } catch(e) {
Console.error('Caps.myDiscoInfos', e); Console.error('Caps.myDiscoInfos', e);
} }
@ -169,103 +557,17 @@ var Caps = (function () {
self.handleDiscoInfos = function(iq) { self.handleDiscoInfos = function(iq) {
try { try {
if(!iq || (iq.getType() == 'error')) if(!iq || (iq.getType() == 'error')) {
return; return;
}
// IQ received, get some values
var from = Common.fullXID(Common.getStanzaFrom(iq)); var from = Common.fullXID(Common.getStanzaFrom(iq));
var query = iq.getQuery(); var query = iq.getQuery();
// Generate the CAPS-processing values // Parse values
var identities = []; var identities = self._parseDiscoIdentities(query);
var features = []; var features = self._parseDiscoFeatures(query);
var data_forms = []; var data_forms = self._parseDiscoDataForms(query);
// Identity values
$(query).find('identity').each(function() {
var pCategory = $(this).attr('category');
var pType = $(this).attr('type');
var pLang = $(this).attr('xml:lang');
var pName = $(this).attr('name');
if(!pCategory)
pCategory = '';
if(!pType)
pType = '';
if(!pLang)
pLang = '';
if(!pName)
pName = '';
identities.push(pCategory + '/' + pType + '/' + pLang + '/' + pName);
});
// Feature values
$(query).find('feature').each(function() {
var pVar = $(this).attr('var');
// Add the current value to the array
if(pVar)
features.push(pVar);
});
// Data-form values
$(query).find('x[xmlns="' + NS_XDATA + '"]').each(function() {
// Initialize some stuffs
var pString = '';
var sortVar = [];
// Add the form type field
$(this).find('field[var="FORM_TYPE"] value').each(function() {
var cText = $(this).text();
if(cText)
pString += cText + '<';
});
// Add the var attributes into an array
$(this).find('field:not([var="FORM_TYPE"])').each(function() {
var cVar = $(this).attr('var');
if(cVar)
sortVar.push(cVar);
});
// Sort the var attributes
sortVar = sortVar.sort();
// Loop this sorted var attributes
$.each(sortVar, function(i) {
// Initialize the value sorting
var sortVal = [];
// Append it to the string
pString += sortVar[i] + '<';
// Add each value to the array
$(this).find('field[var=' + sortVar[i] + '] value').each(function() {
sortVal.push($(this).text());
});
// Sort the values
sortVal = sortVal.sort();
// Append the values to the string
for(var j in sortVal) {
pString += sortVal[j] + '<';
}
});
// Any string?
if(pString) {
// Remove the undesired double '<' from the string
if(pString.match(/(.+)(<)+$/))
pString = pString.substring(0, pString.length - 1);
// Add the current string to the array
data_forms.push(pString);
}
});
// Process the CAPS // Process the CAPS
var caps = self.process(identities, features, data_forms); var caps = self.process(identities, features, data_forms);
@ -309,8 +611,9 @@ var Caps = (function () {
var xid = Common.bareXID(from); var xid = Common.bareXID(from);
// This comes from a private groupchat chat? // This comes from a private groupchat chat?
if(Utils.isPrivate(xid)) if(Utils.isPrivate(xid)) {
xid = from; xid = from;
}
hash = hex_md5(xid); hash = hex_md5(xid);
@ -326,96 +629,20 @@ var Caps = (function () {
}); });
// Paths // Paths
var path = $('#' + hash); var path_sel = $('#' + hash);
var roster_path = $('#roster .buddy.' + hash); var roster_sel = $('#roster .buddy.' + hash);
var roster_jingle_path = roster_path.find('.buddy-infos .call-jingle'); var message_area_sel = path_sel.find('.message-area');
var style_sel = path_sel.find('.chat-tools-style');
var file_sel = path_sel.find('.chat-tools-file');
var message_area = path.find('.message-area'); // Apply Features
var style = path.find('.chat-tools-style'); self._applyDiscoXHTMLIM(xid, features, style_sel, message_area_sel);
var jingle_audio = path.find('.tools-jingle-audio'); self._applyDiscoJingle(xid, path_sel, roster_sel);
var roster_jingle_audio = roster_jingle_path.find('a.audio'); self._applyDiscoOOB(xid, features, file_sel);
var jingle_video = path.find('.tools-jingle-video'); self._applyDiscoReceipts(xid, features, message_area_sel);
var roster_jingle_video = roster_jingle_path.find('a.video'); self._applyDiscoCorrection(xid, features, path_sel);
var roster_jingle_separator = roster_jingle_path.find('span.separator'); self._applyDiscoMarkers(xid, features, path_sel);
var file = path.find('.chat-tools-file'); self._applyDiscoAttention(xid, features, path_sel);
// 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');
}
} catch(e) { } catch(e) {
Console.error('Caps.displayDiscoInfos', e); Console.error('Caps.displayDiscoInfos', e);
} }
@ -426,39 +653,39 @@ var Caps = (function () {
/** /**
* Generates the CAPS hash * Generates the CAPS hash
* @public * @public
* @param {object} cIdentities * @param {object} identities
* @param {object} cFeatures * @param {object} features
* @param {object} cDataForms * @param {object} dataforms
* @return {string} * @return {string}
*/ */
self.process = function(cIdentities, cFeatures, cDataForms) { self.process = function(identities, features, dataforms) {
try { try {
// Initialize // Initialize
var cString = ''; var caps_str = '';
// Sort the arrays // Sort the arrays
cIdentities = cIdentities.sort(); identities = identities.sort();
cFeatures = cFeatures.sort(); features = features.sort();
cDataForms = cDataForms.sort(); dataforms = dataforms.sort();
// Process the sorted identity string // Process the sorted identity string
for(var a in cIdentities) { for(var a in identities) {
cString += cIdentities[a] + '<'; caps_str += identities[a] + '<';
} }
// Process the sorted feature string // Process the sorted feature string
for(var b in cFeatures) { for(var b in features) {
cString += cFeatures[b] + '<'; caps_str += features[b] + '<';
} }
// Process the sorted data-form string // Process the sorted data-form string
for(var c in cDataForms) { for(var c in dataforms) {
cString += cDataForms[c] + '<'; caps_str += dataforms[c] + '<';
} }
// Process the SHA-1 hash // Process the SHA-1 hash
var cHash = b64_sha1(cString); var cHash = b64_sha1(caps_str);
return cHash; return cHash;
} catch(e) { } catch(e) {
@ -477,7 +704,12 @@ var Caps = (function () {
try { try {
return self.process( return self.process(
['client/web//Jappix'], [
self.disco_infos.identity.category + '/' +
self.disco_infos.identity.type + '//' +
self.disco_infos.identity.name
],
self.myDiscoInfos(), self.myDiscoInfos(),
[] []
); );
@ -507,8 +739,14 @@ var Caps = (function () {
var max_priority = null; var max_priority = null;
var cur_xid_full, cur_presence_sel, cur_caps, cur_features, cur_priority; var cur_xid_full, cur_presence_sel, cur_caps, cur_features, cur_priority;
for(var cur_resource in Presence.resources(xid)) { var resources_obj = Presence.resources(xid);
cur_xid_full = xid + '/' + cur_resource; var fn_parse_resource = function(cur_resource) {
cur_xid_full = xid;
if(cur_resource) {
cur_xid_full += '/' + cur_resource;
}
cur_presence_sel = $(Presence.readStanza(cur_xid_full)); cur_presence_sel = $(Presence.readStanza(cur_xid_full));
cur_priority = parseInt((cur_presence_sel.find('priority').text() || 0), 10); cur_priority = parseInt((cur_presence_sel.find('priority').text() || 0), 10);
@ -523,6 +761,14 @@ var Caps = (function () {
selected_xid = cur_xid_full; selected_xid = cur_xid_full;
} }
} }
};
if(resources_obj.bare === 1) {
fn_parse_resource(null);
}
for(var cur_resource in resources_obj.list) {
fn_parse_resource(cur_resource);
} }
} catch(e) { } catch(e) {
Console.error('Caps.getFeatureResource', e); Console.error('Caps.getFeatureResource', e);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -103,7 +103,7 @@ var Features = (function () {
}; };
// Markers // Markers
var namespaces = [NS_PUBSUB, NS_PUBSUB_CN, NS_URN_MAM, NS_COMMANDS, NS_URN_CARBONS]; var namespaces = [NS_PUBSUB, NS_PUBSUB_CN, NS_URN_MAM, NS_COMMANDS, NS_URN_CARBONS, NS_URN_CORRECT];
var identity = selector.find('identity'); var identity = selector.find('identity');
@ -219,6 +219,11 @@ var Features = (function () {
$(path + 'mam-purge-hidable').show(); $(path + 'mam-purge-hidable').show();
} }
// Message correction features
if(self.enabledCorrection()) {
$(path + 'correction-hidable').show();
}
// Commands features // Commands features
if(self.enabledCommands()) { if(self.enabledCommands()) {
$(path + 'commands-hidable').show(); $(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 * Normalizes the XMPP server name
* @private * @private

View file

@ -20,123 +20,236 @@ var Filter = (function () {
var self = {}; var self = {};
/** /* Constants */
* Generates a given emoticon HTML code self.message_regex = {
* @public 'commands': {
* @param {string} image 'me': /((^)|((.+)(>)))(\/me )([^<]+)/
* @param {string} text },
* @param {string} after
* @return {string}
*/
self.emoteImage = function(image, text, after) {
try { 'emotes': {
return ' <img class="emoticon emoticon-' + image + ' smileys-images" alt="' + Common.encodeQuotes(text) + '" src="' + './images/others/blank.gif' + '" /> ' + after; 'angry': [
} catch(e) { /(:-?@)($|\s|<)/gi,
Console.error('Filter.emoteImage', e); '$2'
],
'bat': [
/(:-?\[)($|\s|<)/gi,
'$2'
],
'beer': [
/(\(B\))($|\s|<)/g,
'$2'
],
'biggrin': [
/((:-?D)|(XD))($|\s|<)/gi,
'$4'
],
'blush': [
/(:-?\$)($|\s|<)/gi,
'$2'
],
'boy': [
/(\(Z\))($|\s|<)/g,
'$2'
],
'brflower': [
/(\(W\))($|\s|<)/g,
'$2'
],
'brheart': [
/((&lt;\/3)|(\(U\)))($|\s|<)/g,
'$4'
],
'coffee': [
/(\(C\))($|\s|<)/g,
'$2'
],
'coolglasses': [
/((8-\))|(\(H\)))($|\s|<)/g,
'$4'
],
'cry': [
/(:'-?\()($|\s|<)/gi,
'$2'
],
'cuffs': [
/(\(%\))($|\s|<)/g,
'$2'
],
'devil': [
/(\]:-?&gt;)($|\s|<)/gi,
'$2'
],
'drink': [
/(\(D\))($|\s|<)/g,
'$2'
],
'flower': [
/(@}-&gt;--)($|\s|<)/gi,
'$2'
],
'frowning': [
/((:-?\/)|(:-?S))($|\s|<)/gi,
'$4'
],
'girl': [
/(\(X\))($|\s|<)/g,
'$2'
],
'heart': [
/((&lt;3)|(\(L\)))($|\s|<)/g,
'$4'
],
'hugleft': [
/(\(}\))($|\s|<)/g,
'$2'
],
'hugright': [
/(\({\))($|\s|<)/g,
'$2'
],
'kis': [
/(:-?{})($|\s|<)/gi,
'$2'
],
'lamp': [
/(\(I\))($|\s|<)/g,
'$2'
],
'lion': [
/(:-?3)($|\s|<)/gi,
'$2'
],
'mail': [
/(\(E\))($|\s|<)/g,
'$2'
],
'moon': [
/(\(S\))($|\s|<)/g,
'$2'
],
'music': [
/(\(8\))($|\s|<)/g,
'$2'
],
'oh': [
/((=-?O)|(:-?O))($|\s|<)/gi,
'$4'
],
'phone': [
/(\(T\))($|\s|<)/g,
'$2'
],
'photo': [
/(\(P\))($|\s|<)/g,
'$2'
],
'puke': [
/(:-?!)($|\s|<)/gi,
'$2'
],
'pussy': [
/(\(@\))($|\s|<)/g,
'$2'
],
'rainbow': [
/(\(R\))($|\s|<)/g,
'$2'
],
'smile': [
/(:-?\))($|\s|<)/gi,
'$2'
],
'star': [
/(\(\*\))($|\s|<)/g,
'$2'
],
'stare': [
/(:-?\|)($|\s|<)/gi,
'$2'
],
'thumbdown': [
/(\(N\))($|\s|<)/g,
'$2'
],
'thumbup': [
/(\(Y\))($|\s|<)/g,
'$2'
],
'tongue': [
/(:-?P)($|\s|<)/gi,
'$2'
],
'unhappy': [
/(:-?\()($|\s|<)/gi,
'$2'
],
'wink': [
/(;-?\))($|\s|<)/gi,
'$2'
]
},
'formatting': {
'bold': [
/(^|\s|>|\()((\*)([^<>'"\*]+)(\*))($|\s|<|\))/gi,
'$1<b>$2</b>$6'
],
'italic': [
/(^|\s|>|\()((\/)([^<>'"\/]+)(\/))($|\s|<|\))/gi,
'$1<em>$2</em>$6'
],
'underline': [
/(^|\s|>|\()((_)([^<>'"_]+)(_))($|\s|<|\))/gi,
'$1<span style="text-decoration: underline;">$2</span>$6'
]
} }
}; };
self.xhtml_allow = {
/** 'elements': [
* 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(
'a', 'a',
'abbr', 'abbr',
'acronym', 'acronym',
@ -171,10 +284,9 @@ var Filter = (function () {
'title', 'title',
'ul', 'ul',
'var' 'var'
); ],
// Allowed attributes array 'attributes': [
var attributes = new Array(
'accesskey', 'accesskey',
'alt', 'alt',
'charset', 'charset',
@ -198,22 +310,149 @@ var Filter = (function () {
'width', 'width',
'xml:lang', 'xml:lang',
'xmlns' '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);
}
};
/**
* Returns whether XHTML body exists or not
* @public
* @param {DOM} xhtml_sel
* @return {boolean}
*/
self.has_xhtml_body = function(xhtml_sel) {
var has_xhtml_body = false;
try {
xhtml_sel.find('*').each(function() {
if($(this).text()) {
has_xhtml_body = true;
return false;
}
});
} catch(e) {
Console.error('Filter.has_xhtml_body', e);
} finally {
return has_xhtml_body;
}
};
/**
* 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 // Check if Filter for XHTML-IM images is enabled
if(DataStore.getDB(Connection.desktop_hash, 'options', 'no-xhtml-images') != '1') { if(DataStore.getDB(Connection.desktop_hash, 'options', 'no-xhtml-images') != '1') {
elements.push("img"); self.xhtml_allow.elements.push("img");
} }
// Remove forbidden elements // Remove forbidden elements
$(code).find('html body *').each(function() { code_sel.find('html body *').each(function() {
// This element is not authorized // This element is not authorized
if(!Utils.existArrayValue(elements, (this).nodeName.toLowerCase())) if(!Utils.existArrayValue(self.xhtml_allow.elements, (this).nodeName.toLowerCase())) {
$(this).remove(); $(this).remove();
}
}); });
// Remove forbidden attributes // Remove forbidden attributes
$(code).find('html body *').each(function() { code_sel.find('html body *').each(function() {
// Put a pointer on this element (jQuery way & normal way) // Put a pointer on this element (jQuery way & normal way)
var cSelector = $(this); var cSelector = $(this);
var cElement = (this); var cElement = (this);
@ -226,15 +465,17 @@ var Filter = (function () {
var cVal = cAttr.value; var cVal = cAttr.value;
// This attribute is not authorized, or contains JS code // This attribute is not authorized, or contains JS code
if(!Utils.existArrayValue(attributes, cName.toLowerCase()) || ((cVal.toLowerCase()).match(/(^|"|')javascript:/))) if(!Utils.existArrayValue(self.xhtml_allow.attributes, cName.toLowerCase()) ||
((cVal.toLowerCase()).match(/(^|"|')javascript:/))) {
cSelector.removeAttr(cName); cSelector.removeAttr(cName);
}
}); });
}); });
// Filter some other elements // Filter some other elements
$(code).find('a').attr('target', '_blank'); code_sel.find('a').attr('target', '_blank');
return $(code).find('html body').html(); return code_sel.find('html body').html();
} catch(e) { } catch(e) {
Console.error('Filter.xhtml', e); Console.error('Filter.xhtml', e);
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -140,7 +140,7 @@ var addToHome = (function (w) {
options.message = ''; options.message = '';
} }
if ( options.message === '' ) { // We look for a suitable language (defaulted to en_us) if ( options.message === '' ) { // We look for a suitable language (defaulted to en_us)
options.message = language in intl ? intl[language] : intl['en_us']; options.message = language in intl ? intl[language] : intl.en_us;
} }
if ( options.touchIcon ) { if ( options.touchIcon ) {

View file

@ -21,43 +21,41 @@ var IQ = (function () {
/** /**
* Handles an incoming IQ packet * Handles OOB request
* @public * @private
* @param {object} iq * @param {string} iqType
* @param {string} iqID
* @param {object} iqNode
* @return {undefined} * @return {undefined}
*/ */
self.handle = function(iq) { self._handleOOBRequest = function(iqFrom, iqID, iqNode) {
try { 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 */ /* REF: http://xmpp.org/extensions/xep-0066.html */
OOB.handle(iqFrom, iqID, 'iq', iqNode); OOB.handle(iqFrom, iqID, 'iq', iqNode);
Console.log('Received IQ OOB request: ' + iqFrom); 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 // Get the values
var oob_url = DataStore.getDB(Connection.desktop_hash, 'send/url', iqID); var oob_url = DataStore.getDB(Connection.desktop_hash, 'send/url', iqID);
var oob_desc = DataStore.getDB(Connection.desktop_hash, 'send/desc', iqID); var oob_desc = DataStore.getDB(Connection.desktop_hash, 'send/desc', iqID);
@ -79,25 +77,51 @@ var IQ = (function () {
// Success? // Success?
Notification.create('send_accept', iqFrom, [iqFrom, oob_url, 'iq', iqID, iqNode], oob_desc, notif_id); 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 */ /* REF: http://xmpp.org/extensions/xep-0092.html */
iqQuery = iqResponse.setQuery(NS_VERSION); 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('version', {'xmlns': NS_VERSION}, JAPPIX_VERSION));
iqQuery.appendChild(iqResponse.buildNode('os', {'xmlns': NS_VERSION}, BrowserDetect.OS)); iqQuery.appendChild(iqResponse.buildNode('os', {'xmlns': NS_VERSION}, BrowserDetect.OS));
con.send(iqResponse); con.send(iqResponse);
Console.log('Received software version query: ' + iqFrom); 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 */ /* REF: http://xmpp.org/extensions/xep-0012.html */
iqQuery = iqResponse.setQuery(NS_LAST); iqQuery = iqResponse.setQuery(NS_LAST);
@ -106,10 +130,24 @@ var IQ = (function () {
con.send(iqResponse); con.send(iqResponse);
Console.log('Received last activity query: ' + iqFrom); 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 // REF : http://xmpp.org/extensions/xep-0016.html
// Roster push // Roster push
@ -121,10 +159,24 @@ var IQ = (function () {
}); });
Console.log('Received privacy lists push: ' + iqFrom); 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 // REF : http://xmpp.org/extensions/xep-0092.html
// Roster push // Roster push
@ -136,27 +188,53 @@ var IQ = (function () {
}); });
Console.log('Received roster push: ' + iqFrom); 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 // Open a new notification
Notification.create('rosterx', iqFrom, [iqNode], ''); Notification.create('rosterx', iqFrom, [iqNode], '');
Console.log('Roster Item Exchange from: ' + iqFrom); 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 */ /* REF: http://xmpp.org/extensions/xep-0030.html */
iqQuery = iqResponse.setQuery(NS_DISCO_INFO); iqQuery = iqResponse.setQuery(NS_DISCO_INFO);
// We set the name of the client // We set the name of the client
iqQuery.appendChild(iqResponse.buildNode('identity', { iqQuery.appendChild(iqResponse.buildNode('identity', {
'category': 'client', 'category': Caps.disco_infos.identity.category,
'type': 'web', 'type': Caps.disco_infos.identity.type,
'name': 'Jappix', 'name': Caps.disco_infos.identity.name,
'xmlns': NS_DISCO_INFO 'xmlns': NS_DISCO_INFO
})); }));
@ -170,41 +248,101 @@ var IQ = (function () {
con.send(iqResponse); con.send(iqResponse);
Console.log('Received disco#infos query: ' + iqFrom); 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 */ /* REF: http://xmpp.org/extensions/xep-0202.html */
var iqTime = iqResponse.appendNode('time', {'xmlns': NS_URN_TIME}); var iqTime = iqResponse.appendNode('time', {
iqTime.appendChild(iqResponse.buildNode('tzo', {'xmlns': NS_URN_TIME}, DateUtils.getTZO())); 'xmlns': NS_URN_TIME
iqTime.appendChild(iqResponse.buildNode('utc', {'xmlns': NS_URN_TIME}, DateUtils.getXMPPTime('utc'))); });
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); con.send(iqResponse);
Console.log('Received local time query: ' + iqFrom); 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 */ /* REF: http://xmpp.org/extensions/xep-0199.html */
con.send(iqResponse); con.send(iqResponse);
Console.log('Received a ping: ' + iqFrom); 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 */ /* 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); 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 // Change IQ type
iqResponse.setType('error'); iqResponse.setType('error');
@ -221,6 +359,95 @@ var IQ = (function () {
con.send(iqResponse); con.send(iqResponse);
Console.log('Received an unsupported IQ query from: ' + iqFrom); 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) { } catch(e) {
Console.error('IQ.handle', 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

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

@ -35,6 +35,7 @@ var MAM = (function () {
self.map_reqs = {}; self.map_reqs = {};
self.map_pending = {}; self.map_pending = {};
self.map_states = {}; self.map_states = {};
self.map_messages = {};
self.msg_queue = {}; self.msg_queue = {};
@ -311,11 +312,16 @@ var MAM = (function () {
if(c_message[0]) { if(c_message[0]) {
// Re-build a proper JSJaC message stanza // Re-build a proper JSJaC message stanza
var message = JSJaCPacket.wrapNode(c_message[0]); var message = JSJaCPacket.wrapNode(c_message[0]);
var message_node = message.getNode();
// Check message type // Check message type
var type = message.getType() || 'chat'; var type = message.getType() || 'chat';
if(type == 'chat') { if(type == 'chat') {
// Display function
var c_display_fn;
var c_display_msg_bool = false;
// Read message data // Read message data
var xid = Common.bareXID(Common.getStanzaFrom(message)); var xid = Common.bareXID(Common.getStanzaFrom(message));
var id = message.getID(); var id = message.getID();
@ -331,6 +337,8 @@ var MAM = (function () {
var hash = hex_md5(xid); var hash = hex_md5(xid);
var body = message.getBody(); var body = message.getBody();
// Content message?
if(body) {
// Read delay (required since we deal w/ a past message!) // Read delay (required since we deal w/ a past message!)
var time, stamp; var time, stamp;
var delay = c_delay.attr('stamp'); var delay = c_delay.attr('stamp');
@ -341,9 +349,12 @@ var MAM = (function () {
} }
// Last-minute checks before display // Last-minute checks before display
if(time && stamp && body) { if(time && stamp) {
var mam_chunk_path = '#' + hash + ' .mam-chunk'; var mam_chunk_path = '#' + hash + ' .mam-chunk';
// Markable message?
var is_markable = Markers.hasRequestMarker(message_node);
// No chat auto-scroll? // No chat auto-scroll?
var no_scroll = Common.exists(mam_chunk_path); var no_scroll = Common.exists(mam_chunk_path);
@ -355,26 +366,71 @@ var MAM = (function () {
}; };
// Display the message in that target // Display the message in that target
var c_msg_display = function() { c_display_fn = function() {
Message.display(type, from_xid, hash, b_name.htmlEnc(), body, time, stamp, 'old-message', true, null, mode, null, c_target_sel(), no_scroll); // 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 // 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 // only used when initiating a new chat, avoids collisions
if(!(xid in self.map_states) && $('#' + hash).find('.one-line.user-message:last').text() == body) { if(!(xid in self.map_states) && $('#' + hash).find('.one-line.user-message:last').text() == body) {
return; 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()) { c_display_fn = function() {
// Display the message in that target var is_mam_marker = true;
c_msg_display();
Markers.handle(
from_xid,
message_node,
is_mam_marker
);
};
c_display_msg_bool = (self.map_messages[marked_message_id] === 1) ? true : false;
}
}
// Display message?
if(typeof c_display_fn == 'function') {
if(c_display_msg_bool === true) {
// Display message now
c_display_fn();
} else { } else {
// Delay display (we may not have received the MAM reply ATM) // Delay display (we may not have received the MAM reply ATM)
if(typeof self.msg_queue[xid] != 'object') { if(typeof self.msg_queue[xid] != 'object') {
self.msg_queue[xid] = []; self.msg_queue[xid] = [];
} }
self.msg_queue[xid].push(c_msg_display); self.msg_queue[xid].push(c_display_fn);
} }
} }
} }

View file

@ -0,0 +1,428 @@
/*
Jappix - An open social platform
Implementation of XEP-0333: Chat Markers
-------------------------------------------------
License: AGPL
Author: Valérian Saliou
*/
// Bundle
var Markers = (function () {
/**
* Alias of this
* @private
*/
var self = {};
/* Constants */
self.MARK_TYPE_MARKABLE = 'markable';
self.MARK_TYPE_RECEIVED = 'received';
self.MARK_TYPE_DISPLAYED = 'displayed';
self.MARK_TYPE_ACKNOWLEDGED = 'acknowledged';
self.MARK_TYPES = {};
self.MARK_TYPES[self.MARK_TYPE_MARKABLE] = 1;
self.MARK_TYPES[self.MARK_TYPE_RECEIVED] = 1;
self.MARK_TYPES[self.MARK_TYPE_DISPLAYED] = 1;
self.MARK_TYPES[self.MARK_TYPE_ACKNOWLEDGED] = 1;
/**
* Returns whether entity supports message markers
* @public
* @param {string} xid
* @return {boolean}
*/
self.hasSupport = function(xid) {
var has_support = false;
try {
has_support = true ? $('#' + hex_md5(xid)).attr('data-markers') == 'true' : false;
} catch(e) {
Console.error('Markers.hasSupport', e);
} finally {
return has_support;
}
};
/**
* Returns whether request message is marked or not
* @public
* @param {object} message
* @return {boolean}
*/
self.hasRequestMarker = function(message) {
var has_request_marker = false;
try {
has_request_marker = ($(message).find('markable[xmlns="' + NS_URN_MARKERS + '"]').size() ? true : false);
} catch(e) {
Console.error('Markers.hasRequestMarker', e);
} finally {
return has_request_marker;
}
};
/**
* Returns whether response message is marked or not
* @public
* @param {object} message
* @return {boolean}
*/
self.hasResponseMarker = function(message) {
var has_response_marker = false;
try {
var marker_sel = $(message).find('[xmlns="' + NS_URN_MARKERS + '"]');
if(marker_sel.size()) {
var mark_type = marker_sel.prop('tagName').toLowerCase();
switch(mark_type) {
case self.MARK_TYPE_RECEIVED:
case self.MARK_TYPE_DISPLAYED:
case self.MARK_TYPE_ACKNOWLEDGED:
has_response_marker = true;
break;
}
}
} catch(e) {
Console.error('Markers.hasResponseMarker', e);
} finally {
return has_response_marker;
}
};
/**
* Returns the marked message ID
* @public
* @param {object} message
* @return {boolean}
*/
self.getMessageID = function(message) {
var message_id = null;
try {
message_id = $(message).find('[xmlns="' + NS_URN_MARKERS + '"]').attr('id');
} catch(e) {
Console.error('Markers.getMessageID', e);
} finally {
return message_id;
}
};
/**
* Marks a message
* @public
* @param {object} message
* @return {undefined}
*/
self.mark = function(message) {
try {
message.appendNode('markable', {
'xmlns': NS_URN_MARKERS
});
} catch(e) {
Console.error('Markers.mark', e);
}
};
/**
* Changes received message status (once received or read)
* @public
* @param {string} mark_type
* @param {object} message_id
* @return {undefined}
*/
self.change = function(to, mark_type, message_id, message_sel) {
try {
if(!(mark_type in self.MARK_TYPES)) {
throw 'Marker type (' + mark_type + ') not supported, aborting.';
}
// Store mark state
message_sel.attr('data-mark', mark_type);
var message = new JSJaCMessage();
message.setType('chat');
message.setTo(to);
message.appendNode(mark_type, {
'xmlns': NS_URN_MARKERS,
'id': message_id
});
con.send(message);
Console.debug('Markers.change', 'Changed marker to: ' + mark_type + ' for message with ID: ' + message_id + ' from: ' + to);
} catch(e) {
Console.error('Markers.change', e);
}
};
/**
* Handles marker change coming from Carbons
* @public
* @param {string} message
* @return {undefined}
*/
self.handleCarbonChange = function(message) {
try {
// Check the marker element is existing
var marker_sel = $(message).find('[xmlns="' + NS_URN_MARKERS + '"]');
if(marker_sel.size()) {
var xid = Common.bareXID(message.getTo());
var mark_type = marker_sel.prop('tagName').toLowerCase();
var mark_handle = false;
// Filter allowed markers
switch(mark_type) {
case self.MARK_TYPE_RECEIVED:
case self.MARK_TYPE_DISPLAYED:
case self.MARK_TYPE_ACKNOWLEDGED:
mark_handle = true;
break;
}
if(mark_handle === true) {
var mark_message_id = marker_sel.attr('id');
var message_sel = $('#' + hex_md5(xid) + ' .content .one-line[data-mode="him"][data-markable="true"]').filter(function() {
return ($(this).attr('data-id') + '') === (mark_message_id + '');
}).filter(':last');
if(!message_sel.size()) {
Console.warn('Markers.handleCarbonChange', 'Unknown message marker to keep in sync with Carbons for: ' + xid);
return false;
}
// Store mark state
message_sel.attr('data-mark', mark_type);
Console.debug('Markers.handleCarbonChange', 'Received Carbons chat marker (' + mark_type + ') from another resource for: ' + from);
}
}
} catch(e) {
Console.error('Markers.handleCarbonChange', e);
}
};
/**
* Handles a marked message
* @public
* @param {string} from
* @param {object} message
* @param {boolean} is_mam_marker
* @return {undefined}
*/
self.handle = function(from, message, is_mam_marker, is_groupchat_user) {
try {
var xid = ((is_groupchat_user !== true && Common.bareXID(from)) || from);
var marker_sel = $(message).find('[xmlns="' + NS_URN_MARKERS + '"]');
if(marker_sel.size()) {
var mark_type = marker_sel.prop('tagName').toLowerCase();
var mark_message_id = marker_sel.attr('id');
if(is_mam_marker === true) {
mark_message_id += '-mam';
}
// Filter allowed markers
var mark_valid = false;
switch(mark_type) {
case self.MARK_TYPE_RECEIVED:
case self.MARK_TYPE_DISPLAYED:
case self.MARK_TYPE_ACKNOWLEDGED:
mark_valid = true;
break;
}
if(mark_valid === false) {
Console.warn('Markers.handle', 'Dropping unexpected chat marker (' + mark_type + ') from: ' + from);
return false;
}
// Find marked message target
var message_sel = $('#' + hex_md5(xid) + ' .content .one-line[data-mode="me"]').filter(function() {
return ($(this).attr('data-id') + '') === (mark_message_id + '');
}).filter(':last');
if(!message_sel.size()) {
Console.warn('Markers.handle', 'Dropping chat marker (' + mark_type + ') for inexisting message ID (' + mark_message_id + ') from: ' + from);
return false;
}
Console.debug('Markers.handle', 'Received chat marker (' + mark_type + ') from: ' + from);
// Finally display received marker
self._display(xid, message_sel, mark_type);
return true;
}
return false;
} catch(e) {
Console.error('Markers.handle', e);
return false;
}
};
/**
* Adds the markers input events
* @public
* @param {object} target
* @param {string} xid
* @param {string} hash
* @param {string} type
* @return {undefined}
*/
self.events = function(target, xid, hash, type) {
try {
target.focus(function() {
// Not needed
if(target.is(':disabled')) {
return;
}
// Send displayed message marker?
if(type == 'chat' && self.hasSupport(xid) === true) {
var last_message = $('#' + hash + ' .content .one-line.user-message[data-markable="true"]:last');
if(last_message.attr('data-mark') != self.MARK_TYPE_DISPLAYED) {
var last_message_id = last_message.attr('data-id');
var full_xid = Presence.highestPriority(xid) || xid;
if(last_message_id) {
self.change(
full_xid,
self.MARK_TYPE_DISPLAYED,
last_message_id,
last_message
);
}
}
}
});
} catch(e) {
Console.error('Markers.events', e);
}
};
/**
* Displays a marker
* @private
* @param {string} xid
* @param {object} message_sel
* @param {string} mark_type
* @return {boolean}
*/
self._display = function(xid, message_sel, mark_type) {
try {
// Get marker state translation
var marker_sel = message_sel.find('.message-marker');
var mark_message = null;
var css_classes = 'talk-images message-marker-read';
var marker_category = null;
switch(mark_type) {
case self.MARK_TYPE_RECEIVED:
marker_category = 'delivered';
marker_sel.removeClass(css_classes);
marker_sel.text(
Common._e("Delivered")
);
break;
case self.MARK_TYPE_DISPLAYED:
case self.MARK_TYPE_ACKNOWLEDGED:
marker_category = 'read';
marker_sel.addClass(css_classes);
marker_sel.text(
Common._e("Read")
);
break;
default:
return false;
}
if(marker_category !== null) {
marker_sel.attr('data-category', marker_category);
}
// Reset sending state
message_sel.removeClass('is-sending');
// Toggle marker visibility
message_sel.parents('.content').find('.one-line .message-marker').filter(function() {
var data_category = $(this).attr('data-category');
if(data_category != 'delivered' && data_category != 'read') {
return false;
}
// Leave older "read" checkpoint on screen
if(marker_category == 'delivered') {
return data_category == marker_category;
}
return true;
}).hide();
marker_sel.show();
return true;
} catch(e) {
Console.error('Markers._display', e);
return false;
}
};
/**
* Return class scope
*/
return self;
})();

View file

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

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

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

View file

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

View file

@ -275,11 +275,13 @@ var Options = (function () {
self.switchTab = function(id) { self.switchTab = function(id) {
try { try {
$('#options .one-lap').hide(); var options_sel = $('#options');
$('#options #conf' + id).show();
$('#options .tab a').removeClass('tab-active'); options_sel.find('.one-lap').hide();
$('#options .tab a[data-key="' + id + '"]').addClass('tab-active'); options_sel.find('#conf' + id).show();
$('#options .sub-ask .sub-ask-close').click(); options_sel.find('.tab a').removeClass('tab-active');
options_sel.find('.tab a[data-key="' + id + '"]').addClass('tab-active');
options_sel.find('.sub-ask .sub-ask-close').click();
} catch(e) { } catch(e) {
Console.error('Options.switchTab', e); Console.error('Options.switchTab', e);
} finally { } finally {
@ -298,15 +300,16 @@ var Options = (function () {
self.wait = function(id) { self.wait = function(id) {
try { try {
var sOptions = $('#options .content'); var options_sel = $('#options');
var content_sel = options_sel.find('.content');
// Remove the current item class // Remove the current item class
sOptions.removeClass(id); content_sel.removeClass(id);
// Hide the waiting items if all was received // Hide the waiting items if all was received
if(!sOptions.hasClass('microblog') && !sOptions.hasClass('mam')) { if(!content_sel.hasClass('microblog') && !content_sel.hasClass('mam')) {
$('#options .wait').hide(); options_sel.find('.wait').hide();
$('#options .finish:first').removeClass('disabled'); options_sel.find('.finish:first').removeClass('disabled');
} }
} catch(e) { } catch(e) {
Console.error('Options.wait', e); Console.error('Options.wait', e);
@ -533,23 +536,27 @@ var Options = (function () {
$('.sub-ask-pass input').each(function() { $('.sub-ask-pass input').each(function() {
var select = $(this); var select = $(this);
if(!select.val()) if(!select.val()) {
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
select.addClass('please-complete').focus(); select.addClass('please-complete').focus();
}); });
else } else {
select.removeClass('please-complete'); select.removeClass('please-complete');
}
}); });
if(password0 != Utils.getPassword()) if(password0 != Utils.getPassword()) {
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
$('#options .old').addClass('please-complete').focus(); $('#options .old').addClass('please-complete').focus();
}); });
if(password1 != password2) }
if(password1 != password2) {
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
$('#options .new1, #options .new2').addClass('please-complete').focus(); $('#options .new1, #options .new2').addClass('please-complete').focus();
}); });
} }
}
} catch(e) { } catch(e) {
Console.error('Options.sendNewPassword', e); Console.error('Options.sendNewPassword', e);
} finally { } finally {
@ -612,13 +619,14 @@ var Options = (function () {
} else { } else {
var selector = $('#options .check-mam'); var selector = $('#options .check-mam');
if(password != Utils.getPassword()) if(password != Utils.getPassword()) {
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
selector.addClass('please-complete').focus(); selector.addClass('please-complete').focus();
}); });
else } else {
selector.removeClass('please-complete'); selector.removeClass('please-complete');
} }
}
} catch(e) { } catch(e) {
Console.error('Options.purgeMyArchives', e); Console.error('Options.purgeMyArchives', e);
} finally { } finally {
@ -659,13 +667,14 @@ var Options = (function () {
} else { } else {
var selector = $('#options .check-empty'); var selector = $('#options .check-empty');
if(password != Utils.getPassword()) if(password != Utils.getPassword()) {
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
selector.addClass('please-complete').focus(); selector.addClass('please-complete').focus();
}); });
else } else {
selector.removeClass('please-complete'); selector.removeClass('please-complete');
} }
}
} catch(e) { } catch(e) {
Console.error('Options.purgeMyMicroblog', e); Console.error('Options.purgeMyMicroblog', e);
} finally { } finally {
@ -726,18 +735,17 @@ var Options = (function () {
con.send(iq, self.handleAccDeletion); con.send(iq, self.handleAccDeletion);
Console.info('Delete account sent.'); Console.info('Delete account sent.');
} } else {
else {
var selector = $('#options .check-password'); var selector = $('#options .check-password');
if(password != Utils.getPassword()) if(password != Utils.getPassword()) {
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
selector.addClass('please-complete').focus(); selector.addClass('please-complete').focus();
}); });
else } else {
selector.removeClass('please-complete'); selector.removeClass('please-complete');
} }
}
} catch(e) { } catch(e) {
Console.error('Options.deleteMyAccount', e); Console.error('Options.deleteMyAccount', e);
} finally { } finally {
@ -781,50 +789,58 @@ var Options = (function () {
} }
// We show the "privacy" form if something is visible into it // We show the "privacy" form if something is visible into it
if(enabled_mam || enabled_pep) if(enabled_mam || enabled_pep) {
$('#options fieldset.privacy').show(); $('#options fieldset.privacy').show();
}
// We get the values of the forms for the sounds // We get the values of the forms for the sounds
if(DataStore.getDB(Connection.desktop_hash, 'options', 'sounds') == '0') if(DataStore.getDB(Connection.desktop_hash, 'options', 'sounds') == '0') {
$('#sounds').attr('checked', false); $('#sounds').attr('checked', false);
else } else {
$('#sounds').attr('checked', true); $('#sounds').attr('checked', true);
}
// We get the values of the forms for the geolocation // We get the values of the forms for the geolocation
if(DataStore.getDB(Connection.desktop_hash, 'options', 'geolocation') == '1') if(DataStore.getDB(Connection.desktop_hash, 'options', 'geolocation') == '1') {
$('#geolocation').attr('checked', true); $('#geolocation').attr('checked', true);
else } else {
$('#geolocation').attr('checked', false); $('#geolocation').attr('checked', false);
}
// We get the values of the forms for the roster show all // We get the values of the forms for the roster show all
if(DataStore.getDB(Connection.desktop_hash, 'options', 'roster-showall') == '1') if(DataStore.getDB(Connection.desktop_hash, 'options', 'roster-showall') == '1') {
$('#showall').attr('checked', true); $('#showall').attr('checked', true);
else } else {
$('#showall').attr('checked', false); $('#showall').attr('checked', false);
}
// We get the values of the forms for the XHTML-IM images filter // We get the values of the forms for the XHTML-IM images filter
if(DataStore.getDB(Connection.desktop_hash, 'options', 'no-xhtml-images') == '1') if(DataStore.getDB(Connection.desktop_hash, 'options', 'no-xhtml-images') == '1') {
$('#noxhtmlimg').attr('checked', true); $('#noxhtmlimg').attr('checked', true);
else } else {
$('#noxhtmlimg').attr('checked', false); $('#noxhtmlimg').attr('checked', false);
}
// We get the values of the forms for the integratemedias // We get the values of the forms for the integratemedias
if(DataStore.getDB(Connection.desktop_hash, 'options', 'integratemedias') == '0') if(DataStore.getDB(Connection.desktop_hash, 'options', 'integratemedias') == '0') {
$('#integratemedias').attr('checked', false); $('#integratemedias').attr('checked', false);
else } else {
$('#integratemedias').attr('checked', true); $('#integratemedias').attr('checked', true);
}
// We get the values of the forms for the groupchatpresence // We get the values of the forms for the groupchatpresence
if(DataStore.getDB(Connection.desktop_hash, 'options', 'groupchatpresence') == '0') if(DataStore.getDB(Connection.desktop_hash, 'options', 'groupchatpresence') == '0') {
$('#groupchatpresence').attr('checked', false); $('#groupchatpresence').attr('checked', false);
else } else {
$('#groupchatpresence').attr('checked', true); $('#groupchatpresence').attr('checked', true);
}
// We get the values of the forms for the localarchives // We get the values of the forms for the localarchives
if(DataStore.getDB(Connection.desktop_hash, 'options', 'localarchives') == '0') if(DataStore.getDB(Connection.desktop_hash, 'options', 'localarchives') == '0') {
$('#localarchives').attr('checked', false); $('#localarchives').attr('checked', false);
else } else {
$('#localarchives').attr('checked', true); $('#localarchives').attr('checked', true);
}
} catch(e) { } catch(e) {
Console.error('Options.load', e); Console.error('Options.load', e);
} }
@ -939,10 +955,13 @@ var Options = (function () {
}); });
$('#options .bottom .finish').click(function() { $('#options .bottom .finish').click(function() {
if($(this).is('.save') && !$(this).hasClass('disabled')) if($(this).is('.save') && !$(this).hasClass('disabled')) {
return self.save(); return self.save();
if($(this).is('.cancel')) }
if($(this).is('.cancel')) {
return self.close(); return self.close();
}
return false; return false;
}); });
@ -951,21 +970,25 @@ var Options = (function () {
$('#options .sub-ask input').keyup(function(e) { $('#options .sub-ask input').keyup(function(e) {
if(e.keyCode == 13) { if(e.keyCode == 13) {
// Archives purge // Archives purge
if($(this).is('.purge-archives')) if($(this).is('.purge-archives')) {
return self.purgeMyArchives(); return self.purgeMyArchives();
}
// Microblog purge // Microblog purge
else if($(this).is('.purge-microblog')) else if($(this).is('.purge-microblog')) {
return self.purgeMyMicroblog(); return self.purgeMyMicroblog();
}
// Password change // Password change
else if($(this).is('.password-change')) else if($(this).is('.password-change')) {
return self.sendNewPassword(); return self.sendNewPassword();
}
// Account deletion // Account deletion
else if($(this).is('.delete-account')) else if($(this).is('.delete-account')) {
return self.deleteMyAccount(); return self.deleteMyAccount();
} }
}
}); });
// Load the options // 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? // Any block list?
if($(iqQuery).find('list[name="block"]').size()) { if($(iqQuery).find('list[name="block"]').size()) {
// Not the default one? // Not the default one?
if(!$(iqQuery).find('default[name="block"]').size()) if(!$(iqQuery).find('default[name="block"]').size()) {
self.change('block', 'default'); self.change('block', 'default');
else } else {
DataStore.setDB(Connection.desktop_hash, 'privacy-marker', 'default', 'block'); DataStore.setDB(Connection.desktop_hash, 'privacy-marker', 'default', 'block');
}
// Not the active one? // Not the active one?
if(!$(iqQuery).find('active[name="block"]').size()) if(!$(iqQuery).find('active[name="block"]').size()) {
self.change('block', 'active'); self.change('block', 'active');
else } else {
DataStore.setDB(Connection.desktop_hash, 'privacy-marker', 'active', 'block'); DataStore.setDB(Connection.desktop_hash, 'privacy-marker', 'active', 'block');
}
// Get the block list rules // Get the block list rules
self.get('block'); self.get('block');
@ -381,10 +383,11 @@ var Privacy = (function () {
} }
con.send(iq, function(iq) { con.send(iq, function(iq) {
if(iq.getType() == 'result') if(iq.getType() == 'result') {
Console.log('Sent privacy list.'); Console.log('Sent privacy list.');
else } else {
Console.error('Error sending privacy list.'); Console.error('Error sending privacy list.');
}
}); });
Console.log('Sending privacy list: ' + list); Console.log('Sending privacy list: ' + list);
@ -455,8 +458,9 @@ var Privacy = (function () {
if(!c_order) if(!c_order)
c_order = ''; c_order = '';
if(!isNaN(c_order) && parseInt(c_order) > highest_order) if(!isNaN(c_order) && parseInt(c_order) > highest_order) {
highest_order = parseInt(c_order); highest_order = parseInt(c_order);
}
type.push(c_type); type.push(c_type);
value.push(c_value); value.push(c_value);
@ -464,26 +468,30 @@ var Privacy = (function () {
order.push(c_order); order.push(c_order);
// Child elements // Child elements
if($(this).find('presence-in').size()) if($(this).find('presence-in').size()) {
presence_in.push(true); presence_in.push(true);
else } else {
presence_in.push(false); presence_in.push(false);
}
if($(this).find('presence-out').size()) if($(this).find('presence-out').size()) {
presence_out.push(true); presence_out.push(true);
else } else {
presence_out.push(false); presence_out.push(false);
}
if($(this).find('message').size()) if($(this).find('message').size()) {
msg.push(true); msg.push(true);
else } else {
msg.push(false); msg.push(false);
}
if($(this).find('iq').size()) if($(this).find('iq').size()) {
iq_p.push(true); iq_p.push(true);
else } else {
iq_p.push(false); iq_p.push(false);
} }
}
}); });
order.unshift((++highest_order) + ''); order.unshift((++highest_order) + '');
@ -508,8 +516,9 @@ var Privacy = (function () {
try { try {
// Yet sent? // Yet sent?
if(DataStore.getDB(Connection.desktop_hash, 'privacy-marker', status) == list) if(DataStore.getDB(Connection.desktop_hash, 'privacy-marker', status) == list) {
return; return;
}
// Write a marker // Write a marker
DataStore.setDB(Connection.desktop_hash, 'privacy-marker', status, list); DataStore.setDB(Connection.desktop_hash, 'privacy-marker', status, list);
@ -523,8 +532,9 @@ var Privacy = (function () {
var iqStatus = iqQuery.appendChild(iq.buildNode(status, {'xmlns': NS_PRIVACY})); var iqStatus = iqQuery.appendChild(iq.buildNode(status, {'xmlns': NS_PRIVACY}));
// Can add a "name" attribute? // Can add a "name" attribute?
if(list) if(list) {
iqStatus.setAttribute('name', list); iqStatus.setAttribute('name', list);
}
con.send(iq); con.send(iq);
@ -596,18 +606,20 @@ var Privacy = (function () {
$(data).find('list').each(function() { $(data).find('list').each(function() {
var list_name = $(this).attr('name'); var list_name = $(this).attr('name');
if(list_name) if(list_name) {
code += '<option value="' + Common.encodeQuotes(list_name) + '">' + list_name.htmlEnc() + '</option>'; code += '<option value="' + Common.encodeQuotes(list_name) + '">' + list_name.htmlEnc() + '</option>';
}
}); });
// Apply HTML code // Apply HTML code
select.html(code); select.html(code);
// Not empty? // Not empty?
if(code) if(code) {
select.removeAttr('disabled'); select.removeAttr('disabled');
else } else {
select.attr('disabled', true); select.attr('disabled', true);
}
} catch(e) { } catch(e) {
Console.error('Privacy.displayLists', e); Console.error('Privacy.displayLists', e);
} finally { } finally {
@ -638,8 +650,9 @@ var Privacy = (function () {
select.html(''); select.html('');
// No list? // No list?
if(!list) if(!list) {
return false; return false;
}
// Reset the list status // Reset the list status
$('#privacy .privacy-active input[type="checkbox"]').removeAttr('checked'); $('#privacy .privacy-active input[type="checkbox"]').removeAttr('checked');
@ -648,9 +661,10 @@ var Privacy = (function () {
var status = ['active', 'default']; var status = ['active', 'default'];
for(var s in status) { for(var s in status) {
if(DataStore.getDB(Connection.desktop_hash, 'privacy-marker', status[s]) == list) if(DataStore.getDB(Connection.desktop_hash, 'privacy-marker', status[s]) == list) {
$('#privacy .privacy-active input[name=' + status[s] + ']').attr('checked', true); $('#privacy .privacy-active input[name=' + status[s] + ']').attr('checked', true);
} }
}
// Try to read the stored items // Try to read the stored items
var items = Common.XMLFromString(DataStore.getDB(Connection.desktop_hash, 'privacy', list)); var items = Common.XMLFromString(DataStore.getDB(Connection.desktop_hash, 'privacy', list));
@ -660,10 +674,9 @@ var Privacy = (function () {
select.attr('disabled', true); select.attr('disabled', true);
return self.get(list); return self.get(list);
} } else {
else
select.removeAttr('disabled'); select.removeAttr('disabled');
}
// Parse the XML data! // Parse the XML data!
$(items).find('item').each(function() { $(items).find('item').each(function() {
@ -814,8 +827,9 @@ var Privacy = (function () {
$(type_check).attr('checked', true); $(type_check).attr('checked', true);
// Can apply a value? // Can apply a value?
if(value_input) if(value_input) {
$(value_input).val(value); $(value_input).val(value);
}
// Apply the things to do // Apply the things to do
var privacy_do = '#privacy .privacy-third input[type="checkbox"]'; var privacy_do = '#privacy .privacy-third input[type="checkbox"]';
@ -924,8 +938,9 @@ var Privacy = (function () {
var list = $('#privacy .privacy-head .list-left select').val(); var list = $('#privacy .privacy-head .list-left select').val();
// No value? // No value?
if(!list) if(!list) {
return false; return false;
}
// Remove it from popup // Remove it from popup
$('#privacy .privacy-head .list-left select option[value="' + list + '"]').remove(); $('#privacy .privacy-head .list-left select option[value="' + list + '"]').remove();
@ -941,9 +956,10 @@ var Privacy = (function () {
var status = ['active', 'default']; var status = ['active', 'default'];
for(var s in status) { for(var s in status) {
if(DataStore.getDB(Connection.desktop_hash, 'privacy-marker', status[s]) == list) if(DataStore.getDB(Connection.desktop_hash, 'privacy-marker', status[s]) == list) {
self.change('', status[s]); self.change('', status[s]);
} }
}
// Remove from server // Remove from server
self.set(list); self.set(list);
@ -957,8 +973,9 @@ var Privacy = (function () {
$('#privacy .privacy-head .list-right input').keyup(function(e) { $('#privacy .privacy-head .list-right input').keyup(function(e) {
// Not enter? // Not enter?
if(e.keyCode != 13) if(e.keyCode != 13) {
return; return;
}
// Get list name // Get list name
var list = $('#privacy .privacy-head .list-right input').val(); var list = $('#privacy .privacy-head .list-right input').val();
@ -1015,8 +1032,9 @@ var Privacy = (function () {
$('#privacy .privacy-item a.item-add').click(function() { $('#privacy .privacy-item a.item-add').click(function() {
// Cannot add anything? // Cannot add anything?
if(!Common.exists('#privacy .privacy-head .list-left select option:selected')) if(!Common.exists('#privacy .privacy-head .list-left select option:selected')) {
return false; return false;
}
// Disable item select // Disable item select
$('#privacy .privacy-item select').attr('disabled', true); $('#privacy .privacy-item select').attr('disabled', true);
@ -1034,8 +1052,9 @@ var Privacy = (function () {
$('#privacy .privacy-item a.item-remove').click(function() { $('#privacy .privacy-item a.item-remove').click(function() {
// Cannot add anything? // Cannot add anything?
if(!Common.exists('#privacy .privacy-head .list-left select option:selected')) if(!Common.exists('#privacy .privacy-head .list-left select option:selected')) {
return false; return false;
}
// Get values // Get values
var list = $('#privacy .privacy-head .list-left select').val(); var list = $('#privacy .privacy-head .list-left select').val();
@ -1055,17 +1074,19 @@ var Privacy = (function () {
$('#privacy .privacy-head .list-left select option[value="' + list + '"]').remove(); $('#privacy .privacy-head .list-left select option[value="' + list + '"]').remove();
// No more privacy lists? // No more privacy lists?
if(!Common.exists('#privacy .privacy-head .list-left select option')) if(!Common.exists('#privacy .privacy-head .list-left select option')) {
$('#privacy .privacy-head .list-left select').attr('disabled', true); $('#privacy .privacy-head .list-left select').attr('disabled', true);
}
// Disable this list before removing it // Disable this list before removing it
var status = ['active', 'default']; var status = ['active', 'default'];
for(var s in status) { for(var s in status) {
if(DataStore.getDB(Connection.desktop_hash, 'privacy-marker', status[s]) == list) if(DataStore.getDB(Connection.desktop_hash, 'privacy-marker', status[s]) == list) {
self.change('', status[s]); self.change('', status[s]);
} }
} }
}
// Synchronize it with server // Synchronize it with server
self.push(list, [], [item], [], [], [], [], [], [], hash, 'remove'); self.push(list, [], [item], [], [], [], [], [], [], hash, 'remove');
@ -1079,14 +1100,16 @@ var Privacy = (function () {
$('#privacy .privacy-item a.item-save').click(function() { $('#privacy .privacy-item a.item-save').click(function() {
// Canot push item? // Canot push item?
if(Common.exists('#privacy .privacy-form input:disabled')) if(Common.exists('#privacy .privacy-form input:disabled')) {
return false; return false;
}
// Get the hash // Get the hash
var item_hash = ''; var item_hash = '';
if(!$('#privacy .privacy-item select').is(':disabled')) if(!$('#privacy .privacy-item select').is(':disabled')) {
item_hash = $('#privacy .privacy-item select option:selected').attr('data-hash'); item_hash = $('#privacy .privacy-item select option:selected').attr('data-hash');
}
// Read the form // Read the form
var privacy_second = '#privacy .privacy-second'; var privacy_second = '#privacy .privacy-second';
@ -1170,16 +1193,19 @@ var Privacy = (function () {
var target = '#privacy .privacy-third input[type="checkbox"]'; var target = '#privacy .privacy-third input[type="checkbox"]';
// Must tick "everything" checkbox? // Must tick "everything" checkbox?
if(!$(target).filter(':checked').size()) if(!$(target).filter(':checked').size()) {
$(target + '[name="everything"]').attr('checked', true); $(target + '[name="everything"]').attr('checked', true);
}
// Must untick the other checkboxes? // Must untick the other checkboxes?
else if($(this).is('[name="everything"]')) else if($(this).is('[name="everything"]')) {
$(target + ':not([name="everything"])').removeAttr('checked'); $(target + ':not([name="everything"])').removeAttr('checked');
}
// Must untick "everything" checkbox? // Must untick "everything" checkbox?
else else {
$(target + '[name="everything"]').removeAttr('checked'); $(target + '[name="everything"]').removeAttr('checked');
}
}); });
$('#privacy .privacy-active input[name="order"]').keyup(function() { $('#privacy .privacy-active input[name="order"]').keyup(function() {
@ -1187,14 +1213,16 @@ var Privacy = (function () {
var value = $(this).val(); var value = $(this).val();
// No value? // No value?
if(!value) if(!value) {
return; return;
}
// Not a number? // Not a number?
if(isNaN(value)) if(isNaN(value)) {
value = 1; value = 1;
else } else {
value = parseInt(value); value = parseInt(value);
}
// Negative? // Negative?
if(value < 0) if(value < 0)
@ -1206,8 +1234,9 @@ var Privacy = (function () {
.blur(function() { .blur(function() {
// No value? // No value?
if(!$(this).val()) if(!$(this).val()) {
$(this).val('1'); $(this).val('1');
}
}); });
$('#privacy .privacy-active .privacy-active-elements input').change(function() { $('#privacy .privacy-active .privacy-active-elements input').change(function() {
@ -1216,14 +1245,16 @@ var Privacy = (function () {
var state_name = $(this).attr('name'); var state_name = $(this).attr('name');
// Cannot continue? // Cannot continue?
if(!list_name || !state_name) if(!list_name || !state_name) {
return; return;
}
// Change the current list status // Change the current list status
if($(this).filter(':checked').size()) if($(this).filter(':checked').size()) {
self.change(list_name, state_name); self.change(list_name, state_name);
else } else {
self.change('', state_name); self.change('', state_name);
}
}); });
} catch(e) { } catch(e) {
Console.error('Privacy.instance', e); Console.error('Privacy.instance', e);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -51,8 +51,9 @@ var Talk = (function () {
try { try {
// Talkpage exists? // Talkpage exists?
if(Common.exists('#talk')) if(Common.exists('#talk')) {
return false; return false;
}
// Anonymous detector // Anonymous detector
var anonymous = Utils.isAnonymous(); var anonymous = Utils.isAnonymous();
@ -116,14 +117,14 @@ var Talk = (function () {
if(!anonymous) html += if(!anonymous) html +=
'<div class="tools-all">' + '<div class="tools-all">' +
'<div class="tools jingle talk-images" onclick="return Jingle.open();">' + '<div class="tools call talk-images" onclick="return Call.open();">' +
'<span class="streaming-items">' + '<span class="streaming-items">' +
'<span class="counter" data-default="00:00:00">00:00:00</span>' + '<span class="counter" data-default="00:00:00">00:00:00</span>' +
'<a class="stop" href="#" onclick="return Jingle.stop();">' + Common._e("Stop") + '</a>' + '<a class="stop" href="#" onclick="return Call.stop();">' + Common._e("Stop") + '</a>' +
'</span>' + '</span>' +
'</div>' + '</div>' +
'<div class="jingle-content tools-content">' + '<div class="call-content tools-content">' +
'<div class="tools-content-subarrow talk-images"></div>' + '<div class="tools-content-subarrow talk-images"></div>' +
'<div class="tools-content-subitem"></div>' + '<div class="tools-content-subitem"></div>' +
@ -157,6 +158,10 @@ var Talk = (function () {
'<a href="#" class="groupchat talk-images" title="' + Common._e("Your groupchats") + '"></a>' + '<a href="#" class="groupchat talk-images" title="' + Common._e("Your groupchats") + '"></a>' +
'</div>' + '</div>' +
'<div class="roster-muji roster-icon muji-hidable">' +
'<a href="#" class="muji talk-images" title="' + Common._e("Audio/video conference") + '"></a>' +
'</div>' +
'<div class="roster-more roster-icon">' + '<div class="roster-more roster-icon">' +
'<a href="#" class="more talk-images" title="' + Common._e("More stuff") + '"></a>' + '<a href="#" class="more talk-images" title="' + Common._e("More stuff") + '"></a>' +
'</div>' + '</div>' +
@ -306,7 +311,7 @@ var Talk = (function () {
Presence.first_sent = false; Presence.first_sent = false;
Search.search_filtered = false; Search.search_filtered = false;
Avatar.pending = []; Avatar.pending = [];
JOIN_SUGGEST = []; Groupchat.join_suggest = [];
// Kill all timers, exept the board ones // Kill all timers, exept the board ones
$('*:not(#board .one-board)').stopTime(); $('*:not(#board .one-board)').stopTime();

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

Binary file not shown.

Binary file not shown.

View file

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

View file

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

View file

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

View file

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

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