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,27 +17,38 @@
{ {
"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
@ -27,7 +28,7 @@ sudo chown -R www-data: $final_path
sudo sed -i "s@PATHTOCHANGE2@$path@g" ../conf/nginx.conf sudo sed -i "s@PATHTOCHANGE2@$path@g" ../conf/nginx.conf
if [ -z "$path" ]; then if [ -z "$path" ]; then
path="/" path="/"
fi fi
sudo ls $final_path/i18n/$language > /dev/null 2>&1 sudo ls $final_path/i18n/$language > /dev/null 2>&1
@ -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

@ -29,24 +29,24 @@ var AdHoc = (function () {
try { try {
// Popup HTML content // Popup HTML content
var html = var html =
'<div class="top">' + Common._e("Commands") + '</div>' + '<div class="top">' + Common._e("Commands") + '</div>' +
'<div class="content">' + '<div class="content">' +
'<div class="adhoc-head"></div>' + '<div class="adhoc-head"></div>' +
'<div class="results adhoc-results"></div>' + '<div class="results adhoc-results"></div>' +
'</div>' + '</div>' +
'<div class="bottom">' + '<div class="bottom">' +
'<div class="wait wait-medium"></div>' + '<div class="wait wait-medium"></div>' +
'<a href="#" class="finish">' + Common._e("Close") + '</a>' + '<a href="#" class="finish">' + Common._e("Close") + '</a>' +
'</div>'; '</div>';
// Create the popup // Create the popup
Popup.create('adhoc', html); Popup.create('adhoc', html);
// Associate the events // Associate the events
self.launch(); self.launch();
} catch(e) { } catch(e) {
@ -88,16 +88,16 @@ var AdHoc = (function () {
try { try {
// Open the popup // Open the popup
self.open(); self.open();
// Add a XID marker // Add a XID marker
$('#adhoc .adhoc-head').html('<b>' + Name.getBuddy(xid).htmlEnc() + '</b> (' + xid.htmlEnc() + ')'); $('#adhoc .adhoc-head').html('<b>' + Name.getBuddy(xid).htmlEnc() + '</b> (' + xid.htmlEnc() + ')');
// Get the highest entity resource // Get the highest entity resource
var highest = Presence.highestPriority(xid); var highest = Presence.highestPriority(xid);
if(highest) if(highest)
xid = highest; xid = highest;
// Start a new adhoc command // Start a new adhoc command
DataForm.go(xid, 'command', '', '', 'adhoc'); DataForm.go(xid, 'command', '', '', 'adhoc');
} catch(e) { } catch(e) {
@ -120,10 +120,10 @@ var AdHoc = (function () {
try { try {
// Open the popup // Open the popup
self.open(); self.open();
// Add a XID marker // Add a XID marker
$('#adhoc .adhoc-head').html('<b>' + server.htmlEnc() + '</b>'); $('#adhoc .adhoc-head').html('<b>' + server.htmlEnc() + '</b>');
// Start a new adhoc command // Start a new adhoc command
DataForm.go(server, 'command', '', '', 'adhoc'); DataForm.go(server, 'command', '', '', 'adhoc');
} catch(e) { } catch(e) {
@ -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
@ -29,40 +51,40 @@ var Anonymous = (function () {
try { try {
Console.info('Jappix (anonymous) is now connected.'); Console.info('Jappix (anonymous) is now connected.');
// Connected marker // Connected marker
Connection.connected = true; Connection.connected = true;
Connection.current_session = true; Connection.current_session = true;
Connection.reconnect_try = 0; Connection.reconnect_try = 0;
Connection.reconnect_timer = 0; Connection.reconnect_timer = 0;
// Not resumed? // Not resumed?
if(!Connection.resume) { if(!Connection.resume) {
// Create the app // Create the app
Talk.create(); Talk.create();
// Send our first presence // Send our first presence
Presence.sendFirst(''); Presence.sendFirst('');
// Set last activity stamp // Set last activity stamp
DateUtils.last_activity = DateUtils.getTimeStamp(); DateUtils.last_activity = DateUtils.getTimeStamp();
// Create the new groupchat // Create the new groupchat
Chat.checkCreate(Common.generateXID(ANONYMOUS_ROOM, 'groupchat'), 'groupchat'); Chat.checkCreate(Common.generateXID(ANONYMOUS_ROOM, 'groupchat'), 'groupchat');
// Remove some nasty elements for the anonymous mode // Remove some nasty elements for the anonymous mode
$('.tools-mucadmin, .tools-add').remove(); $('.tools-mucadmin, .tools-add').remove();
} }
// Resumed // Resumed
else { else {
// Send again our presence // Send again our presence
Presence.sendActions(); Presence.sendActions();
// Change the title // Change the title
Interface.updateTitle(); Interface.updateTitle();
} }
// Remove the waiting icon // Remove the waiting icon
Interface.removeGeneralWait(); Interface.removeGeneralWait();
} catch(e) { } catch(e) {
@ -107,21 +129,16 @@ var Anonymous = (function () {
// Check BOSH origin // Check BOSH origin
BOSH_SAME_ORIGIN = Origin.isSame(httpbase); BOSH_SAME_ORIGIN = Origin.isSame(httpbase);
// We create the new http-binding connection // We create the new http-binding connection
con = new JSJaCHttpBindingConnection({ con = new JSJaCHttpBindingConnection({
httpbase: httpbase httpbase: httpbase
}); });
} }
// 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 = {};
oArgs.domain = server; oArgs.domain = server;
@ -129,10 +146,10 @@ var Anonymous = (function () {
oArgs.resource = JAPPIX_RESOURCE + ' Anonymous (' + (new Date()).getTime() + ')'; oArgs.resource = JAPPIX_RESOURCE + ' Anonymous (' + (new Date()).getTime() + ')';
oArgs.secure = true; oArgs.secure = true;
oArgs.xmllang = XML_LANG; oArgs.xmllang = XML_LANG;
// We connect ! // We connect !
con.connect(oArgs); con.connect(oArgs);
// Change the page title // Change the page title
Interface.title('wait'); Interface.title('wait');
} catch(e) { } catch(e) {
@ -140,7 +157,7 @@ var Anonymous = (function () {
// Reset Jappix // Reset Jappix
self.disconnected(); self.disconnected();
// Open an unknown error // Open an unknown error
Board.openThisError(2); Board.openThisError(2);
} finally { } finally {
@ -160,16 +177,19 @@ var Anonymous = (function () {
try { try {
$(document).ready(function() { $(document).ready(function() {
Console.info('Anonymous mode detected, connecting...'); Console.info('Anonymous mode detected, connecting...');
// We add the login wait div // We add the login wait div
Interface.showGeneralWait(); Interface.showGeneralWait();
// Get the vars // Get the vars
if(XMPPLinks.links_var.r) if(XMPPLinks.links_var.r) {
ANONYMOUS_ROOM = XMPPLinks.links_var.r; ANONYMOUS_ROOM = XMPPLinks.links_var.r;
if(XMPPLinks.links_var.n) }
if(XMPPLinks.links_var.n) {
ANONYMOUS_NICK = XMPPLinks.links_var.n; ANONYMOUS_NICK = XMPPLinks.links_var.n;
}
// Fire the login action // Fire the login action
self.login(HOST_ANONYMOUS); self.login(HOST_ANONYMOUS);
}); });

View file

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

View file

@ -29,7 +29,7 @@ var Audio = (function () {
* @private * @private
* @return {boolean} * @return {boolean}
*/ */
self._is_supported = function() { self._isSupported = function() {
is_supported = true; is_supported = true;
@ -38,7 +38,7 @@ var Audio = (function () {
is_supported = false; is_supported = false;
} }
} catch(e) { } catch(e) {
Console.error('Audio._is_supported', e); Console.error('Audio._isSupported', e);
} finally { } finally {
return is_supported; return is_supported;
} }
@ -46,6 +46,57 @@ var Audio = (function () {
}; };
/**
* Append audio DOM code
* @private
* @return {undefined}
*/
self._appendDOM = function() {
try {
// If the audio elements aren't yet in the DOM
if(!Common.exists('#audio')) {
$('body').append(
'<div id="audio">' +
'<audio id="new-chat" preload="auto" data-duration="2">' +
'<source src="' + './sounds/new-chat.mp3' + '" />' +
'<source src="' + './sounds/new-chat.oga' + '" />' +
'</audio>' +
'<audio id="receive-message" preload="auto" data-duration="2">' +
'<source src="' + './sounds/receive-message.mp3' + '" />' +
'<source src="' + './sounds/receive-message.oga' + '" />' +
'</audio>' +
'<audio id="notification" preload="auto" data-duration="2">' +
'<source src="' + './sounds/notification.mp3' + '" />' +
'<source src="' + './sounds/notification.oga' + '" />' +
'</audio>' +
'<audio id="catch-attention" preload="auto" data-duration="3">' +
'<source src="' + './sounds/catch-attention.mp3' + '" />' +
'<source src="' + './sounds/catch-attention.oga' + '" />' +
'</audio>' +
'<audio id="incoming-call" preload="auto" data-duration="7">' +
'<source src="' + './sounds/incoming-call.mp3' + '" />' +
'<source src="' + './sounds/incoming-call.oga' + '" />' +
'</audio>' +
'<audio id="outgoing-call" preload="auto" data-duration="30">' +
'<source src="' + './sounds/outgoing-call.mp3' + '" />' +
'<source src="' + './sounds/outgoing-call.oga' + '" />' +
'</audio>' +
'</div>'
);
}
} catch(e) {
Console.error('Audio._appendDOM', e);
}
};
/** /**
* Plays the given sound ID * Plays the given sound ID
* @public * @public
@ -58,44 +109,14 @@ var Audio = (function () {
repeat = (typeof repeat === 'boolean') ? repeat : false; repeat = (typeof repeat === 'boolean') ? repeat : false;
// Not supported? // Not supported?
if(!self._is_supported()) { if(!self._isSupported()) {
return false; return false;
} }
// If the sounds are enabled // If the sounds are enabled
if(DataStore.getDB(Connection.desktop_hash, 'options', 'sounds') === '1') { if(DataStore.getDB(Connection.desktop_hash, 'options', 'sounds') === '1') {
// If the audio elements aren't yet in the DOM self._appendDOM();
if(!Common.exists('#audio')) {
$('body').append(
'<div id="audio">' +
'<audio id="new-chat" preload="auto" data-duration="2">' +
'<source src="' + './sounds/new-chat.mp3' + '" />' +
'<source src="' + './sounds/new-chat.oga' + '" />' +
'</audio>' +
'<audio id="receive-message" preload="auto" data-duration="2">' +
'<source src="' + './sounds/receive-message.mp3' + '" />' +
'<source src="' + './sounds/receive-message.oga' + '" />' +
'</audio>' +
'<audio id="notification" preload="auto" data-duration="2">' +
'<source src="' + './sounds/notification.mp3' + '" />' +
'<source src="' + './sounds/notification.oga' + '" />' +
'</audio>' +
'<audio id="incoming-call" preload="auto" data-duration="7">' +
'<source src="' + './sounds/incoming-call.mp3' + '" />' +
'<source src="' + './sounds/incoming-call.oga' + '" />' +
'</audio>' +
'<audio id="outgoing-call" preload="auto" data-duration="30">' +
'<source src="' + './sounds/outgoing-call.mp3' + '" />' +
'<source src="' + './sounds/outgoing-call.oga' + '" />' +
'</audio>' +
'</div>'
);
}
// We play the target sound // We play the target sound
var audio_raw_sel = $('#audio audio').filter('#' + name); var audio_raw_sel = $('#audio audio').filter('#' + name);
var audio_sel = audio_raw_sel[0]; var audio_sel = audio_raw_sel[0];
@ -112,7 +133,7 @@ var Audio = (function () {
var duration = parseInt((audio_raw_sel.attr('data-duration') || 0), 10); var duration = parseInt((audio_raw_sel.attr('data-duration') || 0), 10);
self._timeout_stop = false; self._timeout_stop = false;
audio_raw_sel.oneTime((duration + 's'), function() { audio_raw_sel.oneTime((duration + 's'), function() {
if(!self._timeout_stop) { if(!self._timeout_stop) {
self.play(name, repeat); self.play(name, repeat);
@ -146,10 +167,10 @@ var Audio = (function () {
try { try {
// Not supported? // Not supported?
if(!self._is_supported()) { if(!self._isSupported()) {
return false; return false;
} }
self._timeout_stop = true; self._timeout_stop = true;
// Check the audio container exists before doing anything... // Check the audio container exists before doing anything...
@ -159,7 +180,7 @@ var Audio = (function () {
if(audio_parent_sel.size()) { if(audio_parent_sel.size()) {
audio_raw_sel.stopTime(); audio_raw_sel.stopTime();
if(audio_sel) { if(audio_sel) {
if(!audio_sel.paused) { if(!audio_sel.paused) {
audio_sel.pause(); audio_sel.pause();

View file

@ -32,14 +32,17 @@ var Autocompletion = (function () {
try { try {
// Put the two strings into lower case // Put the two strings into lower case
var sA = a[0].toLowerCase(); var sort_a = a[0].toLowerCase();
var sB = b[0].toLowerCase(); var sort_b = b[0].toLowerCase();
// Process the sort // Process the sort
if(sA > sB) if(sort_a > sort_b) {
return 1; return 1;
if(sA < sB) }
if(sort_a < sort_b) {
return -1; return -1;
}
} catch(e) { } catch(e) {
Console.error('Autocompletion.caseInsensitiveSort', e); Console.error('Autocompletion.caseInsensitiveSort', e);
} }
@ -49,40 +52,51 @@ var Autocompletion = (function () {
/** /**
* Split a query into its subqueries ready to be used in autocompletion * Split a query into its subqueries ready to be used in autocompletion
* The function return an array containing two others : the first with subqueries * @public
* and the second with remaining parts
* For example, if query is "A B C", the subqueries are ["C", "B C", "A B C"] and
* the remaining parts are ["A B ", "A ", ""]
* @param {string} query * @param {string} query
* @return {Array} * @return {object}
*/ */
self.getSubQueries = function(query) { self.getSubQueries = function(query) {
var subqueries = []; var result = [];
var remnants = [];
var queryLastCharPos = query.length - 1; try {
var spaceCounter = 0; var subqueries = [];
for (var i=queryLastCharPos; i>=0; i--) { var remnants = [];
// Search from the end of the query
var iChar = query.charAt(i); var query_last_char_pos = query.length - 1;
if (spaceCounter === 0 && iChar.search(/\s/) === 0) { var space_counter = 0;
// the first "local" space was found var cur_char;
// add the subquery and its remnant to results
subqueries.push(query.slice(i+1)); for(var i = query_last_char_pos; i >= 0; i--) {
remnants.push(query.slice(0, i+1)); // Search from the end of the query
spaceCounter++; cur_char = query.charAt(i);
} else {
spaceCounter = 0; if(space_counter === 0 && cur_char.search(/\s/) === 0) {
// The first "local" space was found
// Add the subquery and its remnant to results
subqueries.push(query.slice(i+1));
remnants.push(query.slice(0, i+1));
space_counter++;
} else {
space_counter = 0;
}
} }
}
if (spaceCounter === 0) { if(space_counter === 0) {
// If the first char of the query is not a space, add the full query to results // If the first char of the query is not a space, add the full query to results
subqueries.push(query); subqueries.push(query);
remnants.push(""); remnants.push('');
}
result = [subqueries, remnants];
} catch(e) {
Console.error('Autocompletion.getSubQueries', e);
} finally {
return result;
} }
return [subqueries, remnants];
}; };
@ -102,25 +116,37 @@ var Autocompletion = (function () {
try { try {
// Replace forbidden characters in regex // Replace forbidden characters in regex
query = Common.escapeRegex(query); query = Common.escapeRegex(query);
// Build an array of regex to use // Build an array of regex to use
var queryRegExp = []; var query_reg_exp = [];
for (i = 0; i<query.length; i++) {
if (query[i] !== null) { for(i = 0; i < query.length; i++) {
queryRegExp.push(new RegExp('(^)' + query[i], 'gi')); if(query[i] !== null) {
query_reg_exp.push(
new RegExp('(^)' + query[i], 'gi')
);
} }
} }
// Search in the roster // Search in the roster
var nick, regex;
$('#' + id + ' .user').each(function() { $('#' + id + ' .user').each(function() {
var nick = $(this).find('.name').text(); nick = $(this).find('.name').text();
for (i = 0; i<queryRegExp.length; i++) {
var regex = queryRegExp[i]; for(i = 0; i < query_reg_exp.length; i++) {
regex = query_reg_exp[i];
if(nick.match(regex)) { if(nick.match(regex)) {
results.push([nick, i]); results.push([nick, i]);
} }
} }
}); });
// Sort the array // Sort the array
results = results.sort(self.caseInsensitiveSort); results = results.sort(
self.caseInsensitiveSort
);
} catch(e) { } catch(e) {
Console.error('Autocompletion.process', e); Console.error('Autocompletion.process', e);
} finally { } finally {
@ -139,7 +165,8 @@ var Autocompletion = (function () {
self.reset = function(hash) { self.reset = function(hash) {
try { try {
$('#' + hash + ' .message-area').removeAttr('data-autocompletion-pointer').removeAttr('data-autocompletion-query'); $('#' + hash + ' .message-area').removeAttr('data-autocompletion-pointer')
.removeAttr('data-autocompletion-query');
} catch(e) { } catch(e) {
Console.error('Autocompletion.reset', e); Console.error('Autocompletion.reset', e);
} }
@ -157,59 +184,62 @@ 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!
if((nick !== undefined) && (nick.toLowerCase() == Name.getMUCNick(hash).toLowerCase())) { if((nick !== undefined) && (nick.toLowerCase() == Name.getMUCNick(hash).toLowerCase())) {
// Increment // Increment
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,30 +39,32 @@ 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(
DataStore.getPersistent('global', 'avatar', xid) DataStore.getPersistent('global', 'avatar', xid)
); );
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') {
// Pending marker // Pending marker
self.pending.push(xid); self.pending.push(xid);
// Reset the avatar // Reset the avatar
self.reset(xid, hex_md5(xid)); self.reset(xid, hex_md5(xid));
Console.warn('No avatar for: ' + xid); Console.warn('No avatar for: ' + xid);
} }
// Try to catch the avatar // Try to catch the avatar
else { else {
// Define some stuffs // Define some stuffs
@ -72,38 +74,39 @@ 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) {
// Pending marker // Pending marker
self.pending.push(xid); self.pending.push(xid);
// Display the cache avatar // Display the cache avatar
self.display(xid, hex_md5(xid), type, binval); self.display(xid, hex_md5(xid), type, binval);
Console.info('Read avatar from cache: ' + xid); Console.info('Read avatar from cache: ' + xid);
} }
// Else if the request has not yet been fired, we get it // Else if the request has not yet been fired, we get it
else if((!updated || mode == 'force' || photo == 'forget') && enabled != 'false') { else if((!updated || mode == 'force' || photo == 'forget') && enabled != 'false') {
// Pending marker // Pending marker
self.pending.push(xid); self.pending.push(xid);
// Get the latest avatar // Get the latest avatar
var iq = new JSJaCIQ(); var iq = new JSJaCIQ();
iq.setType('get'); iq.setType('get');
iq.setTo(xid); iq.setTo(xid);
iq.appendNode('vCard', {'xmlns': NS_VCARD}); iq.appendNode('vCard', {'xmlns': NS_VCARD});
con.send(iq, self.handle); con.send(iq, self.handle);
Console.info('Get avatar from server: ' + xid); Console.info('Get avatar from server: ' + xid);
} }
} }
return true; return true;
} catch(e) { } catch(e) {
Console.error('Avatar.get', e); Console.error('Avatar.get', e);
@ -124,90 +127,94 @@ var Avatar = (function () {
// Extract the XML values // Extract the XML values
var handleXML = iq.getNode(); var handleXML = iq.getNode();
var handleFrom = Common.fullXID(Common.getStanzaFrom(iq)); var handleFrom = Common.fullXID(Common.getStanzaFrom(iq));
// Is this me? Remove the resource! // Is this me? Remove the resource!
if(Common.bareXID(handleFrom) == Common.getXID()) { if(Common.bareXID(handleFrom) == Common.getXID()) {
handleFrom = Common.bareXID(handleFrom); handleFrom = Common.bareXID(handleFrom);
} }
// Get some other values // Get some other values
var hash = hex_md5(handleFrom); var hash = hex_md5(handleFrom);
var find = $(handleXML).find('vCard'); var find = $(handleXML).find('vCard');
var aChecksum = 'none'; var aChecksum = 'none';
var oChecksum = null; var oChecksum = null;
// Read our own checksum // Read our own checksum
if(handleFrom == Common.getXID()) { if(handleFrom == Common.getXID()) {
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()) {
// We get our profile details // We get our profile details
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
var aType = find.find('TYPE:first').text(); var aType = find.find('TYPE:first').text();
var aBinval = find.find('BINVAL:first').text(); var aBinval = find.find('BINVAL:first').text();
// No binval? // No binval?
if(!aBinval) { if(!aBinval) {
aType = 'none'; aType = 'none';
aBinval = 'none'; aBinval = 'none';
} }
// 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);
// Store the avatar // Store the avatar
DataStore.setPersistent('global', 'avatar', handleFrom, '<avatar><type>' + aType + '</type><binval>' + aBinval + '</binval><checksum>' + aChecksum + '</checksum><forced>false</forced></avatar>'); DataStore.setPersistent('global', 'avatar', handleFrom, '<avatar><type>' + aType + '</type><binval>' + aBinval + '</binval><checksum>' + aChecksum + '</checksum><forced>false</forced></avatar>');
Console.info('Avatar retrieved from server: ' + handleFrom); Console.info('Avatar retrieved from server: ' + handleFrom);
} }
// vCard is empty // vCard is empty
else { else {
self.reset(handleFrom); self.reset(handleFrom);
} }
// We got a new checksum for us? // We got a new checksum for us?
if(((oChecksum !== null) && (oChecksum != aChecksum)) || !Presence.first_sent) { if(((oChecksum !== null) && (oChecksum != aChecksum)) || !Presence.first_sent) {
// 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);
@ -228,7 +235,7 @@ var Avatar = (function () {
try { try {
// Store the empty avatar // Store the empty avatar
DataStore.setPersistent('global', 'avatar', xid, '<avatar><type>none</type><binval>none</binval><checksum>none</checksum><forced>false</forced></avatar>'); DataStore.setPersistent('global', 'avatar', xid, '<avatar><type>none</type><binval>none</binval><checksum>none</checksum><forced>false</forced></avatar>');
// Display the empty avatar // Display the empty avatar
self.display(xid, hash, 'none', 'none'); self.display(xid, hash, 'none', 'none');
} catch(e) { } catch(e) {
@ -253,18 +260,19 @@ var Avatar = (function () {
// Initialize the vars // Initialize the vars
var container = hash + ' .avatar-container'; var container = hash + ' .avatar-container';
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="" />';
// Replace with the new avatar (in the roster and in the chat) // Replace with the new avatar (in the roster and in the chat)
$('.' + container).html(code); $('.' + container).html(code);
// We can remove the pending marker // We can remove the pending marker
Utils.removeArrayValue(self.pending, xid); Utils.removeArrayValue(self.pending, xid);
} catch(e) { } catch(e) {

View file

@ -17,12 +17,12 @@ var Base64 = (function () {
var chr1, chr2, chr3; var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4; var enc1, enc2, enc3, enc4;
var i = 0; var i = 0;
do { do {
chr1 = input.charCodeAt(i++); chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++); chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++); chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2; enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
@ -33,14 +33,14 @@ var Base64 = (function () {
} else if (isNaN(chr3)) { } else if (isNaN(chr3)) {
enc4 = 64; enc4 = 64;
} }
output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) +
keyStr.charAt(enc3) + keyStr.charAt(enc4); keyStr.charAt(enc3) + keyStr.charAt(enc4);
} while (i < input.length); } while (i < input.length);
return output; return output;
}, },
/** /**
* Decodes a base64 string. * Decodes a base64 string.
* @param {String} input The string to decode. * @param {String} input The string to decode.
@ -50,22 +50,22 @@ var Base64 = (function () {
var chr1, chr2, chr3; var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4; var enc1, enc2, enc3, enc4;
var i = 0; var i = 0;
// remove all characters that are not A-Z, a-z, 0-9, +, /, or = // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
do { do {
enc1 = keyStr.indexOf(input.charAt(i++)); enc1 = keyStr.indexOf(input.charAt(i++));
enc2 = keyStr.indexOf(input.charAt(i++)); enc2 = keyStr.indexOf(input.charAt(i++));
enc3 = keyStr.indexOf(input.charAt(i++)); enc3 = keyStr.indexOf(input.charAt(i++));
enc4 = keyStr.indexOf(input.charAt(i++)); enc4 = keyStr.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4); chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4; chr3 = ((enc3 & 3) << 6) | enc4;
output = output + String.fromCharCode(chr1); output = output + String.fromCharCode(chr1);
if (enc3 != 64) { if (enc3 != 64) {
output = output + String.fromCharCode(chr2); output = output + String.fromCharCode(chr2);
} }
@ -73,7 +73,7 @@ var Base64 = (function () {
output = output + String.fromCharCode(chr3); output = output + String.fromCharCode(chr3);
} }
} while (i < input.length); } while (i < input.length);
return output; return output;
} }
}; };

View file

@ -20,6 +20,137 @@ var Board = (function () {
var self = {}; var self = {};
/* Contants */
self.NOTIFICATION = (window.Notification || window.mozNotification || window.webkitNotification);
/**
* Generate board info message
* @private
* @param {string} id
* @return {string}
*/
self._generateBoardInfo = function(id) {
var text = null;
try {
switch(id) {
// Password change
case 1:
text = Common._e("Your password has been changed, now you can connect to your account with your new login data.");
break;
// Account deletion
case 2:
text = Common._e("Your XMPP account has been removed, bye!");
break;
// Account logout
case 3:
text = Common._e("You have been logged out of your XMPP account, have a nice day!");
break;
// Groupchat join
case 4:
text = Common._e("The room you tried to join doesn't seem to exist.");
break;
// Groupchat removal
case 5:
text = Common._e("The groupchat has been removed.");
break;
// Non-existant groupchat user
case 6:
text = Common._e("The user that you want to reach is not present in the room.");
break;
}
} catch(e) {
Console.error('Board._generateBoardInfo', e);
} finally {
return text;
}
};
/**
* Generate board error message
* @private
* @param {string} id
* @return {string}
*/
self._generateBoardError = function(id) {
var text = null;
try {
switch(id) {
// Custom error
case 1:
text = '<b>' + Common._e("Error") + '</b> &raquo; <span></span>';
break;
// Network error
case 2:
text = Common._e("Jappix has been interrupted by a network issue, a bug or bad login (check that you entered the right credentials), sorry for the inconvenience.");
break;
// List retrieving error
case 3:
text = Common._e("The element list on this server could not be obtained!");
break;
// Attaching error
case 4:
text = Common.printf(Common._e("An error occured while uploading your file: maybe it is too big (%s maximum) or forbidden!"), JAPPIX_MAX_UPLOAD);
break;
}
} catch(e) {
Console.error('Board._generateBoardError', e);
} finally {
return text;
}
};
/**
* Attaches board events
* @private
* @param {object} board_sel
* @return {undefined}
*/
self._attachEvents = function(board_sel) {
try {
board_sel.click(function() {
self.closeThis(this);
});
board_sel.oneTime('5s', function() {
self.closeThis(this);
});
board_sel.slideDown();
} catch(e) {
Console.error('Board._attachEvents', e);
}
};
/** /**
* Creates a board panel * Creates a board panel
* @public * @public
@ -32,97 +163,29 @@ var Board = (function () {
try { try {
// Text var // Text var
var text = ''; var text = '';
// Info // Info
if(type == 'info') { if(type == 'info') {
switch(id) { text = self._generateBoardInfo(id);
// Password change } else {
case 1: text = self._generateBoardError(id);
text = Common._e("Your password has been changed, now you can connect to your account with your new login data.");
break;
// Account deletion
case 2:
text = Common._e("Your XMPP account has been removed, bye!");
break;
// Account logout
case 3:
text = Common._e("You have been logged out of your XMPP account, have a nice day!");
break;
// Groupchat join
case 4:
text = Common._e("The room you tried to join doesn't seem to exist.");
break;
// Groupchat removal
case 5:
text = Common._e("The groupchat has been removed.");
break;
// Non-existant groupchat user
case 6:
text = Common._e("The user that you want to reach is not present in the room.");
break;
}
} }
// Error
else {
switch(id) {
// Custom error
case 1:
text = '<b>' + Common._e("Error") + '</b> &raquo; <span></span>';
break;
// Network error
case 2:
text = Common._e("Jappix has been interrupted by a network issue, a bug or bad login (check that you entered the right credentials), sorry for the inconvenience.");
break;
// List retrieving error
case 3:
text = Common._e("The element list on this server could not be obtained!");
break;
// Attaching error
case 4:
text = Common.printf(Common._e("An error occured while uploading your file: maybe it is too big (%s maximum) or forbidden!"), JAPPIX_MAX_UPLOAD);
break;
}
}
// No text? // No text?
if(!text) if(!text) {
return false; return false;
}
// Append the content // Append the content
$('#board').append('<div class="one-board ' + type + '" data-id="' + id + '">' + text + '</div>'); $('#board').append(
'<div class="one-board ' + type + '" data-id="' + id + '">' + text + '</div>'
);
// Events (click and auto-hide) // Events (click and auto-hide)
$('#board .one-board.' + type + '[data-id="' + id + '"]') self._attachEvents(
$('#board .one-board.' + type + '[data-id="' + id + '"]')
.click(function() { );
self.closeThis(this);
})
.oneTime('5s', function() {
self.closeThis(this);
})
.slideDown();
return true; return true;
} catch(e) { } catch(e) {
Console.error('Board.create', e); Console.error('Board.create', e);
@ -158,7 +221,7 @@ var Board = (function () {
try { try {
// In a first, we destroy other boards // In a first, we destroy other boards
self.destroy(); self.destroy();
// Then we display the board // Then we display the board
self.create(type, id); self.create(type, id);
} catch(e) { } catch(e) {
@ -235,99 +298,74 @@ 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;
} }
// Default icon? // Default icon?
if(!icon) { if(!icon) {
icon = './images/others/default-avatar.png'; icon = './images/others/default-avatar.png';
// Avatar icon? // Avatar icon?
if(xid) { if(xid) {
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':
Interface.switchChan(hex_md5(xid)); Interface.switchChan(hex_md5(xid));
break; break;
case 'groupchat': case 'groupchat':
Interface.switchChan(hex_md5(Common.bareXID(xid))); Interface.switchChan(hex_md5(Common.bareXID(xid)));
break; break;
default: default:
break; break;
} }
// Focus on msg-me // Focus on msg-me
window.focus(); window.focus();
// Remove notification // Remove notification
this.cancel(); this.close();
}; };
// Check for notification permission
try {
if(Notification.permission == 'granted' || Notification.permission === undefined) {
var notification = new Notification(title, {
dir: 'auto',
lang: '',
body: content,
tag: type,
icon: icon
});
notification.onclick = cb_click_fn; // Show event
notification.onshow = function() {
setTimeout(function() {
notification.close();
}, 10000);
};
setTimeout(function() { return notification;
notification.close();
}, 10000);
if(notification.permission == 'granted') {
return notification;
}
}
} catch(_e) {
if(window.webkitNotifications.checkPermission() === 0) {
// Create notification
var notification = window.webkitNotifications.createNotification(icon, title, content);
// Auto-hide after a while
notification.ondisplay = function(event) {
setTimeout(function() {
event.currentTarget.cancel();
}, 10000);
};
// Click event
notification.onclick = cb_click_fn;
// Show notification
notification.show();
return notification;
}
}
return null;
} catch(e) { } catch(e) {
Console.error('Board.quick', e); Console.error('Board.quick', e);
} }
@ -343,21 +381,7 @@ var Board = (function () {
self.quickPermission = function() { self.quickPermission = function() {
try { try {
try { self.NOTIFICATION.requestPermission();
// W3C Notification API (still a draft!)
if(Notification.permission !== 'granted') {
// Ask for permission
Notification.requestPermission();
}
} catch (_e) {
// WebKit Notification API (fallback)
if(!window.webkitNotifications || (window.webkitNotifications.checkPermission() === 0)) {
return;
}
// Ask for permission
window.webkitNotifications.requestPermission();
}
} catch(e) { } catch(e) {
Console.error('Board.quickPermission', e); Console.error('Board.quickPermission', e);
} }
@ -376,8 +400,9 @@ var Board = (function () {
// Fires quickPermission() on document click // Fires quickPermission() on document click
$(document).click(function() { $(document).click(function() {
// Ask for permission to use quick boards // Ask for permission to use quick boards
if((typeof con != 'undefined') && con.connected()) if((typeof con != 'undefined') && con.connected()) {
self.quickPermission(); self.quickPermission();
}
}); });
} catch(e) { } catch(e) {
Console.error('Board.launch', e); Console.error('Board.launch', e);

View file

@ -6,12 +6,12 @@
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";
}, },
searchString: function (data) { searchString: function (data) {
for (var i=0;i<data.length;i++) { for (var i=0;i<data.length;i++) {
var dataString = data[i].string; var dataString = data[i].string;
@ -25,13 +25,13 @@ var BrowserDetect = {
return data[i].identity; return data[i].identity;
} }
}, },
searchVersion: function (dataString) { searchVersion: function (dataString) {
var index = dataString.indexOf(this.versionSearchString); var index = dataString.indexOf(this.versionSearchString);
if (index == -1) return; if (index == -1) return;
return parseFloat(dataString.substring(index+this.versionSearchString.length+1)); return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
}, },
dataBrowser: [ dataBrowser: [
{ {
string: navigator.userAgent, string: navigator.userAgent,
@ -97,7 +97,7 @@ var BrowserDetect = {
versionSearch: "Mozilla" versionSearch: "Mozilla"
} }
], ],
dataOS : [ dataOS : [
{ {
string: navigator.platform, string: navigator.platform,

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,33 +54,36 @@ 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();
// Show the requested bubble // Show the requested bubble
$(selector).show(); $(selector).show();
} }
// 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();
} }
// Creates a new click event to close the bubble // Creates a new click event to close the bubble
$('body').on('click', function(evt) { $('body').on('click', function(evt) {
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,6 +20,444 @@ var Caps = (function () {
var self = {}; var self = {};
/* Constants */
self.disco_infos = {
'identity': {
'category': 'client',
'type': 'web',
'name': 'Jappix'
},
'items': [
NS_MUC,
NS_MUC_USER,
NS_MUC_ADMIN,
NS_MUC_OWNER,
NS_MUC_CONFIG,
NS_DISCO_INFO,
NS_DISCO_ITEMS,
NS_PUBSUB_RI,
NS_BOSH,
NS_CAPS,
NS_MOOD,
NS_ACTIVITY,
NS_TUNE,
NS_GEOLOC,
NS_NICK,
NS_URN_MBLOG,
NS_URN_INBOX,
NS_MOOD + NS_NOTIFY,
NS_ACTIVITY + NS_NOTIFY,
NS_TUNE + NS_NOTIFY,
NS_GEOLOC + NS_NOTIFY,
NS_URN_MBLOG + NS_NOTIFY,
NS_URN_INBOX + NS_NOTIFY,
NS_URN_DELAY,
NS_ROSTER,
NS_ROSTERX,
NS_HTTP_AUTH,
NS_CHATSTATES,
NS_XHTML_IM,
NS_URN_MAM,
NS_IPV6,
NS_LAST,
NS_PRIVATE,
NS_REGISTER,
NS_SEARCH,
NS_COMMANDS,
NS_VERSION,
NS_XDATA,
NS_VCARD,
NS_IETF_VCARD4,
NS_URN_ADATA,
NS_URN_AMETA,
NS_URN_TIME,
NS_URN_PING,
NS_URN_RECEIPTS,
NS_PRIVACY,
NS_IQOOB,
NS_XOOB,
NS_URN_CARBONS,
NS_URN_CORRECT,
NS_URN_MARKERS,
NS_URN_IDLE,
NS_URN_ATTENTION,
NS_URN_REACH,
NS_URN_HINTS
]
};
/**
* Parse identities from disco infos query response
* @private
* @param {object} query
* @return {object}
*/
self._parseDiscoIdentities = function(query) {
var identities = [];
try {
var cur_category, cur_type, cur_lang, cur_name;
$(query).find('identity').each(function() {
cur_category = $(this).attr('category') || '';
cur_type = $(this).attr('type') || '';
cur_lang = $(this).attr('xml:lang') || '';
cur_name = $(this).attr('name') || '';
identities.push(cur_category + '/' + cur_type + '/' + cur_lang + '/' + cur_name);
});
} catch(e) {
Console.error('Caps._parseDiscoIdentities', e);
} finally {
return identities;
}
};
/**
* Parse features from disco infos query response
* @private
* @param {object} query
* @return {object}
*/
self._parseDiscoFeatures = function(query) {
var features = [];
try {
var cur_var;
$(query).find('feature').each(function() {
cur_var = $(this).attr('var');
// Add the current value to the array
if(cur_var) {
features.push(cur_var);
}
});
} catch(e) {
Console.error('Caps._parseDiscoFatures', e);
} finally {
return features;
}
};
/**
* Parse data form from disco infos query response
* @private
* @param {object} query
* @return {object}
*/
self._parseDiscoDataForms = function(query) {
var data_forms = [];
try {
var cur_string, cur_sort_var,
cur_text, cur_var, cur_sort_val;
$(query).find('x[xmlns="' + NS_XDATA + '"]').each(function() {
// Initialize some stuffs
cur_string = '';
cur_sort_var = [];
// Add the form type field
$(this).find('field[var="FORM_TYPE"] value').each(function() {
cur_text = $(this).text();
if(cur_text) {
cur_string += cur_text + '<';
}
});
// Add the var attributes into an array
$(this).find('field:not([var="FORM_TYPE"])').each(function() {
cur_var = $(this).attr('var');
if(cur_var) {
cur_sort_var.push(cur_var);
}
});
// Sort the var attributes
cur_sort_var = cur_sort_var.sort();
// Loop this sorted var attributes
$.each(cur_sort_var, function(i) {
// Initialize the value sorting
cur_sort_val = [];
// Append it to the string
cur_string += cur_sort_var[i] + '<';
// Add each value to the array
$(this).find('field[var=' + cur_sort_var[i] + '] value').each(function() {
cur_sort_val.push($(this).text());
});
// Sort the values
cur_sort_val = cur_sort_val.sort();
// Append the values to the string
for(var j in cur_sort_val) {
cur_string += cur_sort_val[j] + '<';
}
});
// Any string?
if(cur_string) {
// Remove the undesired double '<' from the string
if(cur_string.match(/(.+)(<)+$/)) {
cur_string = cur_string.substring(0, cur_string.length - 1);
}
// Add the current string to the array
data_forms.push(cur_string);
}
});
} catch(e) {
Console.error('Caps._parseDiscoDataForms', e);
} finally {
return data_forms;
}
};
/**
* Apply XHTML-IM features from disco infos
* @private
* @param {string} xid
* @param {object} features
* @param {object} style_sel
* @param {object} message_area_sel
* @return {undefined}
*/
self._applyDiscoXHTMLIM = function(xid, features, style_sel, message_area_sel) {
try {
// Apply
if(NS_XHTML_IM in features) {
style_sel.show();
} else {
// Remove the tooltip elements
style_sel.hide();
style_sel.find('.bubble-style').remove();
// Reset the markers
message_area_sel.removeAttr('style')
.removeAttr('data-font')
.removeAttr('data-fontsize')
.removeAttr('data-color')
.removeAttr('data-bold')
.removeAttr('data-italic')
.removeAttr('data-underline');
}
} catch(e) {
Console.error('Caps._applyDiscoXHTMLIM', e);
}
};
/**
* Apply Jingle features from disco infos
* @private
* @param {string} xid
* @param {object} path_sel
* @param {object} roster_sel
* @return {undefined}
*/
self._applyDiscoJingle = function(xid, path_sel, roster_sel) {
try {
// Selectors
var roster_jingle_sel = roster_sel.find('.buddy-infos .call-jingle');
var jingle_audio = path_sel.find('.tools-jingle-audio');
var roster_jingle_audio = roster_jingle_sel.find('a.audio');
var jingle_video = path_sel.find('.tools-jingle-video');
var roster_jingle_video = roster_jingle_sel.find('a.video');
var roster_jingle_separator = roster_jingle_sel.find('span.separator');
// Apply
var jingle_local_supported = JSJAC_JINGLE_AVAILABLE;
var jingle_audio_xid = self.getFeatureResource(xid, NS_JINGLE_APPS_RTP_AUDIO);
var jingle_video_xid = self.getFeatureResource(xid, NS_JINGLE_APPS_RTP_VIDEO);
if(jingle_audio_xid && jingle_local_supported) {
jingle_audio.show();
roster_jingle_audio.show();
} else {
jingle_audio.hide();
roster_jingle_audio.hide();
}
if(jingle_video_xid && jingle_local_supported) {
jingle_video.show();
roster_jingle_video.show();
} else {
jingle_video.hide();
roster_jingle_video.hide();
}
if(jingle_audio_xid && jingle_video_xid && jingle_local_supported) {
roster_jingle_separator.show();
} else {
roster_jingle_separator.hide();
}
if((jingle_audio_xid || jingle_video_xid) && jingle_local_supported) {
roster_jingle_sel.show();
} else {
roster_jingle_sel.hide();
}
} catch(e) {
Console.error('Caps._applyDiscoJingle', e);
}
};
/**
* Apply Out of Band Data features from disco infos
* @private
* @param {string} xid
* @param {object} features
* @param {object} file_sel
* @return {undefined}
*/
self._applyDiscoOOB = function(xid, features, file_sel) {
try {
// Apply
var iq_oob_xid = self.getFeatureResource(xid, NS_IQOOB);
if(iq_oob_xid || NS_XOOB in features) {
file_sel.show();
// Set a marker
file_sel.attr(
'data-oob',
iq_oob_xid ? 'iq' : 'x'
);
} else {
// Remove the tooltip elements
file_sel.hide();
file_sel.find('.bubble-style').remove();
// Reset the marker
file_sel.removeAttr('data-oob');
}
} catch(e) {
Console.error('Caps._applyDiscoOOB', e);
}
};
/**
* Apply Receipts features from disco infos
* @private
* @param {string} xid
* @param {object} features
* @param {object} message_area_sel
* @return {undefined}
*/
self._applyDiscoReceipts = function(xid, features, message_area_sel) {
try {
// Apply
if(NS_URN_RECEIPTS in features) {
message_area_sel.attr('data-receipts', 'true');
} else {
message_area_sel.removeAttr('data-receipts');
}
} catch(e) {
Console.error('Caps._applyDiscoReceipts', e);
}
};
/**
* Apply Last Message Correction features from disco infos
* @private
* @param {string} xid
* @param {object} features
* @param {object} path_sel
* @return {undefined}
*/
self._applyDiscoCorrection = function(xid, features, path_sel) {
try {
// Apply
if(NS_URN_CORRECT in features) {
path_sel.attr('data-correction', 'true');
} else {
path_sel.removeAttr('data-correction');
}
} catch(e) {
Console.error('Caps._applyDiscoCorrection', e);
}
};
/**
* Apply Chat Markers features from disco infos
* @private
* @param {string} xid
* @param {object} features
* @param {object} path_sel
* @return {undefined}
*/
self._applyDiscoMarkers = function(xid, features, path_sel) {
try {
// Apply
if(NS_URN_MARKERS in features) {
path_sel.attr('data-markers', 'true');
} else {
path_sel.removeAttr('data-markers');
}
} catch(e) {
Console.error('Caps._applyDiscoMarkers', e);
}
};
/**
* Apply Attention features from disco infos
* @private
* @param {string} xid
* @param {object} features
* @param {object} path_sel
* @return {undefined}
*/
self._applyDiscoAttention = function(xid, features, path_sel) {
try {
// Apply
if(NS_URN_ATTENTION in features) {
path_sel.attr('data-attention', 'true');
} else {
path_sel.removeAttr('data-attention');
}
} catch(e) {
Console.error('Caps._applyDiscoAttention', e);
}
};
/** /**
* Reads a stored Caps * Reads a stored Caps
* @public * @public
@ -47,62 +485,12 @@ var Caps = (function () {
self.myDiscoInfos = function() { self.myDiscoInfos = function() {
try { try {
var disco_base = [ var disco_base = self.disco_infos.items;
NS_MUC,
NS_MUC_USER,
NS_MUC_ADMIN,
NS_MUC_OWNER,
NS_MUC_CONFIG,
NS_DISCO_INFO,
NS_DISCO_ITEMS,
NS_PUBSUB_RI,
NS_BOSH,
NS_CAPS,
NS_MOOD,
NS_ACTIVITY,
NS_TUNE,
NS_GEOLOC,
NS_NICK,
NS_URN_MBLOG,
NS_URN_INBOX,
NS_MOOD + NS_NOTIFY,
NS_ACTIVITY + NS_NOTIFY,
NS_TUNE + NS_NOTIFY,
NS_GEOLOC + NS_NOTIFY,
NS_URN_MBLOG + NS_NOTIFY,
NS_URN_INBOX + NS_NOTIFY,
NS_URN_DELAY,
NS_ROSTER,
NS_ROSTERX,
NS_HTTP_AUTH,
NS_CHATSTATES,
NS_XHTML_IM,
NS_URN_MAM,
NS_IPV6,
NS_LAST,
NS_PRIVATE,
NS_REGISTER,
NS_SEARCH,
NS_COMMANDS,
NS_VERSION,
NS_XDATA,
NS_VCARD,
NS_IETF_VCARD4,
NS_URN_ADATA,
NS_URN_AMETA,
NS_URN_TIME,
NS_URN_PING,
NS_URN_RECEIPTS,
NS_PRIVACY,
NS_IQOOB,
NS_XOOB,
NS_URN_CARBONS
];
var disco_jingle = JSJaCJingle_disco(); var disco_jingle = JSJaCJingle.disco();
var disco_all = disco_base.concat(disco_jingle); var disco_all = disco_base.concat(disco_jingle);
return disco_all; return Utils.uniqueArrayValues(disco_all);
} catch(e) { } catch(e) {
Console.error('Caps.myDiscoInfos', e); Console.error('Caps.myDiscoInfos', e);
} }
@ -123,35 +511,35 @@ var Caps = (function () {
// No CAPS // No CAPS
if(!caps) { if(!caps) {
Console.warn('No CAPS: ' + to); Console.warn('No CAPS: ' + to);
self.displayDiscoInfos(to, ''); self.displayDiscoInfos(to, '');
return false; return false;
} }
// Get the stored disco infos // Get the stored disco infos
var xml = self.read(caps); var xml = self.read(caps);
// Yet stored // Yet stored
if(xml) { if(xml) {
Console.info('CAPS from cache: ' + to); Console.info('CAPS from cache: ' + to);
self.displayDiscoInfos(to, xml); self.displayDiscoInfos(to, xml);
return true; return true;
} }
Console.info('CAPS from the network: ' + to); Console.info('CAPS from the network: ' + to);
// Not stored: get the disco#infos // Not stored: get the disco#infos
var iq = new JSJaCIQ(); var iq = new JSJaCIQ();
iq.setTo(to); iq.setTo(to);
iq.setType('get'); iq.setType('get');
iq.setQuery(NS_DISCO_INFO); iq.setQuery(NS_DISCO_INFO);
con.send(iq, self.handleDiscoInfos); con.send(iq, self.handleDiscoInfos);
return true; return true;
} catch(e) { } catch(e) {
Console.error('Caps.getDiscoInfos', e); Console.error('Caps.getDiscoInfos', e);
@ -169,123 +557,37 @@ 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);
// Get the XML string // Get the XML string
var xml = Common.xmlToString(query); var xml = Common.xmlToString(query);
// Store the disco infos // Store the disco infos
DataStore.setPersistent('global', 'caps', caps, xml); DataStore.setPersistent('global', 'caps', caps, xml);
// This is our server // This is our server
if(from == Utils.getServer()) { if(from == Utils.getServer()) {
// Handle the features // Handle the features
Features.handle(xml); Features.handle(xml);
Console.info('Got our server CAPS'); Console.info('Got our server CAPS');
} else { } else {
// Display the disco infos // Display the disco infos
self.displayDiscoInfos(from, xml); self.displayDiscoInfos(from, xml);
Console.info('Got CAPS: ' + from); Console.info('Got CAPS: ' + from);
} }
} catch(e) { } catch(e) {
@ -307,11 +609,12 @@ var Caps = (function () {
try { try {
// Generate the chat path // Generate the chat path
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);
// Display the supported features // Display the supported features
@ -324,98 +627,22 @@ var Caps = (function () {
features[current] = 1; features[current] = 1;
} }
}); });
// 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,40 +653,40 @@ 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) {
Console.error('Caps.process', e); Console.error('Caps.process', e);
@ -477,7 +704,12 @@ var Caps = (function () {
try { try {
return self.process( return self.process(
['client/web//Jappix'], [
self.disco_infos.identity.category + '/' +
self.disco_infos.identity.type + '//' +
self.disco_infos.identity.name
],
self.myDiscoInfos(), self.myDiscoInfos(),
[] []
); );
@ -507,8 +739,14 @@ var Caps = (function () {
var max_priority = null; var max_priority = null;
var cur_xid_full, cur_presence_sel, cur_caps, cur_features, cur_priority; var cur_xid_full, cur_presence_sel, cur_caps, cur_features, cur_priority;
for(var cur_resource in Presence.resources(xid)) { var resources_obj = Presence.resources(xid);
cur_xid_full = xid + '/' + cur_resource; var fn_parse_resource = function(cur_resource) {
cur_xid_full = xid;
if(cur_resource) {
cur_xid_full += '/' + cur_resource;
}
cur_presence_sel = $(Presence.readStanza(cur_xid_full)); cur_presence_sel = $(Presence.readStanza(cur_xid_full));
cur_priority = parseInt((cur_presence_sel.find('priority').text() || 0), 10); cur_priority = parseInt((cur_presence_sel.find('priority').text() || 0), 10);
@ -523,6 +761,14 @@ var Caps = (function () {
selected_xid = cur_xid_full; selected_xid = cur_xid_full;
} }
} }
};
if(resources_obj.bare === 1) {
fn_parse_resource(null);
}
for(var cur_resource in resources_obj.list) {
fn_parse_resource(cur_resource);
} }
} catch(e) { } catch(e) {
Console.error('Caps.getFeatureResource', e); Console.error('Caps.getFeatureResource', e);
@ -538,4 +784,4 @@ var Caps = (function () {
*/ */
return self; return self;
})(); })();

View file

@ -22,7 +22,7 @@ var Carbons = (function () {
/** /**
* Configures Message Carbons options * Configures Message Carbons options
* @public * @private
* @param {string} type * @param {string} type
* @return {undefined} * @return {undefined}
*/ */
@ -35,9 +35,9 @@ var Carbons = (function () {
var iq = new JSJaCIQ(); var iq = new JSJaCIQ();
iq.setType('set'); iq.setType('set');
iq.appendNode(type, {'xmlns': NS_URN_CARBONS}); iq.appendNode(type, {'xmlns': NS_URN_CARBONS});
con.send(iq, function(iq) { con.send(iq, function(iq) {
self._handleConfigure(iq, type); self._handleConfigure(iq, type);
}); });
@ -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
@ -73,7 +359,7 @@ var Chat = (function () {
var fNick = fData.find('nick').text(); var fNick = fData.find('nick').text();
var fPwd = fData.find('password').text(); var fPwd = fData.find('password').text();
var fName = fData.find('name').text(); var fName = fData.find('name').text();
// Apply the room data // Apply the room data
if(!nickname && fNick) if(!nickname && fNick)
nickname = fNick; nickname = fNick;
@ -82,11 +368,11 @@ var Chat = (function () {
if(!title && fName) if(!title && fName)
name = fName; name = fName;
} }
Groupchat.create(hash, xid, name, nickname, password); Groupchat.create(hash, xid, name, nickname, password);
} }
} }
// Switch to the newly-created chat // Switch to the newly-created chat
Interface.switchChan(hash); Interface.switchChan(hash);
} catch(e) { } catch(e) {
@ -113,121 +399,53 @@ var Chat = (function () {
// Generate some stuffs // Generate some stuffs
var path = '#' + id + ' .'; var path = '#' + id + ' .';
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">' +
'<div class="chat-tools-content chat-tools-smileys">' + '<div class="chat-tools-content chat-tools-smileys">' +
'<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>' +
'</div>' + '</div>' +
'<div class="chat-tools-content chat-tools-save">' + '<div class="chat-tools-content chat-tools-save">' +
'<a href="#" class="tools-save tools-tooltip talk-images"></a>' + '<a href="#" class="tools-save tools-tooltip talk-images"></a>' +
'</div>' + '</div>' +
'<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
$(path + 'tools-clear').click(function() {
self.clean(id);
});
// Click event: call (audio) self._generateEvents(path, id, xid);
$(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);
} }
@ -249,32 +467,38 @@ var Chat = (function () {
try { try {
// Path to the element // Path to the element
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>';
// Append the HTML code // Append the HTML code
$(chat_switch + 'chans, ' + chat_switch + 'more-content').append(html); $(chat_switch + 'chans, ' + chat_switch + 'more-content').append(html);
} catch(e) { } catch(e) {
@ -295,10 +519,10 @@ var Chat = (function () {
try { try {
// Remove the messages // Remove the messages
$('#page-engine #' + chat + ' .content .one-group').remove(); $('#page-engine #' + chat + ' .content .one-group').remove();
// Clear the history database // Clear the history database
Message.removeLocalArchive(chat); Message.removeLocalArchive(chat);
// Focus again // Focus again
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
$('#page-engine #' + chat + ' .text .message-area').focus(); $('#page-engine #' + chat + ' .text .message-area').focus();
@ -346,14 +570,14 @@ var Chat = (function () {
try { try {
Console.info('New chat: ' + xid); Console.info('New chat: ' + xid);
// Create the chat content // Create the chat content
self.generate(type, hash, xid, nick); self.generate(type, hash, xid, nick);
// 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()) {
@ -366,130 +590,73 @@ var Chat = (function () {
} else { } else {
// Restore the chat history // Restore the chat history
var chat_history = Message.readLocalArchive(hash); var chat_history = Message.readLocalArchive(hash);
if(chat_history) { if(chat_history) {
// Generate hashs // Generate hashs
var my_hash = hex_md5(Common.getXID()); var my_hash = hex_md5(Common.getXID());
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();
// Send the subscribe request // Send the subscribe request
Roster.addThisContact(xid, nick); Roster.addThisContact(xid, nick);
}).show(); }).show();
}
} }
// We catch the user's informations (like this avatar, vcard, and so on...) // We catch the user's informations (like this avatar, vcard, and so on...)
UserInfos.get(hash, xid, nick, type); UserInfos.get(hash, xid, nick, type);
// The icons-hover functions // The icons-hover functions
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() {
// Clean notifications for this chat
Interface.chanCleanNotify(hash);
// Store focus on this chat!
Interface.chat_focus_hash = hash;
});
inputDetect.blur(function() {
// Reset storage about focus on this chat!
if(Interface.chat_focus_hash == hash)
Interface.chat_focus_hash = null;
});
inputDetect.keypress(function(e) {
// Enter key
if(e.keyCode == 13) {
// Add a new line
if(e.shiftKey || e.ctrlKey) {
inputDetect.val(inputDetect.val() + '\n');
} else {
// Send the message
Message.send(hash, 'chat');
// Reset the composing database entry
DataStore.setDB(Connection.desktop_hash, 'chatstate', xid, 'off');
}
return false;
}
});
// Scroll in chat content // Input events
$('#page-engine #' + hash + ' .content').scroll(function() { ChatState.events(input_sel, xid, hash, 'chat');
var self = this; Markers.events(input_sel, xid, hash, 'chat');
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);
} }
@ -502,4 +669,4 @@ var Chat = (function () {
*/ */
return self; return self;
})(); })();

View file

@ -32,24 +32,27 @@ var ChatState = (function () {
try { try {
var user_type = $('#' + hash).attr('data-type'); var user_type = $('#' + hash).attr('data-type');
// 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);
// New message stanza // New message stanza
var aMsg = new JSJaCMessage(); var aMsg = new JSJaCMessage();
aMsg.setTo(xid); aMsg.setTo(xid);
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);
} }
@ -74,58 +77,61 @@ var ChatState = (function () {
// Groupchat? // Groupchat?
if(type == 'groupchat') { if(type == 'groupchat') {
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 {
// We change the buddy name color in the page-switch // We change the buddy name color in the page-switch
self.reset(hash, type); self.reset(hash, type);
$('#page-switch .' + hash + ' .name').addClass(state); $('#page-switch .' + hash + ' .name').addClass(state);
// We generate the chatstate text // We generate the chatstate text
var text = ''; var text = '';
switch(state) { switch(state) {
// Active // Active
case 'active': case 'active':
text = Common._e("Your friend is paying attention to the conversation."); text = Common._e("Your friend is paying attention to the conversation.");
break; break;
// Composing // Composing
case 'composing': case 'composing':
text = Common._e("Your friend is writing a message..."); text = Common._e("Your friend is writing a message...");
break; break;
// Paused // Paused
case 'paused': case 'paused':
text = Common._e("Your friend stopped writing a message."); text = Common._e("Your friend stopped writing a message.");
break; break;
// Inactive // Inactive
case 'inactive': case 'inactive':
text = Common._e("Your friend is doing something else."); text = Common._e("Your friend is doing something else.");
break; break;
// Gone // Gone
case 'gone': case 'gone':
text = Common._e("Your friend closed the chat."); text = Common._e("Your friend closed the chat.");
break; break;
} }
// We reset the previous state // We reset the previous state
$('#' + 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);
@ -146,12 +152,13 @@ var ChatState = (function () {
try { try {
// 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');
} catch(e) { } catch(e) {
@ -179,53 +186,56 @@ var ChatState = (function () {
if($(this).val() && (DataStore.getDB(Connection.desktop_hash, 'chatstate', xid) != 'on')) { if($(this).val() && (DataStore.getDB(Connection.desktop_hash, 'chatstate', xid) != 'on')) {
// We change the state detect input // We change the state detect input
DataStore.setDB(Connection.desktop_hash, 'chatstate', xid, 'on'); DataStore.setDB(Connection.desktop_hash, 'chatstate', xid, 'on');
// We send the friend a "composing" chatstate // We send the friend a "composing" chatstate
self.send('composing', xid, hash); self.send('composing', xid, hash);
} }
// Flushed the message which was being composed // Flushed the message which was being composed
else if(!$(this).val() && (DataStore.getDB(Connection.desktop_hash, 'chatstate', xid) == 'on')) { else if(!$(this).val() && (DataStore.getDB(Connection.desktop_hash, 'chatstate', xid) == 'on')) {
// We change the state detect input // We change the state detect input
DataStore.setDB(Connection.desktop_hash, 'chatstate', xid, 'off'); DataStore.setDB(Connection.desktop_hash, 'chatstate', xid, 'off');
// We send the friend an "active" chatstate // We send the friend an "active" chatstate
self.send('active', xid, hash); self.send('active', xid, hash);
} }
} }
}); });
target.change(function() { target.change(function() {
// Reset the composing database entry // Reset the composing database entry
DataStore.setDB(Connection.desktop_hash, 'chatstate', xid, 'off'); DataStore.setDB(Connection.desktop_hash, 'chatstate', xid, 'off');
}); });
target.focus(function() { target.focus(function() {
// Not needed // Not needed
if(target.is(':disabled')) if(target.is(':disabled')) {
return; return;
}
// Something was written, user started writing again // Something was written, user started writing again
if($(this).val()) if($(this).val()) {
self.send('composing', xid, hash); self.send('composing', xid, hash);
}
// Chat only: Nothing in the input, user is active // Chat only: Nothing in the input, user is active
else if(type == 'chat') else if(type == 'chat') {
self.send('active', xid, hash); self.send('active', xid, hash);
}
}); });
target.blur(function() { target.blur(function() {
// Not needed // Not needed
if(target.is(':disabled')) if(target.is(':disabled')) {
return; return;
}
// Something was written, user paused
if($(this).val())
self.send('paused', xid, hash);
// Chat only: Nothing in the input, user is inactive // Something was written, user paused
else if(type == 'chat') if($(this).val()) {
self.send('paused', xid, hash);
} else if(type == 'chat') {
self.send('inactive', xid, hash); self.send('inactive', xid, hash);
}
}); });
} catch(e) { } catch(e) {
Console.error('ChatState.events', e); Console.error('ChatState.events', e);

View file

@ -20,6 +20,10 @@ var Common = (function () {
var self = {}; var self = {};
/* Constants */
self.R_DOMAIN_NAME = /^(([a-zA-Z0-9-\.]+)\.)?[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9]\.[a-zA-Z]{2,}$/i;
/** /**
* Checks if an element exists in the DOM * Checks if an element exists in the DOM
* @public * @public
@ -109,6 +113,29 @@ var Common = (function () {
}; };
/**
* Matches a domain name
* @public
* @param {string} xid
* @return {boolean}
*/
self.isDomain = function(xid) {
is_domain = false;
try {
if(xid.match(self.R_DOMAIN_NAME)) {
is_domain = true;
}
} catch(e) {
Console.error('Common.isDomain', e);
} finally {
return is_domain;
}
};
/** /**
* Generates the good XID * Generates the good XID
* @public * @public
@ -120,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
if(xid.indexOf('.') == -1) // Gateway XID
return xid + '@' + HOST_MAIN; if(self.isDomain(xid) === true) {
return xid;
// It might be a gateway? }
return xid;
// User XID
return xid + '@' + HOST_MAIN;
} }
// Nothing special (yet bare XID) // Nothing special (yet bare XID)
return xid; return xid;
} catch(e) { } catch(e) {
@ -190,15 +218,17 @@ 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) {
Console.error('Common.strAfterLast', e); Console.error('Common.strAfterLast', e);
@ -220,15 +250,16 @@ var Common = (function () {
try { try {
// Get the index of our char to explode // Get the index of our char to explode
var index = toStr.indexOf(toEx); var index = toStr.indexOf(toEx);
// 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;
} catch(e) { } catch(e) {
@ -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
@ -358,12 +424,12 @@ var Common = (function () {
try { try {
// Cut the resource // Cut the resource
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;
} catch(e) { } catch(e) {
Console.error('Common.bareXID', e); Console.error('Common.bareXID', e);
@ -384,11 +450,12 @@ var Common = (function () {
// Normalizes the XID // Normalizes the XID
var full = self.bareXID(xid); var full = self.bareXID(xid);
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) {
Console.error('Common.fullXID', e); Console.error('Common.fullXID', e);
@ -401,15 +468,19 @@ var Common = (function () {
* Gets the nick from a XID * Gets the nick from a XID
* @public * @public
* @param {string} aXID * @param {string} aXID
* @param {boolean} raw_explode
* @return {string} * @return {string}
*/ */
self.getXIDNick = function(aXID) { self.getXIDNick = function(aXID, raw_explode) {
try { try {
// Gateway nick? if(raw_explode !== true) {
if(aXID.match(/\\40/)) // Gateway nick?
return self.explodeThis('\\40', aXID, 0); if(aXID.match(/\\40/)) {
return self.explodeThis('\\40', aXID, 0);
}
}
return self.explodeThis('@', aXID, 0); return self.explodeThis('@', aXID, 0);
} catch(e) { } catch(e) {
Console.error('Common.getXIDNick', e); Console.error('Common.getXIDNick', 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}
*/ */
@ -495,7 +566,7 @@ var Common = (function () {
if(con.username && con.domain) { if(con.username && con.domain) {
return con.username + '@' + con.domain; return con.username + '@' + con.domain;
} }
return ''; return '';
} catch(e) { } catch(e) {
Console.error('Common.getXID', e); Console.error('Common.getXID', e);
@ -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
@ -521,15 +615,15 @@ var Common = (function () {
'00236b', '00236b',
'4e005c' '4e005c'
); );
var number = 0; var number = 0;
for(var i = 0; i < xid.length; i++) { for(var i = 0; i < xid.length; i++) {
number += xid.charCodeAt(i); number += xid.charCodeAt(i);
} }
var color = '#' + colors[number % (colors.length)]; var color = '#' + colors[number % (colors.length)];
return color; return color;
} catch(e) { } catch(e) {
Console.error('Common.generateColor', e); Console.error('Common.generateColor', e);
@ -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) {
@ -571,12 +665,12 @@ var Common = (function () {
try { try {
var from = stanza.getFrom(); var from = stanza.getFrom();
// No from, we assume this is our XID // No from, we assume this is our XID
if(!from) { if(!from) {
from = self.getXID(); from = self.getXID();
} }
return from; return from;
} catch(e) { } catch(e) {
Console.error('Common.getStanzaFrom', e); Console.error('Common.getStanzaFrom', e);
@ -618,13 +712,15 @@ 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;
} catch(e) { } catch(e) {
@ -643,23 +739,31 @@ var Common = (function () {
*/ */
self.escapeRegex = function(query) { self.escapeRegex = function(query) {
if (query instanceof Array) { var result = [];
var result = new Array(query.length);
for(i=0; i<query.length; i++) { try {
if(query instanceof Array) {
result = [query.length];
for(i = 0; i < query.length; i++) {
try {
result[i] = Common.escapeRegex(query[i]);
} catch(e) {
Console.error('Common.escapeRegex', e);
result[i] = null;
}
}
} else {
try { try {
result[i] = Common.escapeRegex(query[i]); result = query.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
} catch(e) { } catch(e) {
Console.error('Common.escapeRegex', e); Console.error('Common.escapeRegex[inner]', e);
result[i] = null;
} }
} }
} catch(e) {
Console.error('Common.escapeRegex', e);
} finally {
return result; return result;
} else {
try {
return query.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
} catch(e) {
Console.error('Common.escapeRegex', e);
}
} }
}; };
@ -717,7 +821,7 @@ var Common = (function () {
if(window.XMLSerializer) { if(window.XMLSerializer) {
xml_str = (new XMLSerializer()).serializeToString(xmlData); xml_str = (new XMLSerializer()).serializeToString(xmlData);
} }
// For Internet Explorer // For Internet Explorer
if(window.ActiveXObject) { if(window.ActiveXObject) {
xml_str = xmlData.xml; xml_str = xmlData.xml;
@ -744,21 +848,21 @@ var Common = (function () {
if(!sXML) { if(!sXML) {
return ''; return '';
} }
// Add the XML tag // Add the XML tag
if(!sXML.match(/^<\?xml/i)) { if(!sXML.match(/^<\?xml/i)) {
sXML = '<?xml version="1.0"?>' + sXML; sXML = '<?xml version="1.0"?>' + sXML;
} }
// Parse it! // Parse it!
if(window.DOMParser) { if(window.DOMParser) {
return (new DOMParser()).parseFromString(sXML, 'text/xml'); return (new DOMParser()).parseFromString(sXML, 'text/xml');
} }
if(window.ActiveXObject) { if(window.ActiveXObject) {
var oXML = new ActiveXObject('Microsoft.XMLDOM'); var oXML = new ActiveXObject('Microsoft.XMLDOM');
oXML.loadXML(sXML); oXML.loadXML(sXML);
return oXML; return oXML;
} }
} catch(e) { } catch(e) {
@ -780,7 +884,7 @@ var Common = (function () {
try { try {
var timer = 0; var timer = 0;
return function(callback, ms) { return function(callback, ms) {
clearTimeout(timer); clearTimeout(timer);
timer = setTimeout(callback, ms); timer = setTimeout(callback, ms);
@ -799,4 +903,4 @@ var Common = (function () {
})(); })();
var JappixCommon = Common; var JappixCommon = Common;

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,14 +244,14 @@ 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');
// We add the login wait div // We add the login wait div
Interface.showGeneralWait(); Interface.showGeneralWait();
if(Common.hasWebSocket()) { if(Common.hasWebSocket()) {
// WebSocket supported & configured // WebSocket supported & configured
con = new JSJaCWebSocketConnection({ con = new JSJaCWebSocketConnection({
@ -63,56 +262,56 @@ var Connection = (function () {
// Check BOSH origin // Check BOSH origin
BOSH_SAME_ORIGIN = Origin.isSame(httpbase); BOSH_SAME_ORIGIN = Origin.isSame(httpbase);
// We create the new http-binding connection // We create the new http-binding connection
con = new JSJaCHttpBindingConnection({ con = new JSJaCHttpBindingConnection({
httpbase: httpbase httpbase: httpbase
}); });
} }
// 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');
if(!random_resource) { if(!random_resource) {
random_resource = lResource + ' (' + (new Date()).getTime() + ')'; random_resource = lResource + ' (' + (new Date()).getTime() + ')';
} }
// We retrieve what the user typed in the login inputs
oArgs = {};
oArgs.domain = $.trim(lServer);
oArgs.username = $.trim(lNick);
oArgs.resource = random_resource;
oArgs.pass = lPass;
oArgs.secure = true;
oArgs.xmllang = XML_LANG;
self.desktop_hash = 'jd.' + hex_md5(oArgs.username + '@' + oArgs.domain); var con_args = {
'domain': lServer.trim(),
'username': lNick.trim(),
'resource': random_resource,
'pass': lPass,
'secure': true,
'xmllang': XML_LANG
};
self.desktop_hash = 'jd.' + hex_md5(con_args.username + '@' + con_args.domain);
// Store the resource (for reconnection) // Store the resource (for reconnection)
DataStore.setDB(self.desktop_hash, 'session', 'resource', random_resource); DataStore.setDB(self.desktop_hash, 'session', 'resource', random_resource);
// Store session XML in temporary database // Store session XML in temporary database
self.storeSession(lNick, lServer, lPass, lResource, lPriority, lRemember); self.storeSession(lNick, lServer, lPass, lResource, lPriority, lRemember);
// We store the infos of the user into the data-base // We store the infos of the user into the data-base
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');
Console.info('Jappix is connecting...'); Console.info('Jappix is connecting...');
} catch(e) { } catch(e) {
Console.error('Connection.doLogin', e); Console.error('Connection.doLogin', e);
// Reset Jappix // Reset Jappix
Talk.destroy(); Talk.destroy();
// Open an unknown error // Open an unknown error
Board.openThisError(2); Board.openThisError(2);
} finally { } finally {
@ -131,16 +330,16 @@ var Connection = (function () {
try { try {
Console.info('A new account has been registered.'); Console.info('A new account has been registered.');
// We remove the waiting image // We remove the waiting image
Interface.removeGeneralWait(); Interface.removeGeneralWait();
// Reset the title // Reset the title
Interface.title('home'); Interface.title('home');
// We show the success information // We show the success information
$('#home .registerer .success').fadeIn('fast'); $('#home .registerer .success').fadeIn('fast');
// We quit the session // We quit the session
if(Common.isConnected()) { if(Common.isConnected()) {
self.logout(); self.logout();
@ -165,116 +364,25 @@ var Connection = (function () {
try { try {
Console.info('Trying to register an account...'); Console.info('Trying to register an account...');
// 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>'
); );
// Login link // Login link
$('#home .homediv.registerer .success a').click(function() { $('#home .homediv.registerer .success a').click(function() {
return self.doLogin(username, domain, pass, '', '10', false); return self.doLogin(username, domain, pass, '', '10', false);
}); });
if((REGISTER_API == 'on') && (domain == HOST_MAIN) && captcha) { if((REGISTER_API == 'on') && (domain == HOST_MAIN) && captcha) {
// Show the waiting image self._doRegisterAPI(username, domain, pass, captcha);
Interface.showGeneralWait();
// Change the page title
Interface.title('wait');
// Send request
$.post('./server/register.php', {username: username, domain: domain, password: pass, captcha: captcha}, function(data) {
// Error registering
Interface.removeGeneralWait();
Interface.title('home');
// In all case, update CAPTCHA
$('#home img.captcha_img').attr('src', './server/captcha.php?id=' + genID());
$('#home input.captcha').val('');
// Registration okay
if($(data).find('query status').text() == '1') {
self.handleRegistered();
} else {
// Show error message
var error_message = '';
switch($(data).find('query message').text()) {
case 'CAPTCHA Not Matching':
error_message = Common._e("The security code you entered is invalid. Please retry with another one.");
$('#home input.captcha').focus();
break;
case 'Username Unavailable':
error_message = Common._e("The username you picked is not available. Please try another one.");
$('#home input.nick').focus();
break;
default:
error_message = Common._e("There was an error registering your account. Please retry.");
break;
}
if(error_message)
Errors.show('', error_message, '');
}
});
} else { } else {
try { self._doRegisterInBand(username, domain, pass);
oArgs = {};
if(Common.hasWebSocket()) {
// WebSocket supported & configured
con = new JSJaCWebSocketConnection({
httpbase: HOST_WEBSOCKET
});
} else {
var httpbase = (HOST_BOSH_MAIN || HOST_BOSH);
// Check BOSH origin
BOSH_SAME_ORIGIN = Origin.isSame(httpbase);
// We create the new http-binding connection
con = new JSJaCHttpBindingConnection({
httpbase: httpbase
});
}
// We setup the connection !
con.registerHandler('onconnect', self.handleRegistered);
con.registerHandler('onerror', Errors.handle);
// We retrieve what the user typed in the register inputs
oArgs = {};
oArgs.domain = $.trim(domain);
oArgs.username = $.trim(username);
oArgs.resource = JAPPIX_RESOURCE + ' Register (' + (new Date()).getTime() + ')';
oArgs.pass = pass;
oArgs.register = true;
oArgs.secure = true;
oArgs.xmllang = XML_LANG;
con.connect(oArgs);
// Show the waiting image
Interface.showGeneralWait();
// Change the page title
Interface.title('wait');
}
catch(e) {
// Logs errors
Console.error('doRegister', e);
}
} }
} catch(e) { } catch(e) {
Console.error('Connection.doRegister', e); Console.error('Connection.doRegister', e);
@ -294,31 +402,29 @@ var Connection = (function () {
try { try {
Console.info('Trying to login anonymously...'); Console.info('Trying to login anonymously...');
var aPath = '#home .anonymouser '; var path_sel = $('#home .anonymouser');
var room = $(aPath + '.room').val(); var room = path_sel.find('.room').val();
var nick = $(aPath + '.nick').val(); var nick = path_sel.find('.nick').val();
// If the form is correctly completed // Form correctly completed?
if(room && nick) { if(room && nick) {
// We remove the not completed class to avoid problems // We remove the not completed class to avoid problems
$('#home .anonymouser input').removeClass('please-complete'); $('#home .anonymouser input').removeClass('please-complete');
// Redirect the user to the anonymous room // Redirect the user to the anonymous room
window.location.href = JAPPIX_LOCATION + '?r=' + room + '&n=' + nick; window.location.href = JAPPIX_LOCATION + '?r=' + room + '&n=' + nick;
} } else {
path_sel.find('input[type="text"]').each(function() {
// We check if the form is entirely completed var this_sel = $(this);
else {
$(aPath + 'input[type="text"]').each(function() { if(!this_sel.val()) {
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) {
@ -339,23 +445,23 @@ var Connection = (function () {
try { try {
Console.info('Jappix is now connected.'); Console.info('Jappix is now connected.');
// Connection markers // Connection markers
self.connected = true; self.connected = true;
self.reconnect_try = 0; self.reconnect_try = 0;
self.reconnect_timer = 0; self.reconnect_timer = 0;
// We hide the home page // We hide the home page
$('#home').hide(); $('#home').hide();
// Any suggest to do before triggering connected event? // Any suggest to do before triggering connected event?
Groupchat.suggestCheck(); Groupchat.suggestCheck();
// 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,27 +480,28 @@ 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();
// We reset the homepage // We reset the homepage
Home.change('default'); Home.change('default');
// We get all the other things // We get all the other things
self.getEverything(); self.getEverything();
// Set last activity stamp // Set last activity stamp
DateUtils.last_activity = DateUtils.getTimeStamp(); DateUtils.last_activity = DateUtils.getTimeStamp();
} }
// Resumed // Resumed
else { else {
// Send our presence // Send our presence
Presence.sendActions(); Presence.sendActions();
// Change the title // Change the title
Interface.updateTitle(); Interface.updateTitle();
} }
@ -414,7 +521,10 @@ 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) {
@ -496,13 +614,13 @@ var Connection = (function () {
if(Common.isConnected()) { if(Common.isConnected()) {
// Clear temporary session storage // Clear temporary session storage
self.resetConMarkers(); self.resetConMarkers();
// Show the waiting item (useful if BOSH is sloooow) // Show the waiting item (useful if BOSH is sloooow)
Interface.showGeneralWait(); Interface.showGeneralWait();
// Change the page title // Change the page title
Interface.title('wait'); Interface.title('wait');
// Disconnect from the XMPP server // Disconnect from the XMPP server
self.logout(); self.logout();
} }
@ -525,13 +643,13 @@ var Connection = (function () {
if(!Common.isConnected()) { if(!Common.isConnected()) {
return; return;
} }
// We show the waiting image // We show the waiting image
Interface.showGeneralWait(); Interface.showGeneralWait();
// Change the page title // Change the page title
Interface.title('wait'); Interface.title('wait');
// We disconnect from the XMPP server // We disconnect from the XMPP server
self.logout(); self.logout();
} catch(e) { } catch(e) {
@ -551,60 +669,34 @@ var Connection = (function () {
try { try {
Console.error('This is not a normal disconnection, show the reconnect pane...'); Console.error('This is not a normal disconnection, show the reconnect pane...');
// Reconnect pane not yet displayed? // Reconnect pane not yet displayed?
if(!Common.exists('#reconnect')) { if(!Common.exists('#reconnect')) {
// Blur the focused input/textarea/select // Blur the focused input/textarea/select
$('input, select, textarea').blur(); $('input, select, textarea').blur();
// Create the HTML code // Create the HTML code
var html = '<div id="reconnect" class="lock">' + var html = '<div id="reconnect" class="lock">' +
'<div class="pane">' + '<div class="pane">' +
Common._e("Due to a network issue, you were disconnected. What do you want to do now?"); Common._e("Due to a network issue, you were disconnected. What do you want to do now?");
// Can we cancel reconnection? // Can we cancel reconnection?
if(mode == 'normal') if(mode == 'normal') {
html += '<a href="#" class="finish cancel">' + Common._e("Cancel") + '</a>'; html += '<a href="#" class="finish cancel">' + Common._e("Cancel") + '</a>';
}
html += '<a href="#" class="finish reconnect">' + Common._e("Reconnect") + '</a>' +
'</div></div>'; html += '<a href="#" class="finish reconnect">' + Common._e("Reconnect") + '</a>' +
'</div></div>';
// Append the code // Append the code
$('body').append(html); $('body').append(html);
// Click events // Attach events
if(mode == 'normal') self._eventsReconnect(mode);
$('#reconnect a.finish.cancel').click(function() {
return self.cancelReconnect(); // Schedule next reconnect
}); self._scheduleReconnect(mode);
$('#reconnect a.finish.reconnect').click(function() {
return self.acceptReconnect(mode);
});
// Try to reconnect automatically after a while
if(self.reconnect_try < 5)
self.reconnect_timer = 5 + (5 * self.reconnect_try);
else
self.reconnect_timer = 120;
// Change the try number
self.reconnect_try++;
// Fire the event!
$('#reconnect a.finish.reconnect').everyTime('1s', function() {
// We can reconnect!
if(self.reconnect_timer === 0)
return self.acceptReconnect(mode);
// Button text
if(self.reconnect_timer <= 10)
$(this).text(Common._e("Reconnect") + ' (' + self.reconnect_timer + ')');
// Remove 1 second
self.reconnect_timer--;
});
// Page title // Page title
Interface.updateTitle(); Interface.updateTitle();
} }
@ -625,30 +717,33 @@ var Connection = (function () {
try { try {
Console.info('Trying to reconnect the user...'); Console.info('Trying to reconnect the user...');
// Resume marker // Resume marker
self.resume = true; self.resume = true;
// Show waiting item // Show waiting item
Interface.showGeneralWait(); Interface.showGeneralWait();
// 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();
// Remove the reconnect pane // Remove the reconnect pane
$('#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 {
@ -667,16 +762,16 @@ var Connection = (function () {
try { try {
Console.info('User has canceled automatic reconnection...'); Console.info('User has canceled automatic reconnection...');
// Stop the timer // Stop the timer
$('#reconnect a.finish.reconnect').stopTime(); $('#reconnect a.finish.reconnect').stopTime();
// Remove the reconnect pane // Remove the reconnect pane
$('#reconnect').remove(); $('#reconnect').remove();
// Destroy the talk page // Destroy the talk page
Talk.destroy(); Talk.destroy();
// Renitialize the previous session parameters // Renitialize the previous session parameters
self.resetConMarkers(); self.resetConMarkers();
} catch(e) { } catch(e) {
@ -698,7 +793,7 @@ var Connection = (function () {
try { try {
// Clear temporary storage // Clear temporary storage
self.resetConMarkers(); self.resetConMarkers();
// Clear persistent storage // Clear persistent storage
if($(Common.XMLFromString(DataStore.getPersistent('global', 'session', 1))).find('stored').text() == 'true') { if($(Common.XMLFromString(DataStore.getPersistent('global', 'session', 1))).find('stored').text() == 'true') {
DataStore.removePersistent('global', 'session', 1); DataStore.removePersistent('global', 'session', 1);
@ -741,7 +836,7 @@ var Connection = (function () {
try { try {
// Select the data // Select the data
var session = $(data); var session = $(data);
// Fire the login event // Fire the login event
self.doLogin( self.doLogin(
session.find('username').text(), session.find('username').text(),
@ -768,10 +863,10 @@ var Connection = (function () {
try { try {
// Reset our database // Reset our database
self.clearLastSession(); self.clearLastSession();
// We quit the current session // We quit the current session
self.quit(); self.quit();
// We show an info // We show an info
Board.openThisInfo(3); Board.openThisInfo(3);
} catch(e) { } catch(e) {
@ -817,16 +912,23 @@ 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;
// Remember me? // Remember me?
if(lRemember) { if(lRemember) {
DataStore.setDB(self.desktop_hash, 'remember', 'session', 1); DataStore.setDB(self.desktop_hash, 'remember', 'session', 1);
} }
return session_xml; return session_xml;
} catch(e) { } catch(e) {
Console.error('Connection.storeSession', e); Console.error('Connection.storeSession', e);
@ -846,11 +948,12 @@ var Connection = (function () {
$(document).ready(function() { $(document).ready(function() {
// Logouts when Jappix is closed // Logouts when Jappix is closed
$(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) {
// Generate login data // Generate login data
@ -861,51 +964,56 @@ var Connection = (function () {
var login_resource = JAPPIX_RESOURCE + ' (' + (new Date()).getTime() + ')'; var login_resource = JAPPIX_RESOURCE + ' (' + (new Date()).getTime() + ')';
var login_priority = '10'; var login_priority = '10';
var login_remember = 1; var login_remember = 1;
// 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
document.location.href = './'; document.location.href = './';
} else { } else {
// Hide the homepage // Hide the homepage
$('#home').hide(); $('#home').hide();
// Show the waiting icon // Show the waiting icon
Interface.showGeneralWait(); Interface.showGeneralWait();
// Proceed login // Proceed login
self.doLogin(login_nick, login_server, login_pwd, login_resource, login_priority, login_remember); self.doLogin(login_nick, login_server, login_pwd, login_resource, login_priority, login_remember);
} }
return; return;
} }
// Try to resume a stored session, if not anonymous // Try to resume a stored session, if not anonymous
var session = Common.XMLFromString( var session = Common.XMLFromString(
DataStore.getPersistent('global', 'session', 1) DataStore.getPersistent('global', 'session', 1)
); );
if($(session).find('stored').text() == 'true') { if($(session).find('stored').text() == 'true') {
// Hide the homepage // Hide the homepage
$('#home').hide(); $('#home').hide();
// Show the waiting icon // Show the waiting icon
Interface.showGeneralWait(); Interface.showGeneralWait();
// Login! // Login!
self.loginFromSession(session); self.loginFromSession(session);
Console.info('Saved session found, resuming it...'); Console.info('Saved session found, resuming it...');
} } else if((parent.location.hash != '#OK') && XMPPLinks.links_var.x) {
// Not connected, maybe a XMPP link is submitted?
else if((parent.location.hash != '#OK') && XMPPLinks.links_var.x) {
Home.change('loginer'); Home.change('loginer');
Console.info('A XMPP link is set, switch to login page.'); Console.info('A XMPP link is set, switch to login page.');
} }
}); });

View file

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

View file

@ -0,0 +1,509 @@
/*
Jappix - An open social platform
Implementation of XEP-0308: Last Message Correction
-------------------------------------------------
License: AGPL
Author: Valérian Saliou
*/
// Bundle
var Correction = (function () {
/**
* Alias of this
* @private
*/
var self = {};
/**
* @private
* @param {string} xid
* @return {boolean}
*/
self._hasSupport = function(xid) {
var support = false;
try {
if($('#' + hex_md5(xid) + '[data-correction="true"]').size()) {
support = true;
}
} catch(e) {
Console.error('Correction._hasSupport', e);
} finally {
return support;
}
};
/**
* @private
* @param {string} xid
* @return {string}
*/
self._getLastID = function(xid) {
var last_id = null;
try {
if(self._hasSupport(xid) === true) {
// Check last message from ourselves
last_id = $('#' + hex_md5(xid) + ' .content .one-line.user-message[data-mode="me"]:last').attr('data-id') || null;
}
} catch(e) {
Console.error('Correction._getLastID', e);
} finally {
return last_id;
}
};
/**
* @private
* @param {string} xid
* @return {string}
*/
self._getCurrentID = function(xid) {
var current_id = null;
try {
if(self._hasSupport(xid) === true) {
// Check the ID of the message being edited (if any)
current_id = $('#' + hex_md5(xid) + ' .message-area').attr('data-correction-current') || null;
}
} catch(e) {
Console.error('Correction._getCurrentID', e);
} finally {
return current_id;
}
};
/**
* @private
* @param {string} xid
* @return {object}
*/
self._getLastMessage = function(xid) {
var last_message_val = null;
var last_message_sel = null;
try {
if(self._hasSupport(xid) === true) {
// Check last message from ourselves
last_message_sel = $('#' + hex_md5(xid) + ' .content .one-line.user-message[data-mode="me"]:last');
last_message_val = last_message_sel.find('.message-content').text() || null;
if(last_message_val === null) {
last_message_sel = null;
}
}
} catch(e) {
Console.error('Correction._getLastMessage', e);
} finally {
return {
'value': last_message_val,
'selector': last_message_sel
};
}
};
/**
* @private
* @param {string} xid
* @param {object} message_sel
* @return {undefined}
*/
self._bindInterface = function(xid, message_sel) {
try {
// Add message area elements
var text_sel = $('#' + hex_md5(xid) + ' .text');
text_sel.addClass('correction-active');
text_sel.prepend(
'<div class="correction-toolbox">' +
'<span class="correction-editing">' + Common._e("Editing") + '</span>' +
'<a class="correction-cancel" href="#">' + Common._e("Cancel") + '</a>' +
'</div>'
);
// Add message correction marker
message_sel.addClass('correction-active');
message_sel.find('.correction-label').remove();
message_sel.find('.correction-edit').hide();
message_sel.append(
'<span class="correction-label">' +
Common._e("Being edited") +
'</span>'
);
// Bind click events
text_sel.find('.correction-cancel').click(function() {
self.leave(xid);
return false;
});
} catch(e) {
Console.error('Correction._bindInterface', e);
}
};
/**
* @private
* @param {string} xid
* @param {object} message_sel
* @return {undefined}
*/
self._unbindInterface = function(xid, message_sel) {
try {
// Remove message area elements
var text_sel = $('#' + hex_md5(xid) + ' .text');
text_sel.removeClass('correction-active');
text_sel.find('.correction-toolbox, .correction-label').remove();
if(message_sel.size()) {
message_sel.find('.correction-edit').css('display', '');
// Remove message correction marker
message_sel.removeClass('correction-active');
message_sel.find('.correction-label').remove();
}
} catch(e) {
Console.error('Correction._unbindInterface', e);
}
};
/**
* @private
* @param {string} xid
* @param {string} full_xid
* @param {string} type
* @param {string} message_id
* @param {string} message_body
* @return {string}
*/
self._sendStanza = function(xid, full_xid, type, message_id, message_body) {
var args = {
'id': null,
'xhtml': false,
'message': null
};
try {
var hash = hex_md5(xid);
var id = genID();
args.id = id;
// Initialize message stanza
var message = new JSJaCMessage();
args.message = message;
message.setType(type);
message.setTo(full_xid);
message.setID(id);
// Generates the correct message depending of the choosen style
var generate_message = Message.generate(message, message_body, hash);
args.xhtml = (generate_message === 'XHTML');
// Receipt request
var receipt_request = Receipts.request(hash);
if(receipt_request) {
message.appendNode('request', {'xmlns': NS_URN_RECEIPTS});
}
// Chatstate
message.appendNode('active', {'xmlns': NS_CHATSTATES});
if(message_id !== null) {
message.appendNode('replace', {
'xmlns': NS_URN_CORRECT,
'id': message_id
});
}
con.send(message, Errors.handleReply);
} catch(e) {
Console.error('Correction._sendStanza', e);
} finally {
return args;
}
};
/**
* Detects correction mode request (in input)
* @public
* @param {string} xid
* @param {object} input_sel
* @return {undefined}
*/
self.detect = function(xid, input_sel) {
try {
// Other keys
if(input_sel.val().match(/^\/correct/) && self.isIn(xid) === false) {
// Enter correction mode?
self.enter(xid);
}
} catch(e) {
Console.error('Correction.detect', e);
}
};
/**
* Enter correction mode (for last message)
* @public
* @param {string} xid
* @return {undefined}
*/
self.enter = function(xid) {
try {
Console.debug('Correction.enter', 'Requested to enter the correction mode with: ' + xid);
if(self._hasSupport(xid) === true && self.isIn(xid) === false) {
var last_message = self._getLastMessage(xid);
if(last_message.value && last_message.selector) {
Console.info('Correction.enter', 'Valid last message found for correction mode with: ' + xid);
var message_area_sel = $('#' + hex_md5(xid) + ' .message-area');
message_area_sel.val(last_message.value);
self._bindInterface(
xid,
last_message.selector
);
// Focus hack (to get cursor at the end of textarea)
message_area_sel.oneTime(10, function() {
message_area_sel[0].select();
message_area_sel[0].selectionStart = message_area_sel[0].selectionEnd;
});
}
}
} catch(e) {
Console.error('Correction.enter', e);
}
};
/**
* Leave correction mode
* @public
* @param {string} xid
* @return {undefined}
*/
self.leave = function(xid) {
try {
if(self.isIn(xid) === true) {
var base_sel = $('#' + hex_md5(xid));
var active_message_sel = base_sel.find('.content .one-line.user-message.correction-active');
self._unbindInterface(xid, active_message_sel);
var message_area_sel = base_sel.find('.message-area');
message_area_sel.val('');
message_area_sel.focus();
}
} catch(e) {
Console.error('Correction.leave', e);
}
};
/**
* Send corrected message
* @public
* @param {string} xid
* @param {string} type
* @param {string} replacement
* @return {undefined}
*/
self.send = function(xid, type, replacement) {
try {
if(self._hasSupport(xid) === true) {
if(self._getLastMessage(xid).value != replacement) {
var own_xid = Common.getXID();
var hash = hex_md5(xid);
var replace_id = self._getLastID(xid);
Console.info('Correction.send', 'Sending replacement message for: ' + xid + ' "' + replacement + '" with ID: ' + (replace_id || 'none'));
// Send the stanza itself
var full_xid = Presence.highestPriority(xid) || xid;
var stanza_args = self._sendStanza(
xid,
full_xid,
type,
replace_id,
replacement
);
// Update DOM (for chat only)
if(type == 'chat') {
// Filter the xHTML message (for us!)
var replacement_formatted = replacement;
if(stanza_args.xhtml) {
replacement_formatted = Filter.xhtml(stanza_args.message.getNode());
}
// Remove old message
old_message_sel = $('#' + hash + ' .content .one-line.user-message[data-mode="me"]').filter(function() {
return ($(this).attr('data-id') + '') === (replace_id + '');
}).filter(':last');
var edit_count = old_message_sel.attr('data-edit-count') || 0;
edit_count = isNaN(edit_count) ? 0 : parseInt(edit_count, 10);
if(type == 'chat') {
old_message_sel.remove();
}
// Display edited message
Message.display(
'chat',
own_xid,
hash,
Name.getBuddy(own_xid).htmlEnc(),
replacement_formatted,
DateUtils.getCompleteTime(),
DateUtils.getTimeStamp(),
'user-message',
!stanza_args.xhtml,
'',
'me',
stanza_args.id,
undefined,
undefined,
true,
(edit_count + 1)
);
}
}
}
} catch(e) {
Console.error('Correction.send', e);
}
};
/**
* Catches a replace message
* @public
* @param {object} message
* @param {string} hash
* @param {string} type
* @return {object}
*/
self.catch = function(message, hash, type) {
var edit_results = {
'has_replace': false,
'is_edited': false,
'count': 0,
'next_count': 0
};
try {
var replace_node = message.getChild('replace', NS_URN_CORRECT);
if(replace_node) {
edit_results.has_replace = true;
var message_edit_id = $(replace_node).attr('id');
if(typeof message_edit_id != 'undefined') {
var message_edit_sel = $('#' + hash + ' .one-line.user-message').filter(function() {
var this_sel = $(this);
var is_valid_mode = true;
if(type == 'chat') {
is_valid_mode = true ? this_sel.attr('data-mode') == 'him' : false;
}
return is_valid_mode && ((this_sel.attr('data-id') + '') === (message_edit_id + ''));
}).filter(':last');
if(message_edit_sel.size()) {
edit_results.count = message_edit_sel.attr('data-edit-count') || 0;
edit_results.count = isNaN(edit_results.count) ? 0 : parseInt(edit_results.count, 10);
edit_results.next_count = edit_results.count + 1;
edit_results.is_edited = true;
// Empty group?
var message_edit_group_sel = message_edit_sel.parents('.one-group');
if(message_edit_group_sel.find('.one-line').size() <= 1) {
message_edit_group_sel.remove();
} else {
message_edit_sel.remove();
}
}
}
}
} catch(e) {
Console.error('Correction.catch', e);
} finally {
return edit_results;
}
};
/**
* Returns whether we are in correction mode or not
* @public
* @param {string} xid
* @return {boolean}
*/
self.isIn = function(xid) {
var is_in = false;
try {
is_in = $('#' + hex_md5(xid) + ' .text').hasClass('correction-active');
} catch(e) {
Console.error('Correction.isIn', e);
} finally {
return is_in;
}
};
/**
* Return class scope
*/
return self;
})();

File diff suppressed because it is too large Load diff

View file

@ -39,8 +39,9 @@ var DataStore = (function () {
this.key = function(key) { this.key = function(key) {
if(legacy) { if(legacy) {
if(key >= this.length) if(key >= this.length) {
return null; return null;
}
var c = 0; var c = 0;
@ -56,8 +57,9 @@ var DataStore = (function () {
this.getItem = function(key) { this.getItem = function(key) {
if(legacy) { if(legacy) {
if(storage_emulated[key] !== undefined) if(storage_emulated[key] !== undefined) {
return storage_emulated[key]; return storage_emulated[key];
}
return null; return null;
} else { } else {
@ -67,8 +69,9 @@ var DataStore = (function () {
this.setItem = function(key, data) { this.setItem = function(key, data) {
if(legacy) { if(legacy) {
if(!(key in storage_emulated)) if(!(key in storage_emulated)) {
this.length++; this.length++;
}
storage_emulated[key] = (data + ''); storage_emulated[key] = (data + '');
} else { } else {
@ -162,7 +165,7 @@ var DataStore = (function () {
try { try {
return self.storageDB.getItem(dbID + '_' + type + '_' + id); return self.storageDB.getItem(dbID + '_' + type + '_' + id);
} }
catch(e) { catch(e) {
Console.error('Error while getting a temporary database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', e); Console.error('Error while getting a temporary database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', e);
} }
@ -192,7 +195,7 @@ var DataStore = (function () {
return true; return true;
} }
catch(e) { catch(e) {
Console.error('Error while writing a temporary database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', e); Console.error('Error while writing a temporary database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', e);
} }
@ -218,10 +221,10 @@ var DataStore = (function () {
try { try {
try { try {
self.storageDB.removeItem(dbID + '_' + type + '_' + id); self.storageDB.removeItem(dbID + '_' + type + '_' + id);
return true; return true;
} }
catch(e) { catch(e) {
Console.error('Error while removing a temporary database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', e); Console.error('Error while removing a temporary database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', e);
} }
@ -263,15 +266,15 @@ var DataStore = (function () {
try { try {
try { try {
self.storageDB.clear(); self.storageDB.clear();
Console.info('Temporary database cleared.'); Console.info('Temporary database cleared.');
return true; return true;
} }
catch(e) { catch(e) {
Console.error('Error while clearing temporary database', e); Console.error('Error while clearing temporary database', e);
return false; return false;
} }
} catch(e) { } catch(e) {
@ -294,7 +297,7 @@ var DataStore = (function () {
// Try to write something // Try to write something
self.storagePersistent.setItem('haspersistent_check', 'ok'); self.storagePersistent.setItem('haspersistent_check', 'ok');
self.storagePersistent.removeItem('haspersistent_check'); self.storagePersistent.removeItem('haspersistent_check');
has_persistent = true; has_persistent = true;
} catch(e) { } catch(e) {
Console.error('DataStore.hasPersistent', e); Console.error('DataStore.hasPersistent', e);
@ -319,10 +322,10 @@ var DataStore = (function () {
try { try {
return self.storagePersistent.getItem(dbID + '_' + type + '_' + id); return self.storagePersistent.getItem(dbID + '_' + type + '_' + id);
} }
catch(e) { catch(e) {
Console.error('Error while getting a persistent database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', e); Console.error('Error while getting a persistent database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', e);
return null; return null;
} }
} catch(e) { } catch(e) {
@ -346,24 +349,24 @@ var DataStore = (function () {
try { try {
try { try {
self.storagePersistent.setItem(dbID + '_' + type + '_' + id, value); self.storagePersistent.setItem(dbID + '_' + type + '_' + id, value);
return true; return true;
} }
// Database might be full // Database might be full
catch(e) { catch(e) {
Console.warn('Retrying: could not write a persistent database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', e); Console.warn('Retrying: could not write a persistent database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', e);
// Flush it! // Flush it!
self.flushPersistent(); self.flushPersistent();
// Set the item again // Set the item again
try { try {
self.storagePersistent.setItem(dbID + ' -> ' + type + '_' + id, value); self.storagePersistent.setItem(dbID + ' -> ' + type + '_' + id, value);
return true; return true;
} }
// New error! // New error!
catch(_e) { catch(_e) {
Console.error('Aborted: error while writing a persistent database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', _e); Console.error('Aborted: error while writing a persistent database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', _e);
@ -394,7 +397,7 @@ var DataStore = (function () {
return true; return true;
} }
catch(e) { catch(e) {
Console.error('Error while removing a persistent database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', e); Console.error('Error while removing a persistent database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', e);
} }
@ -439,10 +442,10 @@ var DataStore = (function () {
self.storagePersistent.clear(); self.storagePersistent.clear();
Console.info('Persistent database cleared.'); Console.info('Persistent database cleared.');
return true; return true;
} }
catch(e) { catch(e) {
Console.error('Error while clearing persistent database', e); Console.error('Error while clearing persistent database', e);
} }
@ -467,19 +470,20 @@ var DataStore = (function () {
try { try {
// Get the stored session entry // Get the stored session entry
var session = self.getPersistent('global', 'session', 1); var session = self.getPersistent('global', 'session', 1);
// Reset the persistent database // Reset the persistent database
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.');
return true; return true;
} }
catch(e) { catch(e) {
Console.error('Error while flushing persistent database', e); Console.error('Error while flushing persistent database', e);
} }

View file

@ -84,9 +84,10 @@ 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) {
Console.error('DateUtils.getLastActivity', e); Console.error('DateUtils.getLastActivity', 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,9 +126,10 @@ 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) {
Console.error('DateUtils.getPresenceLast', e); Console.error('DateUtils.getPresenceLast', 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,10 +217,11 @@ 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());
return time; return time;
} catch(e) { } catch(e) {
Console.error('DateUtils.getCompleteTime', e); Console.error('DateUtils.getCompleteTime', e);
@ -199,26 +241,26 @@ var DateUtils = (function () {
// Get the date // Get the date
var date = new Date(); var date = new Date();
var offset = date.getTimezoneOffset(); var offset = date.getTimezoneOffset();
// Default vars // Default vars
var sign = ''; var sign = '';
var hours = 0; var hours = 0;
var minutes = 0; var minutes = 0;
// Process a neutral offset // Process a neutral offset
if(offset < 0) { if(offset < 0) {
offset = offset * -1; offset = offset * -1;
sign = '+'; sign = '+';
} }
// Get the values // Get the values
var n_date = new Date(offset * 60 * 1000); var n_date = new Date(offset * 60 * 1000);
hours = n_date.getHours() - 1; hours = n_date.getHours() - 1;
minutes = n_date.getMinutes(); minutes = n_date.getMinutes();
// Process the TZO // Process the TZO
tzo = sign + Common.padZero(hours) + ':' + Common.padZero(minutes); tzo = sign + Common.padZero(hours) + ':' + Common.padZero(minutes);
// Return the processed value // Return the processed value
return tzo; return tzo;
} catch(e) { } catch(e) {
@ -259,7 +301,7 @@ var DateUtils = (function () {
try { try {
var date = Date.jab2date(to_parse); var date = Date.jab2date(to_parse);
var parsed = date.toLocaleDateString() + ' (' + date.toLocaleTimeString() + ')'; var parsed = date.toLocaleDateString() + ' (' + date.toLocaleTimeString() + ')';
return parsed; return parsed;
} catch(e) { } catch(e) {
Console.error('DateUtils.parse', e); Console.error('DateUtils.parse', e);
@ -279,7 +321,7 @@ var DateUtils = (function () {
try { try {
var date = Date.jab2date(to_parse); var date = Date.jab2date(to_parse);
var parsed = date.toLocaleDateString(); var parsed = date.toLocaleDateString();
return parsed; return parsed;
} catch(e) { } catch(e) {
Console.error('DateUtils.parseDay', e); Console.error('DateUtils.parseDay', e);
@ -299,7 +341,7 @@ var DateUtils = (function () {
try { try {
var date = Date.jab2date(to_parse); var date = Date.jab2date(to_parse);
var parsed = date.toLocaleTimeString(); var parsed = date.toLocaleTimeString();
return parsed; return parsed;
} catch(e) { } catch(e) {
Console.error('DateUtils.parseTime', e); Console.error('DateUtils.parseTime', e);
@ -321,32 +363,36 @@ var DateUtils = (function () {
var current_date = Date.jab2date(self.getXMPPTime('utc')); var current_date = Date.jab2date(self.getXMPPTime('utc'));
var current_day = current_date.getDate(); var current_day = current_date.getDate();
var current_stamp = current_date.getTime(); var current_stamp = current_date.getTime();
// Parse the given date // Parse the given date
var old_date = Date.jab2date(to_parse); var old_date = Date.jab2date(to_parse);
var old_day = old_date.getDate(); var old_day = old_date.getDate();
var old_stamp = old_date.getTime(); var old_stamp = old_date.getTime();
var old_time = old_date.toLocaleTimeString(); var old_time = old_date.toLocaleTimeString();
// Get the day number between the two dates // Get the day number between the two dates
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;
} catch(e) { } catch(e) {
@ -360,30 +406,36 @@ 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
var delay, d_delay; var delay, d_delay;
// Read the delay // Read the delay
d_delay = jQuery(node).find('delay[xmlns="' + NS_URN_DELAY + '"]:first').attr('stamp'); d_delay = jQuery(node).find('delay[xmlns="' + NS_URN_DELAY + '"]:first').attr('stamp');
// New delay (valid XEP) // Get delay
if(d_delay) if(d_delay) {
// New delay (valid XEP)
delay = d_delay; delay = d_delay;
} else {
// Old delay (obsolete XEP!) // Old delay (obsolete XEP!)
else {
// Try to read the old-school delay
var x_delay = jQuery(node).find('x[xmlns="' + NS_DELAY + '"]:first').attr('stamp'); var x_delay = jQuery(node).find('x[xmlns="' + NS_DELAY + '"]:first').attr('stamp');
if(x_delay) if(x_delay) {
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) {
Console.error('DateUtils.readMessageDelay', e); Console.error('DateUtils.readMessageDelay', e);

View file

@ -1,10 +1,10 @@
/** /**
* Version: 1.0 Alpha-1 * Version: 1.0 Alpha-1
* Build Date: 13-Nov-2007 * Build Date: 13-Nov-2007
* Copyright (c) 2006-2007, Coolite Inc. (http://www.coolite.com/). All rights reserved. * Copyright (c) 2006-2007, Coolite Inc. (http://www.coolite.com/). All rights reserved.
* License: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/. * License: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/.
* Website: http://www.datejs.com/ or http://www.coolite.com/datejs/ * Website: http://www.datejs.com/ or http://www.coolite.com/datejs/
*/ */
Date.CultureInfo={name:"en-US",englishName:"English (United States)",nativeName:"English (United States)",dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],abbreviatedDayNames:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],shortestDayNames:["Su","Mo","Tu","We","Th","Fr","Sa"],firstLetterDayNames:["S","M","T","W","T","F","S"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],abbreviatedMonthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],amDesignator:"AM",pmDesignator:"PM",firstDayOfWeek:0,twoDigitYearMax:2029,dateElementOrder:"mdy",formatPatterns:{shortDate:"M/d/yyyy",longDate:"dddd, MMMM dd, yyyy",shortTime:"h:mm tt",longTime:"h:mm:ss tt",fullDateTime:"dddd, MMMM dd, yyyy h:mm:ss tt",sortableDateTime:"yyyy-MM-ddTHH:mm:ss",universalSortableDateTime:"yyyy-MM-dd HH:mm:ssZ",rfc1123:"ddd, dd MMM yyyy HH:mm:ss GMT",monthDay:"MMMM dd",yearMonth:"MMMM, yyyy"},regexPatterns:{jan:/^jan(uary)?/i,feb:/^feb(ruary)?/i,mar:/^mar(ch)?/i,apr:/^apr(il)?/i,may:/^may/i,jun:/^jun(e)?/i,jul:/^jul(y)?/i,aug:/^aug(ust)?/i,sep:/^sep(t(ember)?)?/i,oct:/^oct(ober)?/i,nov:/^nov(ember)?/i,dec:/^dec(ember)?/i,sun:/^su(n(day)?)?/i,mon:/^mo(n(day)?)?/i,tue:/^tu(e(s(day)?)?)?/i,wed:/^we(d(nesday)?)?/i,thu:/^th(u(r(s(day)?)?)?)?/i,fri:/^fr(i(day)?)?/i,sat:/^sa(t(urday)?)?/i,future:/^next/i,past:/^last|past|prev(ious)?/i,add:/^(\+|after|from)/i,subtract:/^(\-|before|ago)/i,yesterday:/^yesterday/i,today:/^t(oday)?/i,tomorrow:/^tomorrow/i,now:/^n(ow)?/i,millisecond:/^ms|milli(second)?s?/i,second:/^sec(ond)?s?/i,minute:/^min(ute)?s?/i,hour:/^h(ou)?rs?/i,week:/^w(ee)?k/i,month:/^m(o(nth)?s?)?/i,day:/^d(ays?)?/i,year:/^y((ea)?rs?)?/i,shortMeridian:/^(a|p)/i,longMeridian:/^(a\.?m?\.?|p\.?m?\.?)/i,timezone:/^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\s*(\+|\-)\s*\d\d\d\d?)|gmt)/i,ordinalSuffix:/^\s*(st|nd|rd|th)/i,timeContext:/^\s*(\:|a|p)/i},abbreviatedTimeZoneStandard:{GMT:"-000",EST:"-0400",CST:"-0500",MST:"-0600",PST:"-0700"},abbreviatedTimeZoneDST:{GMT:"-000",EDT:"-0500",CDT:"-0600",MDT:"-0700",PDT:"-0800"}}; Date.CultureInfo={name:"en-US",englishName:"English (United States)",nativeName:"English (United States)",dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],abbreviatedDayNames:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],shortestDayNames:["Su","Mo","Tu","We","Th","Fr","Sa"],firstLetterDayNames:["S","M","T","W","T","F","S"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],abbreviatedMonthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],amDesignator:"AM",pmDesignator:"PM",firstDayOfWeek:0,twoDigitYearMax:2029,dateElementOrder:"mdy",formatPatterns:{shortDate:"M/d/yyyy",longDate:"dddd, MMMM dd, yyyy",shortTime:"h:mm tt",longTime:"h:mm:ss tt",fullDateTime:"dddd, MMMM dd, yyyy h:mm:ss tt",sortableDateTime:"yyyy-MM-ddTHH:mm:ss",universalSortableDateTime:"yyyy-MM-dd HH:mm:ssZ",rfc1123:"ddd, dd MMM yyyy HH:mm:ss GMT",monthDay:"MMMM dd",yearMonth:"MMMM, yyyy"},regexPatterns:{jan:/^jan(uary)?/i,feb:/^feb(ruary)?/i,mar:/^mar(ch)?/i,apr:/^apr(il)?/i,may:/^may/i,jun:/^jun(e)?/i,jul:/^jul(y)?/i,aug:/^aug(ust)?/i,sep:/^sep(t(ember)?)?/i,oct:/^oct(ober)?/i,nov:/^nov(ember)?/i,dec:/^dec(ember)?/i,sun:/^su(n(day)?)?/i,mon:/^mo(n(day)?)?/i,tue:/^tu(e(s(day)?)?)?/i,wed:/^we(d(nesday)?)?/i,thu:/^th(u(r(s(day)?)?)?)?/i,fri:/^fr(i(day)?)?/i,sat:/^sa(t(urday)?)?/i,future:/^next/i,past:/^last|past|prev(ious)?/i,add:/^(\+|after|from)/i,subtract:/^(\-|before|ago)/i,yesterday:/^yesterday/i,today:/^t(oday)?/i,tomorrow:/^tomorrow/i,now:/^n(ow)?/i,millisecond:/^ms|milli(second)?s?/i,second:/^sec(ond)?s?/i,minute:/^min(ute)?s?/i,hour:/^h(ou)?rs?/i,week:/^w(ee)?k/i,month:/^m(o(nth)?s?)?/i,day:/^d(ays?)?/i,year:/^y((ea)?rs?)?/i,shortMeridian:/^(a|p)/i,longMeridian:/^(a\.?m?\.?|p\.?m?\.?)/i,timezone:/^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\s*(\+|\-)\s*\d\d\d\d?)|gmt)/i,ordinalSuffix:/^\s*(st|nd|rd|th)/i,timeContext:/^\s*(\:|a|p)/i},abbreviatedTimeZoneStandard:{GMT:"-000",EST:"-0400",CST:"-0500",MST:"-0600",PST:"-0700"},abbreviatedTimeZoneDST:{GMT:"-000",EDT:"-0500",CDT:"-0600",MDT:"-0700",PDT:"-0800"}};
Date.getMonthNumberFromName=function(name){var n=Date.CultureInfo.monthNames,m=Date.CultureInfo.abbreviatedMonthNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}} Date.getMonthNumberFromName=function(name){var n=Date.CultureInfo.monthNames,m=Date.CultureInfo.abbreviatedMonthNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
return-1;};Date.getDayNumberFromName=function(name){var n=Date.CultureInfo.dayNames,m=Date.CultureInfo.abbreviatedDayNames,o=Date.CultureInfo.shortestDayNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}} return-1;};Date.getDayNumberFromName=function(name){var n=Date.CultureInfo.dayNames,m=Date.CultureInfo.abbreviatedDayNames,o=Date.CultureInfo.shortestDayNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
@ -101,4 +101,4 @@ return _.any.apply(null,rx);}else{return _get(fx);}};g._formats=g.formats(["yyyy
return g._start.call({},s);};}());Date._parse=Date.parse;Date.parse=function(s){var r=null;if(!s){return null;} return g._start.call({},s);};}());Date._parse=Date.parse;Date.parse=function(s){var r=null;if(!s){return null;}
try{r=Date.Grammar.start.call({},s);}catch(e){return null;} try{r=Date.Grammar.start.call({},s);}catch(e){return null;}
return((r[1].length===0)?r[0]:null);};Date.getParseFunction=function(fx){var fn=Date.Grammar.formats(fx);return function(s){var r=null;try{r=fn.call({},s);}catch(e){return null;} return((r[1].length===0)?r[0]:null);};Date.getParseFunction=function(fx){var fn=Date.Grammar.formats(fx);return function(s){var r=null;try{r=fn.call({},s);}catch(e){return null;}
return((r[1].length===0)?r[0]:null);};};Date.parseExact=function(s,fx){return Date.getParseFunction(fx)(s);}; return((r[1].length===0)?r[0]:null);};};Date.parseExact=function(s,fx){return Date.getParseFunction(fx)(s);};

View file

@ -29,31 +29,31 @@ var Directory = (function () {
try { try {
// Popup HTML content // Popup HTML content
var html = var html =
'<div class="top">' + Common._e("User directory") + '</div>' + '<div class="top">' + Common._e("User directory") + '</div>' +
'<div class="content">' + '<div class="content">' +
'<div class="directory-head">' + '<div class="directory-head">' +
'<div class="directory-server-text">' + Common._e("Server to query") + '</div>' + '<div class="directory-server-text">' + Common._e("Server to query") + '</div>' +
'<input name="directory-server-input" class="directory-server-input" value="' + Common.encodeQuotes(HOST_VJUD) + '" />' + '<input name="directory-server-input" class="directory-server-input" value="' + Common.encodeQuotes(HOST_VJUD) + '" />' +
'</div>' + '</div>' +
'<div class="results directory-results"></div>' + '<div class="results directory-results"></div>' +
'</div>' + '</div>' +
'<div class="bottom">' + '<div class="bottom">' +
'<div class="wait wait-medium"></div>' + '<div class="wait wait-medium"></div>' +
'<a href="#" class="finish">' + Common._e("Close") + '</a>' + '<a href="#" class="finish">' + Common._e("Close") + '</a>' +
'</div>'; '</div>';
// Create the popup // Create the popup
Popup.create('directory', html); Popup.create('directory', html);
// Associate the events // Associate the events
self.instance(); self.instance();
// Start a search! // Start a search!
self.start(); self.start();
} catch(e) { } catch(e) {
@ -94,10 +94,10 @@ var Directory = (function () {
try { try {
// Get the server to query // Get the server to query
var server = $('#directory .directory-server-input').val(); var server = $('#directory .directory-server-input').val();
// Launch the search! // Launch the search!
DataForm.go($('#directory .directory-server-input').val(), 'search', '', '', 'directory'); DataForm.go($('#directory .directory-server-input').val(), 'search', '', '', 'directory');
Console.log('Directory search launched: ' + server); Console.log('Directory search launched: ' + server);
} catch(e) { } catch(e) {
Console.error('Directory.start', e); Console.error('Directory.start', e);
@ -118,17 +118,18 @@ var Directory = (function () {
try { try {
// Click event // Click event
$('#directory .bottom .finish').click(self.close); $('#directory .bottom .finish').click(self.close);
// Keyboard event // Keyboard event
$('#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();
return false; return false;
} }
}); });

View file

@ -29,99 +29,99 @@ var Discovery = (function () {
try { try {
// Popup HTML content // Popup HTML content
var html = var html =
'<div class="top">' + Common._e("Service discovery") + '</div>' + '<div class="top">' + Common._e("Service discovery") + '</div>' +
'<div class="content">' + '<div class="content">' +
'<div class="discovery-head">' + '<div class="discovery-head">' +
'<div class="disco-server-text">' + Common._e("Server to query") + '</div>' + '<div class="disco-server-text">' + Common._e("Server to query") + '</div>' +
'<input name="disco-server-input" class="disco-server-input" value="' + Common.encodeQuotes(HOST_MAIN) + '" />' + '<input name="disco-server-input" class="disco-server-input" value="' + Common.encodeQuotes(HOST_MAIN) + '" />' +
'</div>' + '</div>' +
'<div class="results discovery-results">' + '<div class="results discovery-results">' +
'<div class="disco-category disco-account">' + '<div class="disco-category disco-account">' +
'<p class="disco-category-title">' + Common._e("Accounts") + '</p>' + '<p class="disco-category-title">' + Common._e("Accounts") + '</p>' +
'</div>' + '</div>' +
'<div class="disco-category disco-auth">' + '<div class="disco-category disco-auth">' +
'<p class="disco-category-title">' + Common._e("Authentications") + '</p>' + '<p class="disco-category-title">' + Common._e("Authentications") + '</p>' +
'</div>' + '</div>' +
'<div class="disco-category disco-automation">' + '<div class="disco-category disco-automation">' +
'<p class="disco-category-title">' + Common._e("Automation") + '</p>' + '<p class="disco-category-title">' + Common._e("Automation") + '</p>' +
'</div>' + '</div>' +
'<div class="disco-category disco-client">' + '<div class="disco-category disco-client">' +
'<p class="disco-category-title">' + Common._e("Clients") + '</p>' + '<p class="disco-category-title">' + Common._e("Clients") + '</p>' +
'</div>' + '</div>' +
'<div class="disco-category disco-collaboration">' + '<div class="disco-category disco-collaboration">' +
'<p class="disco-category-title">' + Common._e("Collaboration") + '</p>' + '<p class="disco-category-title">' + Common._e("Collaboration") + '</p>' +
'</div>' + '</div>' +
'<div class="disco-category disco-component">' + '<div class="disco-category disco-component">' +
'<p class="disco-category-title">' + Common._e("Components") + '</p>' + '<p class="disco-category-title">' + Common._e("Components") + '</p>' +
'</div>' + '</div>' +
'<div class="disco-category disco-conference">' + '<div class="disco-category disco-conference">' +
'<p class="disco-category-title">' + Common._e("Rooms") + '</p>' + '<p class="disco-category-title">' + Common._e("Rooms") + '</p>' +
'</div>' + '</div>' +
'<div class="disco-category disco-directory">' + '<div class="disco-category disco-directory">' +
'<p class="disco-category-title">' + Common._e("Directories") + '</p>' + '<p class="disco-category-title">' + Common._e("Directories") + '</p>' +
'</div>' + '</div>' +
'<div class="disco-category disco-gateway">' + '<div class="disco-category disco-gateway">' +
'<p class="disco-category-title">' + Common._e("Gateways") + '</p>' + '<p class="disco-category-title">' + Common._e("Gateways") + '</p>' +
'</div>' + '</div>' +
'<div class="disco-category disco-headline">' + '<div class="disco-category disco-headline">' +
'<p class="disco-category-title">' + Common._e("News") + '</p>' + '<p class="disco-category-title">' + Common._e("News") + '</p>' +
'</div>' + '</div>' +
'<div class="disco-category disco-hierarchy">' + '<div class="disco-category disco-hierarchy">' +
'<p class="disco-category-title">' + Common._e("Hierarchy") + '</p>' + '<p class="disco-category-title">' + Common._e("Hierarchy") + '</p>' +
'</div>' + '</div>' +
'<div class="disco-category disco-proxy">' + '<div class="disco-category disco-proxy">' +
'<p class="disco-category-title">' + Common._e("Proxies") + '</p>' + '<p class="disco-category-title">' + Common._e("Proxies") + '</p>' +
'</div>' + '</div>' +
'<div class="disco-category disco-pubsub">' + '<div class="disco-category disco-pubsub">' +
'<p class="disco-category-title">' + Common._e("Publication/Subscription") + '</p>' + '<p class="disco-category-title">' + Common._e("Publication/Subscription") + '</p>' +
'</div>' + '</div>' +
'<div class="disco-category disco-server">' + '<div class="disco-category disco-server">' +
'<p class="disco-category-title">' + Common._e("Server") + '</p>' + '<p class="disco-category-title">' + Common._e("Server") + '</p>' +
'</div>' + '</div>' +
'<div class="disco-category disco-store">' + '<div class="disco-category disco-store">' +
'<p class="disco-category-title">' + Common._e("Storage") + '</p>' + '<p class="disco-category-title">' + Common._e("Storage") + '</p>' +
'</div>' + '</div>' +
'<div class="disco-category disco-others">' + '<div class="disco-category disco-others">' +
'<p class="disco-category-title">' + Common._e("Others") + '</p>' + '<p class="disco-category-title">' + Common._e("Others") + '</p>' +
'</div>' + '</div>' +
'<div class="disco-category disco-wait">' + '<div class="disco-category disco-wait">' +
'<p class="disco-category-title">' + Common._e("Loading") + '</p>' + '<p class="disco-category-title">' + Common._e("Loading") + '</p>' +
'</div>' + '</div>' +
'</div>' + '</div>' +
'</div>' + '</div>' +
'<div class="bottom">' + '<div class="bottom">' +
'<div class="wait wait-medium"></div>' + '<div class="wait wait-medium"></div>' +
'<a href="#" class="finish">' + Common._e("Close") + '</a>' + '<a href="#" class="finish">' + Common._e("Close") + '</a>' +
'</div>'; '</div>';
// Create the popup // Create the popup
Popup.create('discovery', html); Popup.create('discovery', html);
// Associate the events // Associate the events
self.instance(); self.instance();
// We request a disco to the default server // We request a disco to the default server
self.start(); self.start();
} catch(e) { } catch(e) {
@ -164,10 +164,10 @@ var Discovery = (function () {
try { try {
// We get the server to query // We get the server to query
var discoServer = $('#discovery .disco-server-input').val(); var discoServer = $('#discovery .disco-server-input').val();
// We launch the items query // We launch the items query
DataForm.go(discoServer, 'browse', '', '', 'discovery'); DataForm.go(discoServer, 'browse', '', '', 'discovery');
Console.log('Service discovery launched: ' + discoServer); Console.log('Service discovery launched: ' + discoServer);
} catch(e) { } catch(e) {
Console.error('Discovery.start', e); Console.error('Discovery.start', e);
@ -188,10 +188,10 @@ var Discovery = (function () {
try { try {
// We remove the results // We remove the results
$('#discovery .discovery-oneresult, #discovery .oneinstructions, #discovery .onetitle, #discovery .no-results').remove(); $('#discovery .discovery-oneresult, #discovery .oneinstructions, #discovery .onetitle, #discovery .no-results').remove();
// We clean the user info // We clean the user info
$('#discovery .disco-server-info').text(''); $('#discovery .disco-server-info').text('');
// We hide the wait icon, the no result alert and the results // We hide the wait icon, the no result alert and the results
$('#discovery .wait, #discovery .disco-category').hide(); $('#discovery .wait, #discovery .disco-category').hide();
} catch(e) { } catch(e) {
@ -211,17 +211,18 @@ var Discovery = (function () {
try { try {
// Click event // Click event
$('#discovery .bottom .finish').click(self.close); $('#discovery .bottom .finish').click(self.close);
// Keyboard event // Keyboard event
$('#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();
return false; return false;
} }
}); });

View file

@ -35,30 +35,33 @@ var Errors = (function () {
if(condition || reason) { if(condition || reason) {
// Initialize the error text // Initialize the error text
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;
} }
// We reveal the error // We reveal the error
Board.openThisError(1); Board.openThisError(1);
// Create the error text // Create the error text
$('#board .one-board.error[data-id="1"] span').text(eText); $('#board .one-board.error[data-id="1"] span').text(eText);
} }
// Not enough data to output the error: output a generic board // Not enough data to output the error: output a generic board
else { else {
Board.openThisError(2); Board.openThisError(2);
@ -84,75 +87,76 @@ var Errors = (function () {
// Initialize // Initialize
var type, code, reason, condition; var type, code, reason, condition;
var node = $(packet); var node = $(packet);
// First level error (connection error) // First level error (connection error)
if(node.is('error')) { if(node.is('error')) {
// Get the value // Get the value
code = node.attr('code'); code = node.attr('code');
// Specific error reason // Specific error reason
switch(code) { switch(code) {
case '401': case '401':
reason = Common._e("Authorization failed"); reason = Common._e("Authorization failed");
break; break;
case '409': case '409':
reason = Common._e("Registration failed, please choose a different username"); reason = Common._e("Registration failed, please choose a different username");
break; break;
case '503': case '503':
reason = Common._e("Service unavailable"); reason = Common._e("Service unavailable");
break; break;
case '500': case '500':
reason = Common._e("Internal server error, try later"); reason = Common._e("Internal server error, try later");
break; break;
default: default:
reason = node.find('text').text(); reason = node.find('text').text();
break; break;
} }
// Remove the general wait item (security) // Remove the general wait item (security)
Interface.removeGeneralWait(); Interface.removeGeneralWait();
// 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) {
$('#home').show(); $('#home').show();
Interface.title('home'); Interface.title('home');
} }
// Still connected? (security) // Still connected? (security)
if(Common.isConnected()) { if(Common.isConnected()) {
con.disconnect(); con.disconnect();
} }
Console.error('First level error received.'); Console.error('First level error received.');
} }
// Second level error (another error) // Second level error (another error)
else if(node.find('error').size()) { else if(node.find('error').size()) {
type = node.find('error').attr('type'); type = node.find('error').attr('type');
reason = node.find('error text').text(); reason = node.find('error text').text();
condition = packet.getElementsByTagName('error').item(0).childNodes.item(0).nodeName.replace(/-/g, ' '); condition = packet.getElementsByTagName('error').item(0).childNodes.item(0).nodeName.replace(/-/g, ' ');
Console.error('Second level error received.'); Console.error('Second level error received.');
} else { } else {
return false; return false;
} }
// Show the error board // Show the error board
self.show(condition, reason, type); self.show(condition, reason, type);
// Return there's an error // Return there's an error
return true; return true;
} catch(e) { } catch(e) {

View file

@ -29,103 +29,103 @@ var Favorites = (function () {
try { try {
// Popup HTML content // Popup HTML content
var html = var html =
'<div class="top">' + Common._e("Manage favorite rooms") + '</div>' + '<div class="top">' + Common._e("Manage favorite rooms") + '</div>' +
'<div class="content">' + '<div class="content">' +
'<div class="switch-fav">' + '<div class="switch-fav">' +
'<div class="room-switcher room-list">' + '<div class="room-switcher room-list">' +
'<div class="icon list-icon talk-images"></div>' + '<div class="icon list-icon talk-images"></div>' +
Common._e("Change favorites") + Common._e("Change favorites") +
'</div>' + '</div>' +
'<div class="room-switcher room-search">' + '<div class="room-switcher room-search">' +
'<div class="icon search-icon talk-images"></div>' + '<div class="icon search-icon talk-images"></div>' +
Common._e("Search a room") + Common._e("Search a room") +
'</div>' + '</div>' +
'</div>' + '</div>' +
'<div class="static-fav">' + '<div class="static-fav">' +
'<div class="favorites-edit favorites-content">' + '<div class="favorites-edit favorites-content">' +
'<div class="head fedit-head static-fav-head">' + '<div class="head fedit-head static-fav-head">' +
'<div class="head-text fedit-head-text">' + Common._e("Select a favorite") + '</div>' + '<div class="head-text fedit-head-text">' + Common._e("Select a favorite") + '</div>' +
'<select name="fedit-head-select" class="head-select fedit-head-select"></select>' + '<select name="fedit-head-select" class="head-select fedit-head-select"></select>' +
'</div>' + '</div>' +
'<div class="results fedit-results static-fav-results">' + '<div class="results fedit-results static-fav-results">' +
'<div class="fedit-line">' + '<div class="fedit-line">' +
'<label>' + Common._e("Name") + '</label>' + '<label>' + Common._e("Name") + '</label>' +
'<input class="fedit-title" type="text" required="" />' + '<input class="fedit-title" type="text" required="" />' +
'</div>' + '</div>' +
'<div class="fedit-line">' + '<div class="fedit-line">' +
'<label>' + Common._e("Nickname") + '</label>' + '<label>' + Common._e("Nickname") + '</label>' +
'<input class="fedit-nick" type="text" value="' + Name.getNick() + '" required="" />' + '<input class="fedit-nick" type="text" value="' + Name.getNick() + '" required="" />' +
'</div>' + '</div>' +
'<div class="fedit-line">' + '<div class="fedit-line">' +
'<label>' + Common._e("Room") + '</label>' + '<label>' + Common._e("Room") + '</label>' +
'<input class="fedit-chan" type="text" required="" />' + '<input class="fedit-chan" type="text" required="" />' +
'</div>' + '</div>' +
'<div class="fedit-line">' + '<div class="fedit-line">' +
'<label>' + Common._e("Server") + '</label>' + '<label>' + Common._e("Server") + '</label>' +
'<input class="fedit-server" type="text" value="' + HOST_MUC + '" required="" />' + '<input class="fedit-server" type="text" value="' + HOST_MUC + '" required="" />' +
'</div>' + '</div>' +
'<div class="fedit-line">' + '<div class="fedit-line">' +
'<label>' + Common._e("Password") + '</label>' + '<label>' + Common._e("Password") + '</label>' +
'<input class="fedit-password" type="password" />' + '<input class="fedit-password" type="password" />' +
'</div>' + '</div>' +
'<div class="fedit-line">' + '<div class="fedit-line">' +
'<label>' + Common._e("Automatic") + '</label>' + '<label>' + Common._e("Automatic") + '</label>' +
'<input type="checkbox" class="fedit-autojoin" />' + '<input type="checkbox" class="fedit-autojoin" />' +
'</div>' + '</div>' +
'<div class="fedit-actions">' + '<div class="fedit-actions">' +
'<a href="#" class="fedit-terminate fedit-add add one-button talk-images">' + Common._e("Add") + '</a>' + '<a href="#" class="fedit-terminate fedit-add add one-button talk-images">' + Common._e("Add") + '</a>' +
'<a href="#" class="fedit-terminate fedit-edit one-button talk-images">' + Common._e("Edit") + '</a>' + '<a href="#" class="fedit-terminate fedit-edit one-button talk-images">' + Common._e("Edit") + '</a>' +
'<a href="#" class="fedit-terminate fedit-remove remove one-button talk-images">' + Common._e("Remove") + '</a>' + '<a href="#" class="fedit-terminate fedit-remove remove one-button talk-images">' + Common._e("Remove") + '</a>' +
'</div>' + '</div>' +
'</div>' + '</div>' +
'</div>' + '</div>' +
'<div class="favorites-search favorites-content">' + '<div class="favorites-search favorites-content">' +
'<div class="head fsearch-head static-fav-head">' + '<div class="head fsearch-head static-fav-head">' +
'<div class="head-text fsearch-head-text">' + Common._e("Search a room on") + '</div>' + '<div class="head-text fsearch-head-text">' + Common._e("Search a room on") + '</div>' +
'<input type="text" class="head-input fsearch-head-server" value="' + HOST_MUC + '" />' + '<input type="text" class="head-input fsearch-head-server" value="' + HOST_MUC + '" />' +
'</div>' + '</div>' +
'<div class="results fsearch-results static-fav-results">' + '<div class="results fsearch-results static-fav-results">' +
'<p class="fsearch-noresults">' + Common._e("No room found on this server.") + '</p>' + '<p class="fsearch-noresults">' + Common._e("No room found on this server.") + '</p>' +
'</div>' + '</div>' +
'</div>' + '</div>' +
'</div>' + '</div>' +
'</div>' + '</div>' +
'<div class="bottom">' + '<div class="bottom">' +
'<div class="wait wait-medium"></div>' + '<div class="wait wait-medium"></div>' +
'<a href="#" class="finish">' + Common._e("Close") + '</a>' + '<a href="#" class="finish">' + Common._e("Close") + '</a>' +
'</div>'; '</div>';
// Create the popup // Create the popup
Popup.create('favorites', html); Popup.create('favorites', html);
// Load the favorites // Load the favorites
self.load(); self.load();
// Associate the events // Associate the events
self.instance(); self.instance();
} catch(e) { } catch(e) {
@ -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,30 +187,35 @@ 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();
} catch(e) { } catch(e) {
@ -220,30 +230,30 @@ 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();
} catch(e) { } catch(e) {
@ -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,61 +320,59 @@ 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
self.reset(); self.reset();
} }
// Publish the new favorites // Publish the new favorites
self.publish(); self.publish();
Console.info('Action on this bookmark: ' + room + '@' + server + ' / ' + type); Console.info('Action on this bookmark: ' + room + '@' + server + ' / ' + type);
} catch(e) { } catch(e) {
Console.error('Favorites.terminateThis', e); Console.error('Favorites.terminateThis', e);
@ -385,7 +396,7 @@ var Favorites = (function () {
// We remove the target favorite everywhere needed // We remove the target favorite everywhere needed
$('.buddy-conf-groupchat-select option[value="' + xid + '"]').remove(); $('.buddy-conf-groupchat-select option[value="' + xid + '"]').remove();
$('.fedit-head-select option[value="' + xid + '"]').remove(); $('.fedit-head-select option[value="' + xid + '"]').remove();
// Must remove it from database? // Must remove it from database?
if(database) { if(database) {
DataStore.removeDB(Connection.desktop_hash, 'favorites', xid); DataStore.removeDB(Connection.desktop_hash, 'favorites', xid);
@ -407,37 +418,55 @@ var Favorites = (function () {
try { try {
var iq = new JSJaCIQ(); var iq = new JSJaCIQ();
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_(.+)');
for(var i = 0; i < DataStore.storageDB.length; i++) { for(var i = 0; i < DataStore.storageDB.length; i++) {
// Get the pointer values // Get the pointer values
var current = DataStore.storageDB.key(i); var current = DataStore.storageDB.key(i);
// 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,
if(password) 'jid': xid,
item.appendChild(iq.buildNode('password', {xmlns: NS_BOOKMARKS}, password)); 'autojoin': autojoin,
xmlns: NS_BOOKMARKS
})
);
item.appendChild(iq.buildNode('nick', {
xmlns: NS_BOOKMARKS
}, nick));
if(password) {
item.appendChild(iq.buildNode('password', {
xmlns: NS_BOOKMARKS
}, password));
}
Console.info('Bookmark sent: ' + xid); Console.info('Bookmark sent: ' + xid);
} }
} }
con.send(iq); con.send(iq);
} catch(e) { } catch(e) {
Console.error('Favorites.publish', e); Console.error('Favorites.publish', e);
@ -454,20 +483,20 @@ 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);
con.send(iq, self.handleGCList); con.send(iq, self.handleGCList);
} catch(e) { } catch(e) {
Console.error('Favorites.getGCList', e); Console.error('Favorites.getGCList', e);
@ -485,60 +514,72 @@ 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);
} }
else { else {
var handleXML = iq.getQuery(); var handleXML = iq.getQuery();
if($(handleXML).find('item').size()) { if($(handleXML).find('item').size()) {
// Initialize the HTML code // Initialize the HTML code
var html = ''; var html = '';
$(handleXML).find('item').each(function() { $(handleXML).find('item').each(function() {
var roomXID = $(this).attr('jid'); var this_sel = $(this);
var roomName = $(this).attr('name');
var room_xid = this_sel.attr('jid');
if(roomXID && roomName) { 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>';
} }
}); });
// 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 {
@ -581,15 +629,22 @@ var Favorites = (function () {
try { try {
// Generate the HTML code // Generate the HTML code
var html = '<option value="' + Common.encodeQuotes(xid) + '">' + name.htmlEnc() + '</option>'; var html = '<option value="' + Common.encodeQuotes(xid) + '">' + name.htmlEnc() + '</option>';
// Remove the existing favorite // Remove the existing favorite
self.remove(xid, false); self.remove(xid, false);
// We complete the select forms // We complete the select forms
$('#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);
@ -608,27 +663,34 @@ var Favorites = (function () {
try { try {
// Initialize the HTML code // Initialize the HTML code
var html = ''; var html = '';
// Read the database // Read the database
var db_regex = new RegExp(('^' + Connection.desktop_hash + '_') + 'favorites_(.+)'); var db_regex = new RegExp(('^' + Connection.desktop_hash + '_') + 'favorites_(.+)');
for(var i = 0; i < DataStore.storageDB.length; i++) { for(var i = 0; i < DataStore.storageDB.length; i++) {
// Get the pointer values // Get the pointer values
var current = DataStore.storageDB.key(i); var current = DataStore.storageDB.key(i);
// 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 = 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);
$('#favorites .fedit-head-select').html(favorites_popup); $('#favorites .fedit-head-select').html(favorites_popup);
@ -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

@ -50,29 +50,29 @@ var Features = (function () {
var to = Utils.getServer(); var to = Utils.getServer();
var caps = con.server_caps; var caps = con.server_caps;
var xml = null; var xml = null;
// Try to get the stored data // Try to get the stored data
if(caps) { if(caps) {
xml = Common.XMLFromString( xml = Common.XMLFromString(
DataStore.getPersistent('global', 'caps', caps) DataStore.getPersistent('global', 'caps', caps)
); );
} }
// Any stored data? // Any stored data?
if(xml) { if(xml) {
self.handle(xml); self.handle(xml);
Console.log('Read server CAPS from cache.'); Console.log('Read server CAPS from cache.');
} else { } else {
// Not stored (or no CAPS)! // Not stored (or no CAPS)!
var iq = new JSJaCIQ(); var iq = new JSJaCIQ();
iq.setTo(to); iq.setTo(to);
iq.setType('get'); iq.setType('get');
iq.setQuery(NS_DISCO_INFO); iq.setQuery(NS_DISCO_INFO);
con.send(iq, Caps.handleDiscoInfos); con.send(iq, Caps.handleDiscoInfos);
Console.log('Read server CAPS from network.'); Console.log('Read server CAPS from network.');
} }
} catch(e) { } catch(e) {
@ -93,7 +93,7 @@ var Features = (function () {
try { try {
// Selector // Selector
var selector = $(xml); var selector = $(xml);
// Functions // Functions
var check_feature_fn = function(namespace) { var check_feature_fn = function(namespace) {
// This weird selector fixes an IE8 bug... // This weird selector fixes an IE8 bug...
@ -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');
@ -137,21 +137,21 @@ var Features = (function () {
// Get the PEP nodes to initiate // Get the PEP nodes to initiate
Microblog.getInit(); Microblog.getInit();
PEP.getInitGeoloc(); PEP.getInitGeoloc();
// Get the notifications // Get the notifications
Notification.get(); Notification.get();
// Geolocate the user // Geolocate the user
PEP.geolocate(); PEP.geolocate();
// Enable microblogging send tools // Enable microblogging send tools
Microblog.wait('sync'); Microblog.wait('sync');
$('.postit.attach').css('display', 'block'); $('.postit.attach').css('display', 'block');
Console.info('XMPP server supports PEP.'); Console.info('XMPP server supports PEP.');
} else { } else {
Microblog.wait('unsync'); Microblog.wait('unsync');
Console.warn('XMPP server does not support PEP.'); Console.warn('XMPP server does not support PEP.');
} }
@ -159,10 +159,10 @@ var Features = (function () {
if(features.pep === false && features[NS_URN_MAM] === false) { if(features.pep === false && features[NS_URN_MAM] === false) {
$('#options fieldset.privacy').hide(); $('#options fieldset.privacy').hide();
} }
// Apply the features // Apply the features
self.apply('talk'); self.apply('talk');
// Process the roster height // Process the roster height
if(features.pep === true) { if(features.pep === true) {
Roster.adapt(); Roster.adapt();
@ -192,12 +192,12 @@ var Features = (function () {
try { try {
// Path to the elements // Path to the elements
var path = '#' + id + ' .'; var path = '#' + id + ' .';
// PEP features // PEP features
if(self.enabledPEP()) { if(self.enabledPEP()) {
$(path + 'pep-hidable').show(); $(path + 'pep-hidable').show();
} }
// PubSub features // PubSub features
if(self.enabledPubSub()) { if(self.enabledPubSub()) {
$(path + 'pubsub-hidable').show(); $(path + 'pubsub-hidable').show();
@ -207,7 +207,7 @@ var Features = (function () {
if(self.enabledPubSubCN()) { if(self.enabledPubSubCN()) {
$(path + 'pubsub-hidable-cn').show(); $(path + 'pubsub-hidable-cn').show();
} }
// MAM features // MAM features
if(self.enabledMAM()) { if(self.enabledMAM()) {
$(path + 'mam-hidable').show(); $(path + 'mam-hidable').show();
@ -218,12 +218,17 @@ var Features = (function () {
if(self.enabledMAMPurge()) { if(self.enabledMAMPurge()) {
$(path + 'mam-purge-hidable').show(); $(path + 'mam-purge-hidable').show();
} }
// Message correction features
if(self.enabledCorrection()) {
$(path + 'correction-hidable').show();
}
// Commands features // Commands features
if(self.enabledCommands()) { if(self.enabledCommands()) {
$(path + 'commands-hidable').show(); $(path + 'commands-hidable').show();
} }
// XMPP links (browser feature) // XMPP links (browser feature)
if(navigator.registerProtocolHandler) { if(navigator.registerProtocolHandler) {
$(path + 'xmpplinks-hidable').show(); $(path + 'xmpplinks-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,6 +20,300 @@ var Filter = (function () {
var self = {}; var self = {};
/* Constants */
self.message_regex = {
'commands': {
'me': /((^)|((.+)(>)))(\/me )([^<]+)/
},
'emotes': {
'angry': [
/(:-?@)($|\s|<)/gi,
'$2'
],
'bat': [
/(:-?\[)($|\s|<)/gi,
'$2'
],
'beer': [
/(\(B\))($|\s|<)/g,
'$2'
],
'biggrin': [
/((:-?D)|(XD))($|\s|<)/gi,
'$4'
],
'blush': [
/(:-?\$)($|\s|<)/gi,
'$2'
],
'boy': [
/(\(Z\))($|\s|<)/g,
'$2'
],
'brflower': [
/(\(W\))($|\s|<)/g,
'$2'
],
'brheart': [
/((&lt;\/3)|(\(U\)))($|\s|<)/g,
'$4'
],
'coffee': [
/(\(C\))($|\s|<)/g,
'$2'
],
'coolglasses': [
/((8-\))|(\(H\)))($|\s|<)/g,
'$4'
],
'cry': [
/(:'-?\()($|\s|<)/gi,
'$2'
],
'cuffs': [
/(\(%\))($|\s|<)/g,
'$2'
],
'devil': [
/(\]:-?&gt;)($|\s|<)/gi,
'$2'
],
'drink': [
/(\(D\))($|\s|<)/g,
'$2'
],
'flower': [
/(@}-&gt;--)($|\s|<)/gi,
'$2'
],
'frowning': [
/((:-?\/)|(:-?S))($|\s|<)/gi,
'$4'
],
'girl': [
/(\(X\))($|\s|<)/g,
'$2'
],
'heart': [
/((&lt;3)|(\(L\)))($|\s|<)/g,
'$4'
],
'hugleft': [
/(\(}\))($|\s|<)/g,
'$2'
],
'hugright': [
/(\({\))($|\s|<)/g,
'$2'
],
'kis': [
/(:-?{})($|\s|<)/gi,
'$2'
],
'lamp': [
/(\(I\))($|\s|<)/g,
'$2'
],
'lion': [
/(:-?3)($|\s|<)/gi,
'$2'
],
'mail': [
/(\(E\))($|\s|<)/g,
'$2'
],
'moon': [
/(\(S\))($|\s|<)/g,
'$2'
],
'music': [
/(\(8\))($|\s|<)/g,
'$2'
],
'oh': [
/((=-?O)|(:-?O))($|\s|<)/gi,
'$4'
],
'phone': [
/(\(T\))($|\s|<)/g,
'$2'
],
'photo': [
/(\(P\))($|\s|<)/g,
'$2'
],
'puke': [
/(:-?!)($|\s|<)/gi,
'$2'
],
'pussy': [
/(\(@\))($|\s|<)/g,
'$2'
],
'rainbow': [
/(\(R\))($|\s|<)/g,
'$2'
],
'smile': [
/(:-?\))($|\s|<)/gi,
'$2'
],
'star': [
/(\(\*\))($|\s|<)/g,
'$2'
],
'stare': [
/(:-?\|)($|\s|<)/gi,
'$2'
],
'thumbdown': [
/(\(N\))($|\s|<)/g,
'$2'
],
'thumbup': [
/(\(Y\))($|\s|<)/g,
'$2'
],
'tongue': [
/(:-?P)($|\s|<)/gi,
'$2'
],
'unhappy': [
/(:-?\()($|\s|<)/gi,
'$2'
],
'wink': [
/(;-?\))($|\s|<)/gi,
'$2'
]
},
'formatting': {
'bold': [
/(^|\s|>|\()((\*)([^<>'"\*]+)(\*))($|\s|<|\))/gi,
'$1<b>$2</b>$6'
],
'italic': [
/(^|\s|>|\()((\/)([^<>'"\/]+)(\/))($|\s|<|\))/gi,
'$1<em>$2</em>$6'
],
'underline': [
/(^|\s|>|\()((_)([^<>'"_]+)(_))($|\s|<|\))/gi,
'$1<span style="text-decoration: underline;">$2</span>$6'
]
}
};
self.xhtml_allow = {
'elements': [
'a',
'abbr',
'acronym',
'address',
'blockquote',
'body',
'br',
'cite',
'code',
'dd',
'dfn',
'div',
'dt',
'em',
'h1',
'h2',
'h3',
'h4',
'h5',
'h6',
'head',
'html',
'kbd',
'li',
'ol',
'p',
'pre',
'q',
'samp',
'span',
'strong',
'title',
'ul',
'var'
],
'attributes': [
'accesskey',
'alt',
'charset',
'cite',
'class',
'height',
'href',
'hreflang',
'id',
'longdesc',
'profile',
'rel',
'rev',
'src',
'style',
'tabindex',
'title',
'type',
'uri',
'version',
'width',
'xml:lang',
'xmlns'
]
};
/** /**
* Generates a given emoticon HTML code * Generates a given emoticon HTML code
* @public * @public
@ -42,83 +336,64 @@ var Filter = (function () {
/** /**
* Filters a given message * Filters a given message
* @public * @public
* @param {string} neutralMessage * @param {string} message
* @param {string} nick * @param {string} nick
* @param {string} html_escape * @param {string} html_escape
* @return {string} * @return {string}
*/ */
self.message = function(neutralMessage, nick, html_escape) { self.message = function(message, nick, html_escape) {
try { try {
var filteredMessage = neutralMessage; var filtered = message;
// We encode the HTML special chars // We encode the HTML special chars
if(html_escape)
filteredMessage = filteredMessage.htmlEnc();
// /me command
filteredMessage = filteredMessage.replace(/((^)|((.+)(>)))(\/me )([^<]+)/, nick + ' $7')
// We replace the smilies text into images
.replace(/(:-?@)($|\s|<)/gi, self.emoteImage('angry', '$1', '$2'))
.replace(/(:-?\[)($|\s|<)/gi, self.emoteImage('bat', '$1', '$2'))
.replace(/(\(B\))($|\s|<)/g, self.emoteImage('beer', '$1', '$2'))
.replace(/((:-?D)|(XD))($|\s|<)/gi, self.emoteImage('biggrin', '$1', '$4'))
.replace(/(:-?\$)($|\s|<)/gi, self.emoteImage('blush', '$1', '$2'))
.replace(/(\(Z\))($|\s|<)/g, self.emoteImage('boy', '$1', '$2'))
.replace(/(\(W\))($|\s|<)/g, self.emoteImage('brflower', '$1', '$2'))
.replace(/((&lt;\/3)|(\(U\)))($|\s|<)/g, self.emoteImage('brheart', '$1', '$4'))
.replace(/(\(C\))($|\s|<)/g, self.emoteImage('coffee', '$1', '$2'))
.replace(/((8-\))|(\(H\)))($|\s|<)/g, self.emoteImage('coolglasses', '$1', '$4'))
.replace(/(:'-?\()($|\s|<)/gi, self.emoteImage('cry', '$1', '$2'))
.replace(/(\(%\))($|\s|<)/g, self.emoteImage('cuffs', '$1', '$2'))
.replace(/(\]:-?&gt;)($|\s|<)/gi, self.emoteImage('devil', '$1', '$2'))
.replace(/(\(D\))($|\s|<)/g, self.emoteImage('drink', '$1', '$2'))
.replace(/(@}-&gt;--)($|\s|<)/gi, self.emoteImage('flower', '$1', '$2'))
.replace(/((:-?\/)|(:-?S))($|\s|<)/gi, self.emoteImage('frowning', '$1', '$4'))
.replace(/(\(X\))($|\s|<)/g, self.emoteImage('girl', '$1', '$2'))
.replace(/((&lt;3)|(\(L\)))($|\s|<)/g, self.emoteImage('heart', '$1', '$4'))
.replace(/(\(}\))($|\s|<)/g, self.emoteImage('hugleft', '$1', '$2'))
.replace(/(\({\))($|\s|<)/g, self.emoteImage('hugright', '$1', '$2'))
.replace(/(:-?{})($|\s|<)/gi, self.emoteImage('kiss', '$1', '$2'))
.replace(/(\(I\))($|\s|<)/g, self.emoteImage('lamp', '$1', '$2'))
.replace(/(:-?3)($|\s|<)/gi, self.emoteImage('lion', '$1', '$2'))
.replace(/(\(E\))($|\s|<)/g, self.emoteImage('mail', '$1', '$2'))
.replace(/(\(S\))($|\s|<)/g, self.emoteImage('moon', '$1', '$2'))
.replace(/(\(8\))($|\s|<)/g, self.emoteImage('music', '$1', '$2'))
.replace(/((=-?O)|(:-?O))($|\s|<)/gi, self.emoteImage('oh', '$1', '$4'))
.replace(/(\(T\))($|\s|<)/g, self.emoteImage('phone', '$1', '$2'))
.replace(/(\(P\))($|\s|<)/g, self.emoteImage('photo', '$1', '$2'))
.replace(/(:-?!)($|\s|<)/gi, self.emoteImage('puke', '$1', '$2'))
.replace(/(\(@\))($|\s|<)/g, self.emoteImage('pussy', '$1', '$2'))
.replace(/(\(R\))($|\s|<)/g, self.emoteImage('rainbow', '$1', '$2'))
.replace(/(:-?\))($|\s|<)/gi, self.emoteImage('smile', '$1', '$2'))
.replace(/(\(\*\))($|\s|<)/g, self.emoteImage('star', '$1', '$2'))
.replace(/(:-?\|)($|\s|<)/gi, self.emoteImage('stare', '$1', '$2'))
.replace(/(\(N\))($|\s|<)/g, self.emoteImage('thumbdown', '$1', '$2'))
.replace(/(\(Y\))($|\s|<)/g, self.emoteImage('thumbup', '$1', '$2'))
.replace(/(:-?P)($|\s|<)/gi, self.emoteImage('tongue', '$1', '$2'))
.replace(/(:-?\()($|\s|<)/gi, self.emoteImage('unhappy', '$1', '$2'))
.replace(/(;-?\))($|\s|<)/gi, self.emoteImage('wink', '$1', '$2'))
// Text in bold
.replace(/(^|\s|>|\()((\*)([^<>'"\*]+)(\*))($|\s|<|\))/gi, '$1<b>$2</b>$6')
// Italic text
.replace(/(^|\s|>|\()((\/)([^<>'"\/]+)(\/))($|\s|<|\))/gi, '$1<em>$2</em>$6')
// Underlined text
.replace(/(^|\s|>|\()((_)([^<>'"_]+)(_))($|\s|<|\))/gi, '$1<span style="text-decoration: underline;">$2</span>$6');
// Add the links
if(html_escape) { if(html_escape) {
filteredMessage = Links.apply(filteredMessage, 'desktop'); filtered = filtered.htmlEnc();
} }
// Filter integratebox links // Security: don't filter huge messages (avoids crash attacks)
filteredMessage = IntegrateBox.filter(filteredMessage); if(filtered.length < 10000) {
// /me command
return filteredMessage; 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) { } catch(e) {
Console.error('Filter.message', e); Console.error('Filter.message', e);
} }
@ -126,6 +401,32 @@ var Filter = (function () {
}; };
/**
* 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 * Filters a xHTML message to be displayed in Jappix
* @public * @public
@ -135,106 +436,46 @@ var Filter = (function () {
self.xhtml = function(code) { self.xhtml = function(code) {
try { try {
// Allowed elements array var code_sel = $(code);
var elements = new Array(
'a',
'abbr',
'acronym',
'address',
'blockquote',
'body',
'br',
'cite',
'code',
'dd',
'dfn',
'div',
'dt',
'em',
'h1',
'h2',
'h3',
'h4',
'h5',
'h6',
'head',
'html',
'kbd',
'li',
'ol',
'p',
'pre',
'q',
'samp',
'span',
'strong',
'title',
'ul',
'var'
);
// Allowed attributes array
var attributes = new Array(
'accesskey',
'alt',
'charset',
'cite',
'class',
'height',
'href',
'hreflang',
'id',
'longdesc',
'profile',
'rel',
'rev',
'src',
'style',
'tabindex',
'title',
'type',
'uri',
'version',
'width',
'xml:lang',
'xmlns'
);
// Check if Filter for XHTML-IM images is enabled // Check if Filter for XHTML-IM images is enabled
if(DataStore.getDB(Connection.desktop_hash, 'options', 'no-xhtml-images') != '1') { if(DataStore.getDB(Connection.desktop_hash, 'options', 'no-xhtml-images') != '1') {
elements.push("img"); self.xhtml_allow.elements.push("img");
} }
// Remove forbidden elements // Remove forbidden elements
$(code).find('html body *').each(function() { code_sel.find('html body *').each(function() {
// This element is not authorized // This element is not authorized
if(!Utils.existArrayValue(elements, (this).nodeName.toLowerCase())) if(!Utils.existArrayValue(self.xhtml_allow.elements, (this).nodeName.toLowerCase())) {
$(this).remove(); $(this).remove();
}
}); });
// Remove forbidden attributes // Remove forbidden attributes
$(code).find('html body *').each(function() { code_sel.find('html body *').each(function() {
// Put a pointer on this element (jQuery way & normal way) // Put a pointer on this element (jQuery way & normal way)
var cSelector = $(this); var cSelector = $(this);
var cElement = (this); var cElement = (this);
// Loop the attributes of the current element // Loop the attributes of the current element
$(cElement.attributes).each(function(index) { $(cElement.attributes).each(function(index) {
// Read the current attribute // Read the current attribute
var cAttr = cElement.attributes[index]; var cAttr = cElement.attributes[index];
var cName = cAttr.name; var cName = cAttr.name;
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,17 +229,20 @@ 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() {
MUCAdmin.open(xid, affiliation); MUCAdmin.open(xid, affiliation);
@ -72,33 +267,35 @@ var Groupchat = (function () {
try { try {
// Room hash // Room hash
var hash = hex_md5(room); var hash = hex_md5(room);
// Reset the elements // Reset the elements
$('#' + hash + ' .muc-ask').remove(); $('#' + hash + ' .muc-ask').remove();
$('#' + hash + ' .compose').show(); $('#' + hash + ' .compose').show();
// 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) {
// Get our general presence // Get our general presence
var show = DataStore.getDB(Connection.desktop_hash, 'presence-show', 1); var show = DataStore.getDB(Connection.desktop_hash, 'presence-show', 1);
var status = DataStore.getDB(Connection.desktop_hash, 'options', 'presence-status'); var status = DataStore.getDB(Connection.desktop_hash, 'options', 'presence-status');
// Set my nick // Set my nick
$('#' + hash).attr('data-nick', escape(nickname)); $('#' + hash).attr('data-nick', escape(nickname));
// Send the appropriate presence // Send the appropriate presence
Presence.send(room + '/' + nickname, '', show, status, '', true, password, self.handleMUC); Presence.send(room + '/' + nickname, '', show, status, '', true, password, self.handleMUC);
} }
@ -126,43 +323,50 @@ 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);
// Catch the errors // Catch the errors
if(!Errors.handle(xml)) { if(!Errors.handle(xml)) {
// Define some stuffs // Define some stuffs
var muc_user = $(xml).find('x[xmlns="' + NS_MUC_USER + '"]'); var muc_user = $(xml).find('x[xmlns="' + NS_MUC_USER + '"]');
var affiliation = muc_user.find('item').attr('affiliation'); var affiliation = muc_user.find('item').attr('affiliation');
var statuscode = parseInt(muc_user.find('status').attr('code')); var statuscode = parseInt(muc_user.find('status').attr('code'));
// Handle my presence // Handle my presence
Presence.handle(presence); Presence.handle(presence);
// Configure the new room
if(affiliation == 'owner' || affiliation == 'admin') {
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);
// Tell the MUC we can notify the incoming presences // Tell the MUC we can notify the incoming presences
$(document).oneTime('15s', function() { $(document).oneTime('15s', function() {
$('#' + hash).attr('data-initial', 'true'); $('#' + hash).attr('data-initial', 'true');
}); });
// Enable the chatting input // Enable the chatting input
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
$('#' + hash + ' .message-area').removeAttr('disabled').focus(); $('#' + hash + ' .message-area').removeAttr('disabled').focus();
}); });
} }
// A password is required // A password is required
else if($(xml).find('error[type="auth"] not-authorized').size()) { else if($(xml).find('error[type="auth"] not-authorized').size()) {
self.generateMUCAsk('password', room, hash, nickname); self.generateMUCAsk('password', room, hash, nickname);
} }
// There's a nickname conflict // There's a nickname conflict
else if($(xml).find('error[type="cancel"] conflict').size()) { else if($(xml).find('error[type="cancel"] conflict').size()) {
self.generateMUCAsk('nickname', room, hash); self.generateMUCAsk('nickname', room, hash);
@ -189,34 +393,34 @@ var Groupchat = (function () {
try { try {
// Generate the path to the elements // Generate the path to the elements
var path_to = '#' + hash + ' .muc-ask'; var path_to = '#' + hash + ' .muc-ask';
// Define the label text // Define the label text
var label_text; var label_text;
switch(type) { switch(type) {
case 'nickname': case 'nickname':
label_text = Common._e("Nickname"); label_text = Common._e("Nickname");
break; break;
case 'password': case 'password':
label_text = Common._e("Password"); label_text = Common._e("Password");
break; break;
} }
// Create the HTML markup // Create the HTML markup
$('#' + hash + ' .compose').hide(); $('#' + hash + ' .compose').hide();
$('#' + hash).append( $('#' + hash).append(
'<div class="muc-ask text">' + '<div class="muc-ask text">' +
'<label>' + label_text + '</label>' + '<label>' + label_text + '</label>' +
'<input class="focusable" type="text" />' + '<input class="focusable" type="text" />' +
'</div>' '</div>'
); );
// When a key is pressed in the input // When a key is pressed in the input
$(path_to + ' input').keyup(function(e) { $(path_to + ' input').keyup(function(e) {
var value_input = $(this).val(); var value_input = $(this).val();
// Enter key pressed // Enter key pressed
if(e.keyCode == 13) { if(e.keyCode == 13) {
// $.trim() fixes #304 // $.trim() fixes #304
@ -224,14 +428,14 @@ var Groupchat = (function () {
nickname = $.trim(value_input); nickname = $.trim(value_input);
return self.getMUC(room, nickname, password); return self.getMUC(room, nickname, password);
} }
if(type == 'password' && value_input) { if(type == 'password' && value_input) {
password = value_input; password = value_input;
return self.getMUC(room, nickname, password); return self.getMUC(room, nickname, password);
} }
} }
}); });
// Focus on the input // Focus on the input
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
$(path_to + ' input').focus(); $(path_to + ' input').focus();
@ -259,86 +463,37 @@ var Groupchat = (function () {
try { try {
Console.info('New groupchat: ' + room); Console.info('New groupchat: ' + room);
// Create the chat content // Create the chat content
Chat.generate('groupchat', hash, room, chan); Chat.generate('groupchat', hash, room, chan);
// Create the chat switcher // Create the chat switcher
Chat.generateSwitch('groupchat', hash, room, chan); Chat.generateSwitch('groupchat', hash, room, chan);
// The icons-hover functions // The icons-hover functions
Tooltip.icons(room, hash); Tooltip.icons(room, hash);
// Click event on the add tool // Click event on the add tool
$('#' + 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();
// Add the groupchat to the user favorites // Add the groupchat to the user favorites
Favorites.addThis(room, chan); Favorites.addThis(room, chan);
}); });
// Must show the add button?
if(!DataStore.existDB('favorites', room))
$('#' + hash + ' .tools-add').show();
// The event handlers
var inputDetect = $('#' + hash + ' .message-area');
// Focus event
inputDetect.focus(function() {
// Clean notifications for this chat
Interface.chanCleanNotify(hash);
// Store focus on this chat!
Interface.chat_focus_hash = hash;
});
// Blur event
inputDetect.blur(function() {
// Reset storage about focus on this chat!
if(Interface.chat_focus_hash == hash)
Interface.chat_focus_hash = null;
// Reset autocompletion // Must show the add button?
Autocompletion.reset(hash); if(!DataStore.existDB(Connection.desktop_hash, 'favorites', room)) {
}); $('#' + hash + ' .tools-add').show();
}
// Lock to the input
inputDetect.keydown(function(e) { // The event handlers
// Enter key var input_sel = $('#' + hash + ' .message-area');
if(e.keyCode == 13) { self._createEvents(input_sel, hash, room);
// 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);
} catch(e) { } catch(e) {
@ -359,27 +514,30 @@ var Groupchat = (function () {
// Values array // Values array
var muc_arr = [GROUPCHATS_JOIN]; var muc_arr = [GROUPCHATS_JOIN];
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) {
Console.error('Groupchat.arrayJoin', e); Console.error('Groupchat.arrayJoin', 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) {
@ -422,16 +581,17 @@ var Groupchat = (function () {
try { try {
var groupchat_arr = self.arrayJoin(); var groupchat_arr = self.arrayJoin();
// 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">';
html += '<div class="title">' + Common._e("Suggested chatrooms") + '</div>'; html += '<div class="title">' + Common._e("Suggested chatrooms") + '</div>';
html += '<div class="content">'; html += '<div class="content">';
for(var g in groupchat_arr) { for(var g in groupchat_arr) {
html += '<a class="one" href="#" data-xid="' + Common.encodeQuotes(groupchat_arr[g]) + '">'; html += '<a class="one" href="#" data-xid="' + Common.encodeQuotes(groupchat_arr[g]) + '">';
@ -442,52 +602,21 @@ var Groupchat = (function () {
html += '</a>'; html += '</a>';
} }
html += '</div>'; html += '</div>';
html += '<div class="bottom">'; html += '<div class="bottom">';
html += '<a class="next continue disabled" href="#">' + Common._e("Continue") + '</a>'; html += '<a class="next continue disabled" href="#">' + Common._e("Continue") + '</a>';
html += '<a class="next skip" href="#">' + Common._e("Skip") + '</a>'; html += '<a class="next skip" href="#">' + Common._e("Skip") + '</a>';
html += '</div>'; html += '</div>';
html += '</div>'; html += '</div>';
// 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();
} }
} catch(e) { } catch(e) {
@ -512,20 +641,26 @@ 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();
iq.setTo(room_xid); iq.setTo(room_xid);
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);
Console.log('Banned user with XID: ' + ban_xid + ' from room: ' + room_xid); Console.log('Banned user with XID: ' + ban_xid + ' from room: ' + room_xid);
@ -559,14 +694,20 @@ var Groupchat = (function () {
var iq = new JSJaCIQ(); var iq = new JSJaCIQ();
iq.setTo(room_xid); iq.setTo(room_xid);
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);
Console.info('Kicked user "' + nick + '" from room: ' + room_xid); Console.info('Kicked user "' + nick + '" from room: ' + room_xid);
@ -671,10 +812,54 @@ 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
*/ */
return self; return self;
})(); })();

View file

@ -20,6 +20,119 @@ var Home = (function () {
var self = {}; var self = {};
/**
* Apply change events
* @private
* @param {object} current_sel
* @param {string} div
* @return {undefined}
*/
self._eventsChange = function(current_sel, div) {
try {
// Create the attached events
switch(div) {
// Login tool
case 'loginer':
current_sel.find('a.to-anonymous').click(function() {
return self.change('anonymouser');
});
current_sel.find('a.advanced').click(self.showAdvanced);
current_sel.find('form').submit(self.loginForm);
break;
// Anonymous login tool
case 'anonymouser':
current_sel.find('a.to-home').click(function() {
return self.change('loginer');
});
current_sel.find('form').submit(Connection.doAnonymous);
// Keyup event on anonymous join's room input
current_sel.find('input.room').keyup(function() {
var value = $(this).val();
var report_sel = current_sel.find('.report');
var span_sel = current_sel.find('span');
if(!value) {
report_sel.hide();
span_sel.text('');
} else {
report_sel.show();
span_sel.text(JAPPIX_LOCATION + '?r=' + value);
}
});
break;
// Register tool
case 'registerer':
// Server input change
$('#home input.server').keyup(function(e) {
if($.trim($(this).val()) == HOST_MAIN) {
$('#home .captcha_grp').show();
$('#home input.captcha').removeAttr('disabled');
} else {
$('#home .captcha_grp').hide();
$('#home input.captcha').attr('disabled', true);
}
});
// Register input placeholder
// FIXME: breaks IE compatibility
//$('#home input[placeholder]').placeholder();
// Register form submit
current_sel.find('form').submit(self.registerForm);
break;
}
} catch(e) {
Console.error('Home._eventsChange', e);
}
};
/**
* Create obsolete form
* @private
* @param {string} home
* @param {string} locale
* @return {undefined}
*/
self._obsolete = function(home, locale) {
try {
// Add the code
$(locale).after(
'<div class="obsolete">' +
'<p>' + Common._e("Your browser is out of date!") + '</p>' +
'<a class="firefox browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Mozilla Firefox') + '" href="http://www.mozilla.com/firefox/"></a>' +
'<a class="chrome browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Google Chrome') + '" href="http://www.google.com/chrome"></a>' +
'<a class="safari browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Safari') + '" href="http://www.apple.com/safari/"></a>' +
'<a class="opera browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Opera') + '" href="http://www.opera.com/"></a>' +
'<a class="ie browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Internet Explorer') + '" href="http://www.microsoft.com/hk/windows/internet-explorer/"></a>' +
'</div>'
);
// Display it later
$(home + '.obsolete').oneTime('1s', function() {
$(this).slideDown();
});
Console.warn('Jappix does not support this browser!');
} catch(e) {
Console.error('Home._obsolete', e);
}
};
/** /**
* Allows the user to switch the difference home page elements * Allows the user to switch the difference home page elements
* @public * @public
@ -33,19 +146,19 @@ var Home = (function () {
var home = '#home .'; var home = '#home .';
var right = home + 'right '; var right = home + 'right ';
var current = right + '.homediv.' + div; var current = right + '.homediv.' + div;
// We switch the div // We switch the div
$(right + '.homediv, ' + right + '.top').hide(); $(right + '.homediv, ' + right + '.top').hide();
$(right + '.' + div).show(); $(right + '.' + div).show();
// We reset the homedivs // We reset the homedivs
$(home + 'homediv:not(.default), ' + home + 'top:not(.default)').remove(); $(home + 'homediv:not(.default), ' + home + 'top:not(.default)').remove();
// Get the HTML code to display // Get the HTML code to display
var disable_form = ''; var disable_form = '';
var lock_host = ''; var lock_host = '';
var code = ''; var code = '';
// Apply the previous link // Apply the previous link
switch(div) { switch(div) {
case 'loginer': case 'loginer':
@ -54,196 +167,144 @@ var Home = (function () {
if(!Common.exists(right + '.top.sub')) { if(!Common.exists(right + '.top.sub')) {
// Append the HTML code for previous link // Append the HTML code for previous link
$(right + '.top.default').after('<h1 class="top sub loginer anonymouser registerer">&laquo; <a href="#" class="previous">' + Common._e("Previous") + '</a></h1>'); $(right + '.top.default').after('<h1 class="top sub loginer anonymouser registerer">&laquo; <a href="#" class="previous">' + Common._e("Previous") + '</a></h1>');
// Click event on previous link // Click event on previous link
$(home + 'top.sub a.previous').click(function() { $(home + 'top.sub a.previous').click(function() {
return self.change('default'); return self.change('default');
}); });
} }
break; break;
} }
// Apply the form // Apply the form
switch(div) { switch(div) {
// Login tool // Login tool
case 'loginer': case 'loginer':
lock_host = Utils.disableInput(LOCK_HOST, 'on'); lock_host = Utils.disableInput(LOCK_HOST, 'on');
code = '<p>' + Common.printf(Common._e("Login to your existing XMPP account. You can also use the %s to join a groupchat."), '<a href="#" class="to-anonymous">' + Common._e("anonymous mode") + '</a>') + '</p>' + code = '<p>' + Common.printf(Common._e("Login to your existing XMPP account. You can also use the %s to join a groupchat."), '<a href="#" class="to-anonymous">' + Common._e("anonymous mode") + '</a>') + '</p>' +
'<form action="#" method="post">' +
'<fieldset>' +
'<legend>' + Common._e("Required") + '</legend>' +
'<label for="lnick">' + Common._e("Address") + '</label>' +
'<input type="text" class="nick" id="lnick" pattern="[^@/]+" required="" /><span class="jid">@</span><input type="text" class="server" id="lserver" value="' + HOST_MAIN + '" ' + lock_host + ' pattern="[^@/]+" required="" />' +
'<label for="lpassword">' + Common._e("Password") + '</label>' +
'<input type="password" class="password" id="lpassword" required="" />' +
'<label for="lremember">' + Common._e("Remember me") + '</label>' +
'<input type="checkbox" class="remember" id="lremember" />' +
'</fieldset>' +
'<a href="#" class="advanced home-images">' + Common._e("Advanced") + '</a>' +
'<fieldset class="advanced">' +
'<legend>' + Common._e("Advanced") + '</legend>' +
'<label for="lresource">' + Common._e("Resource") + '</label>' +
'<input type="text" class="resource" id="lresource" value="' + JAPPIX_RESOURCE + '" />' +
'<label for="lpriority">' + Common._e("Priority") + '</label>' +
'<select class="priority" id="lpriority">' +
'<option value="1">' + Common._e("Low") + '</option>' +
'<option value="10" selected="">' + Common._e("Medium") + '</option>' +
'<option value="100">' + Common._e("High") + '</option>' +
'</select>' +
'</fieldset>' +
'<div class="submit">' +
'<input type="submit" value="' + Common._e("Here we go!") + '" />' +
'<div class="clear"></div>' + '<form action="#" method="post">' +
'</div>' + '<fieldset>' +
'<legend>' + Common._e("Required") + '</legend>' +
'<label for="lnick">' + Common._e("Address") + '</label>' +
'<input type="text" class="nick" id="lnick" pattern="[^@/]+" required="" /><span class="jid">@</span><input type="text" class="server" id="lserver" value="' + HOST_MAIN + '" ' + lock_host + ' pattern="[^@/]+" required="" list="server" />' +
'<label for="lpassword">' + Common._e("Password") + '</label>' +
'<input type="password" class="password" id="lpassword" required="" />' +
'<label for="lremember">' + Common._e("Remember me") + '</label>' +
'<input type="checkbox" class="remember" id="lremember" />' +
'</fieldset>' +
'<a href="#" class="advanced home-images">' + Common._e("Advanced") + '</a>' +
'<fieldset class="advanced">' +
'<legend>' + Common._e("Advanced") + '</legend>' +
'<label for="lresource">' + Common._e("Resource") + '</label>' +
'<input type="text" class="resource" id="lresource" value="' + JAPPIX_RESOURCE + '" />' +
'<label for="lpriority">' + Common._e("Priority") + '</label>' +
'<select class="priority" id="lpriority">' +
'<option value="1">' + Common._e("Low") + '</option>' +
'<option value="10" selected="">' + Common._e("Medium") + '</option>' +
'<option value="100">' + Common._e("High") + '</option>' +
'</select>' +
'</fieldset>' +
'<div class="submit">' +
'<input type="submit" value="' + Common._e("Here we go!") + '" />' +
'<div class="clear"></div>' +
'</div>' +
'</form>'; '</form>';
break; break;
// Anonymous login tool // Anonymous login tool
case 'anonymouser': case 'anonymouser':
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">' +
'<fieldset>' + code += '<form action="#" method="post">' +
'<legend>' + Common._e("Required") + '</legend>' + '<fieldset>' +
'<legend>' + Common._e("Required") + '</legend>' +
'<label>' + Common._e("Room") + '</label>' +
'<input type="text" class="room"' + disable_form + ' pattern="[^/]+" required="" />' + '<label>' + Common._e("Room") + '</label>' +
'<input type="text" class="room"' + disable_form + ' pattern="[^/]+" required="" />' +
'<label>' + Common._e("Nickname") + '</label>' +
'<input type="text" class="nick"' + disable_form + ' required="" />' + '<label>' + Common._e("Nickname") + '</label>' +
'</fieldset>' + '<input type="text" class="nick"' + disable_form + ' required="" />' +
'</fieldset>' +
'<input type="submit" value="' + Common._e("Here we go!") + '"' + disable_form + ' />' +
'</form>' + '<input type="submit" value="' + Common._e("Here we go!") + '"' + disable_form + ' />' +
'</form>' +
'<div class="info report">' +
Common._e("Share this link with your friends:") + ' <span></span>' + '<div class="info report">' +
Common._e("Share this link with your friends:") + ' <span></span>' +
'</div>'; '</div>';
break; break;
// Register tool // Register tool
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">' +
'<fieldset>' + code += '<form action="#" method="post">' +
'<legend>' + Common._e("Required") + '</legend>' + '<fieldset>' +
'<legend>' + Common._e("Required") + '</legend>' +
'<label for="rnick">' + Common._e("Address") + '</label>' +
'<input type="text" class="nick" id="rnick" ' + disable_form + ' pattern="[^@/]+" required="" placeholder="' + Common._e("Username") + '" /><span class="jid">@</span><input type="text" class="server" id="rserver" value="' + HOST_MAIN + '" ' + disable_form + lock_host + ' pattern="[^@/]+" required="" placeholder="' + Common._e("Server") + '" />' + '<label for="rnick">' + Common._e("Address") + '</label>' +
'<label for="rpassword">' + Common._e("Password") + '</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="" list="server" placeholder="' + Common._e("Server") + '" />' +
'<label for="rpassword">' + Common._e("Password") + '</label>' +
'<input type="password" class="password" id="rpassword" ' + disable_form + ' required="" placeholder="' + Common._e("Enter password") + '" /><input type="password" class="spassword" id="spassword" ' + disable_form + ' required="" placeholder="' + Common._e("Once again...") + '" />'; '<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>' +
'<input type="submit" value="' + Common._e("Here we go!") + '" ' + disable_form + '/>' +
'<input type="submit" value="' + Common._e("Here we go!") + '" ' + disable_form + '/>' +
'</form>'; '</form>';
break; break;
} }
// 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
switch(div) { self._eventsChange(
// Login tool $(current),
case 'loginer': div
$(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
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
$(right + 'input:visible:first').focus(); $(right + 'input:visible:first').focus();
@ -267,7 +328,7 @@ var Home = (function () {
try { try {
// Hide the link // Hide the link
$('#home a.advanced').hide(); $('#home a.advanced').hide();
// Show the fieldset // Show the fieldset
$('#home fieldset.advanced').show(); $('#home fieldset.advanced').show();
} catch(e) { } catch(e) {
@ -288,27 +349,29 @@ 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) {
Connection.doLogin(lNick, lServer, lPass, lResource, lPriority, lRemember); Connection.doLogin(lNick, lServer, lPass, lResource, lPriority, lRemember);
} else { } else {
$(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,38 +391,40 @@ 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)) {
// We remove the not completed class to avoid problems // We remove the not completed class to avoid problems
$('#home .registerer input').removeClass('please-complete'); $('#home .registerer input').removeClass('please-complete');
// Fire the register event! // Fire the register event!
Connection.doRegister(username, domain, pass, captcha); Connection.doRegister(username, domain, pass, captcha);
} }
// 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) {
@ -387,76 +452,61 @@ var Home = (function () {
var corp = home + '.corporation'; var corp = home + '.corporation';
var aboutus = home + '.aboutus'; var aboutus = home + '.aboutus';
var locale = home + '.locale'; var locale = home + '.locale';
// Removes the <noscript /> elements to lighten the DOM // Removes the <noscript /> elements to lighten the DOM
$('noscript').remove(); $('noscript').remove();
// 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
$(corp + ', ' + aboutus).hover(function() { $(corp + ', ' + aboutus).hover(function() {
$(this).addClass('hovered'); $(this).addClass('hovered');
}, function() { }, function() {
$(this).removeClass('hovered'); $(this).removeClass('hovered');
}); });
// Allows the user to switch the language // Allows the user to switch the language
$(locale).hover(function() { $(locale).hover(function() {
// Initialize the HTML code // Initialize the HTML code
var keepget = $(locale).attr('data-keepget'); var keepget = $(locale).attr('data-keepget');
var html = '<div class="list">'; var html = '<div class="list">';
// Generate each locale HTML code // Generate each locale HTML code
for(var i in LOCALES_AVAILABLE_ID) { for(var i in LOCALES_AVAILABLE_ID) {
html += '<a href="./?l=' + LOCALES_AVAILABLE_ID[i] + keepget + '">' + LOCALES_AVAILABLE_NAMES[i].htmlEnc() + '</a>'; html += '<a href="./?l=' + LOCALES_AVAILABLE_ID[i] + keepget + '">' + LOCALES_AVAILABLE_NAMES[i].htmlEnc() + '</a>';
} }
html += '</div>'; html += '</div>';
// Append the HTML code // Append the HTML code
$(locale).append(html); $(locale).append(html);
}, function() { }, function() {
$(locale + ' .list').remove(); $(locale + ' .list').remove();
}); });
// 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!');
}); });
} catch(e) { } catch(e) {
@ -473,4 +523,4 @@ var Home = (function () {
})(); })();
Home.launch(); Home.launch();

View file

@ -34,8 +34,6 @@ var HTTPAuth = (function () {
try { try {
// We add the login wait div // We add the login wait div
Interface.showGeneralWait(); Interface.showGeneralWait();
oArgs = {};
if(Common.hasWebSocket()) { if(Common.hasWebSocket()) {
// WebSocket supported & configured // WebSocket supported & configured
@ -47,60 +45,58 @@ var HTTPAuth = (function () {
// Check BOSH origin // Check BOSH origin
BOSH_SAME_ORIGIN = Origin.isSame(httpbase); BOSH_SAME_ORIGIN = Origin.isSame(httpbase);
// We create the new http-binding connection // We create the new http-binding connection
con = new JSJaCHttpBindingConnection({ con = new JSJaCHttpBindingConnection({
httpbase: httpbase httpbase: httpbase
}); });
} }
// And we handle everything that happen // And we handle everything that happen
Connection.setupCon(con); Connection.setupCon(con);
// Generate a resource // Generate a resource
var random_resource = DataStore.getDB(Connection.desktop_hash, 'session', 'resource'); var random_resource = DataStore.getDB(Connection.desktop_hash, 'session', 'resource');
if(!random_resource) { if(!random_resource) {
random_resource = JAPPIX_RESOURCE + ' (' + (new Date()).getTime() + ')'; random_resource = JAPPIX_RESOURCE + ' (' + (new Date()).getTime() + ')';
} }
// 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);
// 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>' + random_resource + '</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>' + random_resource + '</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)
Connection.current_session = session_xml; Connection.current_session = session_xml;
// We store the infos of the user into the data-base // We store the infos of the user into the data-base
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');
Console.info('Jappix is connecting...'); Console.info('Jappix is connecting...');
} catch(e) { } catch(e) {
Console.error('HTTPAuth.go', e); Console.error('HTTPAuth.go', e);
// Reset Jappix // Reset Jappix
Talk.destroy(); Talk.destroy();
// Open an unknown error // Open an unknown error
Board.openThisError(2); Board.openThisError(2);
} finally { } finally {

View file

@ -37,23 +37,31 @@ var HTTPReply = (function () {
var id = confirm.attr('id'); var id = confirm.attr('id');
var method = confirm.attr('method'); var method = confirm.attr('method');
var url = confirm.attr('url'); var url = confirm.attr('url');
// We generate the reply message // We generate the reply message
var aMsg = new JSJaCMessage(); var aMsg = new JSJaCMessage();
aMsg.setTo(from); aMsg.setTo(from);
// 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);
Console.info('Replying HTTP auth request: ' + from); Console.info('Replying HTTP auth request: ' + from);
} catch(e) { } catch(e) {
Console.error('HTTPReply.go', e); Console.error('HTTPReply.go', e);

View file

@ -29,69 +29,69 @@ var Inbox = (function () {
try { try {
// Popup HTML content // Popup HTML content
var html = var html =
'<div class="top">' + Common._e("Your inbox") + '</div>' + '<div class="top">' + Common._e("Your inbox") + '</div>' +
'<div class="content">' + '<div class="content">' +
'<div class="head inbox-head">' + '<div class="head inbox-head">' +
'<div class="head-text inbox-head-text">' + Common._e("Available actions") + '</div>' + '<div class="head-text inbox-head-text">' + Common._e("Available actions") + '</div>' +
'<div class="head-actions inbox-head-actions">' + '<div class="head-actions inbox-head-actions">' +
'<a href="#" class="a-delete-messages">' + Common._e("Clean") + '</a>' + '<a href="#" class="a-delete-messages">' + Common._e("Clean") + '</a>' +
'<a href="#" class="a-new-message">' + Common._e("New") + '</a>' + '<a href="#" class="a-new-message">' + Common._e("New") + '</a>' +
'<a href="#" class="a-show-messages">' + Common._e("Received") + '</a>' + '<a href="#" class="a-show-messages">' + Common._e("Received") + '</a>' +
'</div>' + '</div>' +
'</div>' + '</div>' +
'<div class="inbox-results">' + '<div class="inbox-results">' +
'<p class="inbox-noresults">' + Common._e("Your inbox is empty.") + '</p>' + '<p class="inbox-noresults">' + Common._e("Your inbox is empty.") + '</p>' +
'<div class="inbox"></div>' + '<div class="inbox"></div>' +
'</div>' + '</div>' +
'<div class="inbox-new">' + '<div class="inbox-new">' +
'<div class="inbox-new-to inbox-new-block search">' + '<div class="inbox-new-to inbox-new-block search">' +
'<p class="inbox-new-text">' + Common._e("To") + '</p>' + '<p class="inbox-new-text">' + Common._e("To") + '</p>' +
'<input name="inbox-new-to-input" class="inbox-new-input inbox-new-to-input" type="text" required="" />' + '<input name="inbox-new-to-input" class="inbox-new-input inbox-new-to-input" type="text" required="" />' +
'</div>' + '</div>' +
'<div class="inbox-new-topic inbox-new-block">' + '<div class="inbox-new-topic inbox-new-block">' +
'<p class="inbox-new-text">' + Common._e("Subject") + '</p>' + '<p class="inbox-new-text">' + Common._e("Subject") + '</p>' +
'<input name="inbox-new-subject-input" class="inbox-new-input inbox-new-subject-input" type="text" required="" />' + '<input name="inbox-new-subject-input" class="inbox-new-input inbox-new-subject-input" type="text" required="" />' +
'</div>' + '</div>' +
'<div class="inbox-new-body inbox-new-block">' + '<div class="inbox-new-body inbox-new-block">' +
'<p class="inbox-new-text">' + Common._e("Content") + '</p>' + '<p class="inbox-new-text">' + Common._e("Content") + '</p>' +
'<textarea class="inbox-new-textarea" rows="8" cols="60" required=""></textarea>' + '<textarea class="inbox-new-textarea" rows="8" cols="60" required=""></textarea>' +
'</div>' + '</div>' +
'<form class="inbox-new-file inbox-new-block" action="./server/file-share.php" method="post" enctype="multipart/form-data">' + '<form class="inbox-new-file inbox-new-block" action="./server/file-share.php" method="post" enctype="multipart/form-data">' +
'<p class="inbox-new-text">' + Common._e("File") + '</p>' + '<p class="inbox-new-text">' + Common._e("File") + '</p>' +
Interface.generateFileShare() + Interface.generateFileShare() +
'</form>' + '</form>' +
'<div class="inbox-new-send inbox-new-block">' + '<div class="inbox-new-send inbox-new-block">' +
'<a href="#" class="send one-button talk-images">' + Common._e("Send message") + '</a>' + '<a href="#" class="send one-button talk-images">' + Common._e("Send message") + '</a>' +
'</div>' + '</div>' +
'</div>' + '</div>' +
'</div>' + '</div>' +
'<div class="bottom">' + '<div class="bottom">' +
'<div class="wait wait-medium"></div>' + '<div class="wait wait-medium"></div>' +
'<a href="#" class="finish">' + Common._e("Close") + '</a>' + '<a href="#" class="finish">' + Common._e("Close") + '</a>' +
'</div>'; '</div>';
// Create the popup // Create the popup
Popup.create('inbox', html); Popup.create('inbox', html);
// Associate the events // Associate the events
self.instance(); self.instance();
// Load the messages // Load the messages
self.load(); self.load();
} catch(e) { } catch(e) {
@ -134,10 +134,10 @@ var Inbox = (function () {
// Open things // Open things
self.open(); self.open();
self.newMessage(); self.newMessage();
// Apply XID // Apply XID
$('#inbox .inbox-new-to-input').val(xid); $('#inbox .inbox-new-to-input').val(xid);
// Focus to the next item // Focus to the next item
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
$('#inbox .inbox-new-subject-input').focus(); $('#inbox .inbox-new-subject-input').focus();
@ -163,33 +163,32 @@ var Inbox = (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_INBOX})); var storage = query.appendChild(iq.buildNode('storage', {'xmlns': NS_INBOX}));
var db_regex = new RegExp(('^' + Connection.desktop_hash + '_') + 'inbox' + ('_(.+)')); var db_regex = new RegExp(('^' + Connection.desktop_hash + '_') + 'inbox' + ('_(.+)'));
for(var i = 0; i < DataStore.storageDB.length; i++) { for(var i = 0; i < DataStore.storageDB.length; i++) {
// Get the pointer values // Get the pointer values
var current = DataStore.storageDB.key(i); var current = DataStore.storageDB.key(i);
// If the pointer is on a stored message // If the pointer is on a stored message
if(current.match(db_regex)) { if(current.match(db_regex)) {
// Get the values // Get the values
var value = $(Common.XMLFromString(DataStore.storageDB.getItem(current))); var value = $(Common.XMLFromString(DataStore.storageDB.getItem(current)));
// Create the storage node // Create the storage node
storage.appendChild(iq.buildNode('message', { storage.appendChild(
'id': value.find('id').text().revertHtmlEnc(), iq.buildNode('message', {
'from': value.find('from').text().revertHtmlEnc(), 'id': value.find('id').text().revertHtmlEnc(),
'subject': value.find('subject').text().revertHtmlEnc(), 'from': value.find('from').text().revertHtmlEnc(),
'status': value.find('status').text().revertHtmlEnc(), 'subject': value.find('subject').text().revertHtmlEnc(),
'date': value.find('date').text().revertHtmlEnc(), 'status': value.find('status').text().revertHtmlEnc(),
'xmlns': NS_INBOX 'date': value.find('date').text().revertHtmlEnc(),
}, 'xmlns': NS_INBOX
}, value.find('content').text().revertHtmlEnc()
value.find('content').text().revertHtmlEnc() ));
));
} }
} }
con.send(iq); con.send(iq);
} catch(e) { } catch(e) {
Console.error('Inbox.store', e); Console.error('Inbox.store', e);
@ -207,20 +206,20 @@ 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
self.cleanNewMessage(); self.cleanNewMessage();
} catch(e) { } catch(e) {
@ -230,7 +229,7 @@ var Inbox = (function () {
} }
}; };
/** /**
* Cleans the inbox * Cleans the inbox
@ -241,16 +240,16 @@ var Inbox = (function () {
try { try {
// Init // Init
var mPath = '#inbox .'; var inbox_sel = $('#inbox');
// We reset the forms // We reset the forms
$(mPath + 'inbox-new-block:not(form) input, ' + mPath + 'inbox-new textarea').val('').removeClass('please-complete'); inbox_sel.find('.inbox-new-block:not(form) input, .inbox-new textarea').val('').removeClass('please-complete');
$(mPath + 'inbox-new-file a').remove(); inbox_sel.find('.inbox-new-file a').remove();
$(mPath + 'inbox-new-file input').show(); inbox_sel.find('.inbox-new-file input').show();
// We close an eventual opened message // We close an eventual opened message
$(mPath + 'message-content').remove(); inbox_sel.find('.message-content').remove();
$(mPath + 'one-message').removeClass('message-reading'); inbox_sel.find('.one-message').removeClass('message-reading');
} catch(e) { } catch(e) {
Console.error('Inbox.cleanNewMessage', e); Console.error('Inbox.cleanNewMessage', e);
} }
@ -270,26 +269,26 @@ var Inbox = (function () {
try { try {
// We send the message // We send the message
var mess = new JSJaCMessage(); var message = new JSJaCMessage();
// Main attributes // Main attributes
mess.setTo(to); message.setTo(to);
mess.setSubject(subject); message.setSubject(subject);
mess.setType('normal'); message.setType('normal');
// Any file to attach? // Any file to attach?
var attached = '#inbox .inbox-new-file a.file'; var attached = '#inbox .inbox-new-file a.file';
if(Common.exists(attached)) { if(Common.exists(attached)) {
body += '\n' + body += '\n' +
'\n' + '\n' +
$(attached).attr('data-attachedtitle') + ' - ' + $(attached).attr('data-attachedhref'); $(attached).attr('data-attachedtitle') + ' - ' + $(attached).attr('data-attachedhref');
} }
// Set body // Set body
mess.setBody(body); message.setBody(body);
con.send(mess, Errors.handleReply); con.send(message, Errors.handleReply);
} catch(e) { } catch(e) {
Console.error('Inbox.sendMessage', e); Console.error('Inbox.sendMessage', e);
} }
@ -306,54 +305,54 @@ 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
var xid = new Array(to); var xid = new Array(to);
// More than one XID // More than one XID
if(to.indexOf(',') != -1) { if(to.indexOf(',') != -1) {
xid = to.split(','); xid = to.split(',');
} }
for(var i in xid) { for(var i in xid) {
var current = xid[i]; var current = xid[i];
// No current value? // No current value?
if(!current || current.match(/^(\s+)$/)) if(!current || current.match(/^(\s+)$/))
continue; continue;
// Edit the XID if needed // Edit the XID if needed
current = current.replace(/ /g, ''); current = current.replace(/ /g, '');
current = Common.generateXID(current, 'chat'); current = Common.generateXID(current, 'chat');
// We send the message // We send the message
self.sendMessage(current, subject, body); self.sendMessage(current, subject, body);
// We clean the inputs // We clean the inputs
self.cleanNewMessage(); self.cleanNewMessage();
Console.info('Inbox message sent: ' + current); Console.info('Inbox message sent: ' + current);
} }
// Close the inbox // Close the inbox
self.close(); self.close();
} }
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,18 +373,17 @@ 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();
} catch(e) { } catch(e) {
@ -414,50 +412,50 @@ var Inbox = (function () {
// Generate some paths // Generate some paths
var inbox = '#inbox .'; var inbox = '#inbox .';
var one_message = inbox + 'one-message.' + id; var one_message = inbox + 'one-message.' + id;
// Message yet displayed! // Message yet displayed!
if(Common.exists(one_message)) { if(Common.exists(one_message)) {
return false; return false;
} }
// Get the nearest element // Get the nearest element
var stamp = DateUtils.extractStamp(Date.jab2date(date)); var stamp = DateUtils.extractStamp(Date.jab2date(date));
var nearest = Search.sortElementByStamp(stamp, '#inbox .one-message'); var nearest = Search.sortElementByStamp(stamp, '#inbox .one-message');
// Get the buddy name // Get the buddy name
var name = Name.getBuddy(from).htmlEnc(); var name = Name.getBuddy(from).htmlEnc();
// We generate the html code // We generate the html code
var nContent = '<div class="one-message message-' + status + ' ' + id + ' ' + hex_md5(from) + '" data-stamp="' + stamp + '">' + var nContent = '<div class="one-message message-' + status + ' ' + id + ' ' + hex_md5(from) + '" data-stamp="' + stamp + '">' +
'<div class="message-head">' + '<div class="message-head">' +
'<div class="avatar-container">' + '<div class="avatar-container">' +
'<img class="avatar" src="' + './images/others/default-avatar.png' + '" alt="" />' + '<img class="avatar" src="' + './images/others/default-avatar.png' + '" alt="" />' +
'</div>' + '</div>' +
'<div class="message-jid">' + name + '</div>' + '<div class="message-jid">' + name + '</div>' +
'<div class="message-subject">' + subject.htmlEnc() + '</div>' + '<div class="message-subject">' + subject.htmlEnc() + '</div>' +
'<div class="message-truncated">' + Utils.truncate(Utils.noLines(content), 90).htmlEnc() + '</div>' + '<div class="message-truncated">' + Utils.truncate(Utils.noLines(content), 90).htmlEnc() + '</div>' +
'</div>' + '</div>' +
'</div>'; '</div>';
// Display the message // Display the message
if(nearest === 0) { if(nearest === 0) {
$(inbox + 'inbox-results .inbox').append(nContent); $(inbox + 'inbox-results .inbox').append(nContent);
} else { } else {
$('#inbox .one-message[data-stamp="' + nearest + '"]:first').before(nContent); $('#inbox .one-message[data-stamp="' + nearest + '"]:first').before(nContent);
} }
// Click events // Click events
$(one_message + ' .message-head').click(function() { $(one_message + ' .message-head').click(function() {
if(!Common.exists(one_message + ' .message-content')) if(!Common.exists(one_message + ' .message-content'))
self.revealMessage(id, from, subject, content, name, date, status); self.revealMessage(id, from, subject, content, name, date, status);
else else
self.hideMessage(id); self.hideMessage(id);
return false; return false;
}); });
// Get the user avatar // Get the user avatar
Avatar.get(from, 'cache', 'true', 'forget'); Avatar.get(from, 'cache', 'true', 'forget');
@ -484,11 +482,15 @@ 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);
} catch(e) { } catch(e) {
@ -504,18 +506,18 @@ 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
$('#inbox .one-message.' + id).remove(); $('#inbox .one-message.' + id).remove();
// Remove the message from the database // Remove the message from the database
DataStore.removeDB(Connection.desktop_hash, 'inbox', id); DataStore.removeDB(Connection.desktop_hash, 'inbox', id);
// Check the unread messages // Check the unread messages
self.checkMessages(); self.checkMessages();
// Store the new inbox // Store the new inbox
self.store(); self.store();
} catch(e) { } catch(e) {
@ -541,21 +543,21 @@ var Inbox = (function () {
for(var i = 0; i < DataStore.storageDB.length; i++) { for(var i = 0; i < DataStore.storageDB.length; i++) {
// Get the pointer values // Get the pointer values
var current = DataStore.storageDB.key(i); var current = DataStore.storageDB.key(i);
// If the pointer is on a stored message // If the pointer is on a stored message
if(current.match(db_regex)) { if(current.match(db_regex)) {
DataStore.removeDB(Connection.desktop_hash, 'inbox', RegExp.$1); DataStore.removeDB(Connection.desktop_hash, 'inbox', RegExp.$1);
} }
} }
// Prevent the database lag // Prevent the database lag
$(document).oneTime(100, function() { $(document).oneTime(100, function() {
// Store the new inbox // Store the new inbox
self.store(); self.store();
// Remove all the messages from the inbox // Remove all the messages from the inbox
$('#inbox .one-message').remove(); $('#inbox .one-message').remove();
// Reload the inbox // Reload the inbox
self.load(); self.load();
}); });
@ -579,56 +581,56 @@ var Inbox = (function () {
// Selectors // Selectors
var inbox_link = '#top-content a.inbox-hidable'; var inbox_link = '#top-content a.inbox-hidable';
var no_results = '#inbox .inbox-noresults'; var no_results = '#inbox .inbox-noresults';
// Marker // Marker
var has_messages = false; var has_messages = false;
// Read the number of unread messages // Read the number of unread messages
var unread = 0; var unread = 0;
// Read the local inbox database // Read the local inbox database
var db_regex = new RegExp(('^' + Connection.desktop_hash + '_') + 'inbox' + ('_(.+)')); var db_regex = new RegExp(('^' + Connection.desktop_hash + '_') + 'inbox' + ('_(.+)'));
for(var i = 0; i < DataStore.storageDB.length; i++) { for(var i = 0; i < DataStore.storageDB.length; i++) {
// Database pointer // Database pointer
var current = DataStore.storageDB.key(i); var current = DataStore.storageDB.key(i);
// Check inbox messages // Check inbox messages
if(current.match(db_regex)) { if(current.match(db_regex)) {
// Read the current status // Read the current status
var status = $(Common.XMLFromString(DataStore.storageDB.getItem(current))).find('status').text(); var status = $(Common.XMLFromString(DataStore.storageDB.getItem(current))).find('status').text();
// Found an unread message // Found an unread message
if(status == 'unread') { if(status == 'unread') {
unread++; unread++;
} }
// Update the marker // Update the marker
has_messages = true; has_messages = true;
} }
} }
// No message? // No message?
if(!has_messages) { if(!has_messages) {
$(no_results).show(); $(no_results).show();
} else { } else {
$(no_results).hide(); $(no_results).hide();
} }
// Reset notifications // Reset notifications
$(inbox_link + ' .notify').remove(); $(inbox_link + ' .notify').remove();
// Any unread message? // Any unread message?
if(unread) { if(unread) {
// Notify the user // Notify the user
$(inbox_link).prepend('<div class="notify one-counter" data-counter="' + unread + '">' + unread + '</div>'); $(inbox_link).prepend('<div class="notify one-counter" data-counter="' + unread + '">' + unread + '</div>');
// Update the title // Update the title
Interface.updateTitle(); Interface.updateTitle();
return true; return true;
} }
// Anyway, update the title // Anyway, update the title
Interface.updateTitle(); Interface.updateTitle();
} catch(e) { } catch(e) {
@ -659,53 +661,53 @@ var Inbox = (function () {
var all_message = '#inbox .one-message'; var all_message = '#inbox .one-message';
var one_message = all_message + '.' + id; var one_message = all_message + '.' + id;
var one_content = one_message + ' .message-content'; var one_content = one_message + ' .message-content';
// We reset all the other messages // We reset all the other messages
$(all_message + ' .message-content').remove(); $(all_message + ' .message-content').remove();
$(all_message).removeClass('message-reading'); $(all_message).removeClass('message-reading');
// Message content // Message content
var html = var html =
'<div class="message-content">' + '<div class="message-content">' +
'<div class="message-body">' + Filter.message(content, name, true) + '</div>' + '<div class="message-body">' + Filter.message(content, name, true) + '</div>' +
'<div class="message-meta">' + '<div class="message-meta">' +
'<span class="date">' + DateUtils.parse(date) + '</span>' + '<span class="date">' + DateUtils.parse(date) + '</span>' +
'<a href="#" class="reply one-button talk-images">' + Common._e("Reply") + '</a>' + '<a href="#" class="reply one-button talk-images">' + Common._e("Reply") + '</a>' +
'<a href="#" class="remove one-button talk-images">' + Common._e("Delete") + '</a>' + '<a href="#" class="remove one-button talk-images">' + Common._e("Delete") + '</a>' +
'<div class="clear">' + '<div class="clear">' +
'</div>' + '</div>' +
'</div>'; '</div>';
// Message content // Message content
html += '</div>'; html += '</div>';
$(one_message).append(html).addClass('message-reading'); $(one_message).append(html).addClass('message-reading');
// Click events // Click events
$(one_content + ' a.reply').click(function() { $(one_content + ' a.reply').click(function() {
return self.replyMessage(id, from, subject, content); return self.replyMessage(id, from, subject, content);
}); });
$(one_content + ' a.remove').click(function() { $(one_content + ' a.remove').click(function() {
return self.deleteMessage(id); return self.deleteMessage(id);
}); });
// Unread message // Unread message
if(status == 'unread') { if(status == 'unread') {
// Update our database // Update our database
var xml = DataStore.getDB(Connection.desktop_hash, 'inbox', id).replace(/<status>unread<\/status>/i,'<status>read</status>'); var xml = DataStore.getDB(Connection.desktop_hash, 'inbox', id).replace(/<status>unread<\/status>/i,'<status>read</status>');
DataStore.setDB(Connection.desktop_hash, 'inbox', id, xml); DataStore.setDB(Connection.desktop_hash, 'inbox', id, xml);
// Remove the unread class // Remove the unread class
$(one_message).removeClass('message-unread'); $(one_message).removeClass('message-unread');
// Send it to the server! // Send it to the server!
self.store(); self.store();
} }
// Check the unread messages // Check the unread messages
self.checkMessages(); self.checkMessages();
} catch(e) { } catch(e) {
@ -727,7 +729,7 @@ var Inbox = (function () {
// Define the paths // Define the paths
var inbox = '#inbox .'; var inbox = '#inbox .';
var one_message = inbox + 'one-message.' + id; var one_message = inbox + 'one-message.' + id;
// Reset this message // Reset this message
$(one_message).removeClass('message-reading'); $(one_message).removeClass('message-reading');
$(one_message + ' .message-content').remove(); $(one_message + ' .message-content').remove();
@ -749,17 +751,17 @@ var Inbox = (function () {
try { try {
// We switch to the writing div // We switch to the writing div
self.newMessage(); self.newMessage();
// Inbox path // Inbox path
var inbox = '#inbox .'; var inbox = '#inbox .';
// Generate the body // Generate the body
body = '\n' + '____________' + '\n\n' + Utils.truncate(body, 120); body = '\n' + '____________' + '\n\n' + Utils.truncate(body, 120);
// We apply the generated values to the form // We apply the generated values to the form
$(inbox + 'inbox-new-to-input').val(from); $(inbox + 'inbox-new-to-input').val(from);
$(inbox + 'inbox-new-subject-input').val(subject); $(inbox + 'inbox-new-subject-input').val(subject);
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
$(inbox + 'inbox-new-textarea').val(body).focus().selectRange(1, 0); $(inbox + 'inbox-new-textarea').val(body).focus().selectRange(1, 0);
}); });
@ -786,24 +788,24 @@ var Inbox = (function () {
for(var i = 0; i < DataStore.storageDB.length; i++) { for(var i = 0; i < DataStore.storageDB.length; i++) {
// Get the pointer values // Get the pointer values
var current = DataStore.storageDB.key(i); var current = DataStore.storageDB.key(i);
// If the pointer is on a stored message // If the pointer is on a stored message
if(current.match(db_regex)) { if(current.match(db_regex)) {
// Get the current value // Get the current value
var value = $(Common.XMLFromString(DataStore.storageDB.getItem(current))); var value = $(Common.XMLFromString(DataStore.storageDB.getItem(current)));
// Display the current message // Display the current message
self.displayMessage( self.displayMessage(
value.find('from').text().revertHtmlEnc(), value.find('from').text().revertHtmlEnc(),
value.find('subject').text().revertHtmlEnc(), value.find('subject').text().revertHtmlEnc(),
value.find('content').text().revertHtmlEnc(), value.find('content').text().revertHtmlEnc(),
value.find('status').text().revertHtmlEnc(), value.find('status').text().revertHtmlEnc(),
value.find('id').text().revertHtmlEnc(), value.find('id').text().revertHtmlEnc(),
value.find('date').text().revertHtmlEnc() value.find('date').text().revertHtmlEnc()
); );
} }
} }
// Check new messages // Check new messages
self.checkMessages(); self.checkMessages();
} catch(e) { } catch(e) {
@ -840,37 +842,51 @@ var Inbox = (function () {
try { try {
// Data selector // Data selector
var dData = $(responseXML).find('jappix'); var dData = $(responseXML).find('jappix');
// Process the returned data // Process the returned data
if(dData.find('error').size()) { if(dData.find('error').size()) {
Board.openThisError(4); Board.openThisError(4);
Console.error('Error while attaching the file', dData.find('error').text()); Console.error('Error while attaching the file', dData.find('error').text());
} else { } else {
// Get the file values // Get the file values
var fName = dData.find('title').text(); var fName = dData.find('title').text();
var fType = dData.find('type').text(); var fType = dData.find('type').text();
var fURL = dData.find('href').text(); var fURL = dData.find('href').text();
// 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;
}); });
Console.info('File attached.'); Console.info('File attached.');
} }
// Reset the attach bubble // Reset the attach bubble
$('#inbox .inbox-new-file input[type="file"]').val(''); $('#inbox .inbox-new-file input[type="file"]').val('');
$('#inbox .wait').hide(); $('#inbox .wait').hide();
@ -891,21 +907,22 @@ var Inbox = (function () {
try { try {
// Define the pats // Define the pats
var inbox = '#inbox .'; var inbox = '#inbox .';
// Define the buddy search vars // Define the buddy search vars
var destination = inbox + 'inbox-new-to'; var destination = inbox + 'inbox-new-to';
var dHovered = destination + ' ul li.hovered:first'; var dHovered = destination + ' ul li.hovered:first';
// 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
$(inbox + 'inbox-new-to-input').keyup(function(e) { $(inbox + 'inbox-new-to-input').keyup(function(e) {
if(e.keyCode != 13) { if(e.keyCode != 13) {
@ -913,61 +930,61 @@ var Inbox = (function () {
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);
} }
}) })
// Buddy search lost focus // Buddy search lost focus
.blur(function() { .blur(function() {
if(!$(destination + ' ul').attr('mouse-hover')) { if(!$(destination + ' ul').attr('mouse-hover')) {
Search.resetBuddy(destination); Search.resetBuddy(destination);
} }
}) })
// Buddy search got focus // Buddy search got focus
.focus(function() { .focus(function() {
var value = $(this).val(); var value = $(this).val();
// Add a comma at the end // Add a comma at the end
if(value && !value.match(/^(.+)((,)(\s)?)$/)) { if(value && !value.match(/^(.+)((,)(\s)?)$/)) {
$(this).val(value + ', '); $(this).val(value + ', ');
} }
}); });
// Click events // Click events
$(inbox + 'a-delete-messages').click(self.purge); $(inbox + 'a-delete-messages').click(self.purge);
$(inbox + 'a-new-message').click(self.newMessage); $(inbox + 'a-new-message').click(self.newMessage);
$(inbox + 'a-show-messages').click(self.showMessage); $(inbox + 'a-show-messages').click(self.showMessage);
$(inbox + 'inbox-new-send a').click(self.checkMessage); $(inbox + 'inbox-new-send a').click(self.checkMessage);
$(inbox + 'bottom .finish').click(function() { $(inbox + 'bottom .finish').click(function() {
return self.close(); return self.close();
}); });
// File upload // File upload
var attach_options = { var attach_options = {
dataType: 'xml', dataType: 'xml',
beforeSubmit: self.waitAttach, beforeSubmit: self.waitAttach,
success: self.handleAttach success: self.handleAttach
}; };
// Upload form submit event // Upload form submit event
$('#inbox .inbox-new-file').submit(function() { $('#inbox .inbox-new-file').submit(function() {
if($('#inbox .wait').is(':hidden') && $('#inbox .inbox-new-file input[type="file"]').val()) { if($('#inbox .wait').is(':hidden') && $('#inbox .inbox-new-file input[type="file"]').val()) {
$(this).ajaxSubmit(attach_options); $(this).ajaxSubmit(attach_options);
} }
return false; return false;
}); });
// Upload input change event // Upload input change event
$('#inbox .inbox-new-file input[type="file"]').change(function() { $('#inbox .inbox-new-file input[type="file"]').change(function() {
if($('#inbox .wait').is(':hidden') && $(this).val()) { if($('#inbox .wait').is(':hidden') && $(this).val()) {
$('#inbox .inbox-new-file').ajaxSubmit(attach_options); $('#inbox .inbox-new-file').ajaxSubmit(attach_options);
} }
return false; return false;
}); });
} catch(e) { } catch(e) {

View file

@ -29,22 +29,22 @@ var IntegrateBox = (function () {
try { try {
// Popup HTML content // Popup HTML content
var html = var html =
'<div class="top">' + Common._e("Media viewer") + '</div>' + '<div class="top">' + Common._e("Media viewer") + '</div>' +
'<div class="content"></div>' + '<div class="content"></div>' +
'<div class="bottom">' + '<div class="bottom">' +
'<div class="wait wait-medium"></div>' + '<div class="wait wait-medium"></div>' +
'<a href="#" class="finish close">' + Common._e("Close") + '</a>' + '<a href="#" class="finish close">' + Common._e("Close") + '</a>' +
'<a href="#" class="finish next disabled" title="' + Common._e("Next") + '">&gt;</a>' + '<a href="#" class="finish next disabled" title="' + Common._e("Next") + '">&gt;</a>' +
'<a href="#" class="finish previous disabled" title="' + Common._e("Previous") + '">&lt;</a>' + '<a href="#" class="finish previous disabled" title="' + Common._e("Previous") + '">&lt;</a>' +
'</div>'; '</div>';
// Create the popup // Create the popup
Popup.create('integratebox', html); Popup.create('integratebox', html);
// Associate the events // Associate the events
self.instance(); self.instance();
} catch(e) { } catch(e) {
@ -84,17 +84,17 @@ var IntegrateBox = (function () {
try { try {
var code = ''; var code = '';
// Protocol to use // Protocol to use
var protocol = Utils.isHTTPS() ? 'https' : 'http'; var protocol = Utils.isHTTPS() ? 'https' : 'http';
// Legacy browser // Legacy browser
var legacy = false; var legacy = false;
if((BrowserDetect.browser == 'Explorer') && (BrowserDetect.version < 9)) { if((BrowserDetect.browser == 'Explorer') && (BrowserDetect.version < 9)) {
legacy = true; legacy = true;
} }
// Switch to get the good DOM code // Switch to get the good DOM code
switch(serv) { switch(serv) {
case 'youtube': case 'youtube':
@ -103,37 +103,37 @@ var IntegrateBox = (function () {
} else { } else {
code = '<object width="640" height="385" data="' + Common.encodeQuotes(protocol) + '://www.youtube.com/embed/' + Common.encodeQuotes(url) + '?autoplay=1" type="text/html"><a href="http://www.youtube.com/watch?v=' + Common.encodeQuotes(url) + '" target="_blank">http://www.youtube.com/watch?v=' + Common.encodeQuotes(url) + '</a></object>'; code = '<object width="640" height="385" data="' + Common.encodeQuotes(protocol) + '://www.youtube.com/embed/' + Common.encodeQuotes(url) + '?autoplay=1" type="text/html"><a href="http://www.youtube.com/watch?v=' + Common.encodeQuotes(url) + '" target="_blank">http://www.youtube.com/watch?v=' + Common.encodeQuotes(url) + '</a></object>';
} }
break; break;
case 'dailymotion': case 'dailymotion':
code = '<object width="640" height="385"><param name="movie" value="http://www.dailymotion.com/swf/video/' + url + '&amp;autoplay=1"></param><param name="allowFullScreen" value="false"></param><embed type="application/x-shockwave-flash" src="http://www.dailymotion.com/swf/video/' + Common.encodeQuotes(url) + '&amp;autoplay=1" width="640" height="385" allowfullscreen="true" allowscriptaccess="always"></embed></object>'; code = '<object width="640" height="385"><param name="movie" value="http://www.dailymotion.com/swf/video/' + url + '&amp;autoplay=1"></param><param name="allowFullScreen" value="false"></param><embed type="application/x-shockwave-flash" src="http://www.dailymotion.com/swf/video/' + Common.encodeQuotes(url) + '&amp;autoplay=1" width="640" height="385" allowfullscreen="true" allowscriptaccess="always"></embed></object>';
break; break;
case 'vimeo': case 'vimeo':
code = '<object width="640" height="385"><param name="allowfullscreen" value="true" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=' + Common.encodeQuotes(url) + '&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1&amp;autoplay=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=' + Common.encodeQuotes(url) + '&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1&amp;autoplay=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="640" height="385"></embed></object>'; code = '<object width="640" height="385"><param name="allowfullscreen" value="true" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=' + Common.encodeQuotes(url) + '&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1&amp;autoplay=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=' + Common.encodeQuotes(url) + '&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1&amp;autoplay=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="640" height="385"></embed></object>';
break; break;
case 'theora': case 'theora':
case 'video': case 'video':
code = '<video width="640" height="385" src="' + Common.encodeQuotes(url) + '" controls autoplay><a href="' + Common.encodeQuotes(url) + '" target="_blank">' + Common.encodeQuotes(url) + '</a></video>'; code = '<video width="640" height="385" src="' + Common.encodeQuotes(url) + '" controls autoplay><a href="' + Common.encodeQuotes(url) + '" target="_blank">' + Common.encodeQuotes(url) + '</a></video>';
break; break;
case 'vorbis': case 'vorbis':
case 'audio': case 'audio':
code = '<audio src="' + Common.encodeQuotes(url) + '" controls autoplay><a href="' + Common.encodeQuotes(url) + '" target="_blank">' + Common.encodeQuotes(url) + '</a></audio>'; code = '<audio src="' + Common.encodeQuotes(url) + '" controls autoplay><a href="' + Common.encodeQuotes(url) + '" target="_blank">' + Common.encodeQuotes(url) + '</a></audio>';
break; break;
case 'image': case 'image':
code = '<a href="' + Common.encodeQuotes(url) + '" target="_blank"><img alt="" src="' + Common.encodeQuotes(url) + '" /></a>'; code = '<a href="' + Common.encodeQuotes(url) + '" target="_blank"><img alt="" src="' + Common.encodeQuotes(url) + '" /></a>';
break; break;
} }
return code; return code;
} catch(e) { } catch(e) {
Console.error('IntegrateBox.code', e); Console.error('IntegrateBox.code', e);
@ -159,64 +159,65 @@ var IntegrateBox = (function () {
try { try {
// Close the integratebox // Close the integratebox
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);
// Any code: apply it! // Any code: apply it!
if(dom_code) { if(dom_code) {
// We show the integratebox // We show the integratebox
self.open(); self.open();
// We add the code to the DOM // We add the code to the DOM
$('#integratebox .content').prepend('<div class="one-media">' + dom_code + '</div>'); $('#integratebox .content').prepend('<div class="one-media">' + dom_code + '</div>');
// Image waiting icon // Image waiting icon
if(service == 'image') { if(service == 'image') {
var waitItem = $('#integratebox .wait'); var waitItem = $('#integratebox .wait');
// Show it while it is loading // Show it while it is loading
waitItem.show(); waitItem.show();
// Hide it when it is loaded // Hide it when it is loaded
$('#integratebox img').load(function() { $('#integratebox img').load(function() {
waitItem.hide(); waitItem.hide();
// Center the image vertically // Center the image vertically
$(this).oneTime(10, function() { $(this).oneTime(10, function() {
$(this).css('margin-top', (($('#integratebox .content').height() - $(this).height()) / 2)); $(this).css('margin-top', (($('#integratebox .content').height() - $(this).height()) / 2));
}); });
}); });
} }
// Large style? // Large style?
var comments_id = genID(); var comments_id = genID();
if(width_style == 'large') { if(width_style == 'large') {
// Make the popup large // Make the popup large
$('#integratebox .popup').addClass('large'); $('#integratebox .popup').addClass('large');
// Add the right content // Add the right content
$('#integratebox .content').after( $('#integratebox .content').after(
'<div class="comments" data-id="' + Common.encodeQuotes(comments_id) + '">' + '<div class="comments" data-id="' + Common.encodeQuotes(comments_id) + '">' +
'<div class="comments-content">' + '<div class="comments-content">' +
'<div class="one-comment loading"><span class="icon talk-images"></span>' + Common._e("Loading comments...") + '</div>' + '<div class="one-comment loading"><span class="icon talk-images"></span>' + Common._e("Loading comments...") + '</div>' +
'</div>' + '</div>' +
'</div>' '</div>'
); );
} }
// Previous and next items? // Previous and next items?
var url_array = Utils.stringToArray(url_list); var url_array = Utils.stringToArray(url_list);
var services_array = Utils.stringToArray(services_list); var services_array = Utils.stringToArray(services_list);
var comments_e_array = Utils.stringToArray(comments_e_list); var comments_e_array = Utils.stringToArray(comments_e_list);
var comments_n_array = Utils.stringToArray(comments_n_list); var comments_n_array = Utils.stringToArray(comments_n_list);
var index = Utils.indexArrayValue(url_array, url); var index = Utils.indexArrayValue(url_array, url);
// Any comments? // Any comments?
if(Common.exists('#integratebox .comments')) { if(Common.exists('#integratebox .comments')) {
if(comments_e_array[index] && comments_n_array[index]) { if(comments_e_array[index] && comments_n_array[index]) {
@ -225,57 +226,57 @@ var IntegrateBox = (function () {
$('#integratebox .comments .comments-content').html('<div class="one-comment loading"><span class="icon talk-images"></span>' + Common._e("Comments locked!") + '</div>'); $('#integratebox .comments .comments-content').html('<div class="one-comment loading"><span class="icon talk-images"></span>' + Common._e("Comments locked!") + '</div>');
} }
} }
// Get the previous values // Get the previous values
var previous_url = url_array[index - 1]; var previous_url = url_array[index - 1];
var previous_services = services_array[index - 1]; var previous_services = services_array[index - 1];
// Get the next values // Get the next values
var next_url = url_array[index + 1]; var next_url = url_array[index + 1];
var next_services = services_array[index + 1]; var next_services = services_array[index + 1];
// Enable/disable buttons // Enable/disable buttons
if(previous_url && previous_services) { if(previous_url && previous_services) {
$('#integratebox .bottom .finish.previous').removeClass('disabled'); $('#integratebox .bottom .finish.previous').removeClass('disabled');
} else { } else {
$('#integratebox .bottom .finish.previous').addClass('disabled'); $('#integratebox .bottom .finish.previous').addClass('disabled');
} }
if(next_url && next_services) { if(next_url && next_services) {
$('#integratebox .bottom .finish.next').removeClass('disabled'); $('#integratebox .bottom .finish.next').removeClass('disabled');
} else { } else {
$('#integratebox .bottom .finish.next').addClass('disabled'); $('#integratebox .bottom .finish.next').addClass('disabled');
} }
// Click events // Click events
$('#integratebox .bottom .finish.previous, #integratebox .bottom .finish.next').click(function() { $('#integratebox .bottom .finish.previous, #integratebox .bottom .finish.next').click(function() {
// Not acceptable? // Not acceptable?
if($(this).is('.disabled')) { if($(this).is('.disabled')) {
return false; return false;
} }
// Apply the event! // Apply the event!
if($(this).is('.previous')) { if($(this).is('.previous')) {
self.apply(previous_url, previous_services, url_list, services_list, comments_e_list, comments_n_list, width_style); self.apply(previous_url, previous_services, url_list, services_list, comments_e_list, comments_n_list, width_style);
} else { } else {
self.apply(next_url, next_services, url_list, services_list, comments_e_list, comments_n_list, width_style); self.apply(next_url, next_services, url_list, services_list, comments_e_list, comments_n_list, width_style);
} }
return false; return false;
}); });
if(width_style == 'large') if(width_style == 'large')
$('#integratebox .content a:has(img)').click(function() { $('#integratebox .content a:has(img)').click(function() {
if(next_url && next_services) { if(next_url && next_services) {
self.apply(next_url, next_services, url_list, services_list, comments_e_list, comments_n_list, width_style); self.apply(next_url, next_services, url_list, services_list, comments_e_list, comments_n_list, width_style);
} }
return false; return false;
}); });
return false; return false;
} }
// Nothing: return true to be able to open the URL in a new tab // Nothing: return true to be able to open the URL in a new tab
return true; return true;
} catch(e) { } catch(e) {
@ -320,90 +321,90 @@ var IntegrateBox = (function () {
try { try {
// Encapsulates the string into two <div /> elements // Encapsulates the string into two <div /> elements
var xml = $('<div><div>' + data + '</div></div>').contents(); var xml = $('<div><div>' + data + '</div></div>').contents();
// Loop the <a /> elements // Loop the <a /> elements
$(xml).find('a').each(function() { $(xml).find('a').each(function() {
// Initialize this element // Initialize this element
var href = $(this).attr('href'); var href = $(this).attr('href');
var to, url, service, event; var to, url, service, event;
// XMPP ID // XMPP ID
if(href.match(/^xmpp:(.+)/i)) { if(href.match(/^xmpp:(.+)/i)) {
to = RegExp.$1; to = RegExp.$1;
} }
// YouTube video box // YouTube video box
else if(href.match(/(\w{3,5})(:)(\S+)((\.youtube\.com\/watch(\?v|\?\S+v|\#\!v|\#\!\S+v)\=)|(youtu\.be\/))([^& ]+)((&amp;\S)|(&\S)|\s|$)/gim)) { else if(href.match(/(\w{3,5})(:)(\S+)((\.youtube\.com\/watch(\?v|\?\S+v|\#\!v|\#\!\S+v)\=)|(youtu\.be\/))([^& ]+)((&amp;\S)|(&\S)|\s|$)/gim)) {
url = RegExp.$8; url = RegExp.$8;
service = 'youtube'; service = 'youtube';
} }
// Dailymotion video box // Dailymotion video box
else if(href.match(/(\w{3,5})(:)(\S+)\.dailymotion\.com\/video\/([\w\-]+)((\#[\w\-]+)|\s|$)/gim)) { else if(href.match(/(\w{3,5})(:)(\S+)\.dailymotion\.com\/video\/([\w\-]+)((\#[\w\-]+)|\s|$)/gim)) {
url = RegExp.$4; url = RegExp.$4;
service = 'dailymotion'; service = 'dailymotion';
} }
// Vimeo video box // Vimeo video box
else if(href.match(/((\w{3,5})(:)(\S+)(vimeo|www\.vimeo)\.com\/([\w\-]+))/gim)) { else if(href.match(/((\w{3,5})(:)(\S+)(vimeo|www\.vimeo)\.com\/([\w\-]+))/gim)) {
url = RegExp.$6; url = RegExp.$6;
service = 'vimeo'; service = 'vimeo';
} }
// Theora video box // Theora video box
else if(href.match(/((\w{3,5})(:)(\S+)(\.)(ogv|ogg))/gim)) { else if(href.match(/((\w{3,5})(:)(\S+)(\.)(ogv|ogg))/gim)) {
url = RegExp.$1; url = RegExp.$1;
service = 'theora'; service = 'theora';
} }
// Vorbis audio box // Vorbis audio box
else if(href.match(/((\w{3,5})(:)(\S+)(\.oga))/gim)) { else if(href.match(/((\w{3,5})(:)(\S+)(\.oga))/gim)) {
url = RegExp.$1; url = RegExp.$1;
service = 'vorbis'; service = 'vorbis';
} }
// Image box // Image box
else if(href.match(/((\w{3,5})(:)(\S+)(\.)(jpg|jpeg|png|gif|tif|bmp))/gim)) { else if(href.match(/((\w{3,5})(:)(\S+)(\.)(jpg|jpeg|png|gif|tif|bmp))/gim)) {
url = RegExp.$1; url = RegExp.$1;
service = 'image'; service = 'image';
} }
// Define the good event // Define the good event
if(to) { if(to) {
event = 'XMPPLinks.go(\'' + Utils.encodeOnclick(to) + '\')'; event = 'XMPPLinks.go(\'' + Utils.encodeOnclick(to) + '\')';
} else if(url && service) { } else if(url && service) {
event = 'IntegrateBox.apply(\'' + Utils.encodeOnclick(url) + '\', \'' + Utils.encodeOnclick(service) + '\')'; event = 'IntegrateBox.apply(\'' + Utils.encodeOnclick(url) + '\', \'' + Utils.encodeOnclick(service) + '\')';
} }
// Any click event to apply? // Any click event to apply?
if(event) { if(event) {
// Regenerate the link element (for onclick) // Regenerate the link element (for onclick)
var new_a = '<a'; var new_a = '<a';
var element_a = (this); var element_a = (this);
// Attributes // Attributes
$(element_a.attributes).each(function(index) { $(element_a.attributes).each(function(index) {
// Read the current attribute // Read the current attribute
var current_attr = element_a.attributes[index]; var current_attr = element_a.attributes[index];
// Apply the current attribute // Apply the current attribute
new_a += ' ' + Common.encodeQuotes(current_attr.name) + '="' + Common.encodeQuotes(current_attr.value) + '"'; new_a += ' ' + Common.encodeQuotes(current_attr.name) + '="' + Common.encodeQuotes(current_attr.value) + '"';
}); });
// Add onclick attribute // Add onclick attribute
new_a += ' onclick="return ' + event + ';"'; new_a += ' onclick="return ' + event + ';"';
// Value // Value
new_a += '>' + $(this).html() + '</a>'; new_a += '>' + $(this).html() + '</a>';
// Replace it! // Replace it!
$(this).replaceWith(new_a); $(this).replaceWith(new_a);
} }
}); });
// Regenerate the HTML code (include string into a div to be readable) // Regenerate the HTML code (include string into a div to be readable)
var string = $(xml).html(); var string = $(xml).html();
return string; return string;
} catch(e) { } catch(e) {
Console.error('IntegrateBox.filter', e); Console.error('IntegrateBox.filter', e);
@ -441,14 +442,14 @@ var IntegrateBox = (function () {
// Previous item? // Previous item?
if((Common.exists('#integratebox .bottom .finish.previous:not(.disabled)')) && (e.keyCode == 37)) { if((Common.exists('#integratebox .bottom .finish.previous:not(.disabled)')) && (e.keyCode == 37)) {
$('#integratebox .bottom .finish.previous').click(); $('#integratebox .bottom .finish.previous').click();
return false; return false;
} }
// Next item? // Next item?
if((Common.exists('#integratebox .bottom .finish.next:not(.disabled)')) && (e.keyCode == 39)) { if((Common.exists('#integratebox .bottom .finish.next:not(.disabled)')) && (e.keyCode == 39)) {
$('#integratebox .bottom .finish.next').click(); $('#integratebox .bottom .finish.next').click();
return false; return false;
} }
}); });

View file

@ -35,25 +35,25 @@ var Interface = (function () {
try { try {
// Anonymous mode? // Anonymous mode?
var head_name = Name.get(); var head_name = Name.get();
if(Utils.isAnonymous()) { if(Utils.isAnonymous()) {
head_name = ANONYMOUS_ROOM + ' (' + Common._e("anonymous mode") + ')'; head_name = ANONYMOUS_ROOM + ' (' + Common._e("anonymous mode") + ')';
} }
// We change the title to give essential informations // We change the title to give essential informations
switch(title_type) { switch(title_type) {
case 'home': case 'home':
document.title = SERVICE_NAME + ' • ' + SERVICE_DESC; document.title = SERVICE_NAME + ' • ' + SERVICE_DESC;
break; break;
case 'talk': case 'talk':
document.title = SERVICE_NAME + ' • ' + head_name; document.title = SERVICE_NAME + ' • ' + head_name;
break; break;
case 'new': case 'new':
document.title = '[' + self.pendingEvents() + '] ' + SERVICE_NAME + ' • ' + head_name; document.title = '[' + self.pendingEvents() + '] ' + SERVICE_NAME + ' • ' + head_name;
break; break;
case 'wait': case 'wait':
document.title = SERVICE_NAME + ' • ' + Common._e("Please wait..."); document.title = SERVICE_NAME + ' • ' + Common._e("Please wait...");
break; break;
@ -74,18 +74,19 @@ 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 =
'<div id="general-wait" class="removable">' + '<div id="general-wait" class="removable">' +
'<div class="general-wait-content wait-big"></div>' + '<div class="general-wait-content wait-big"></div>' +
'</div>'; '</div>';
// Append the HTML code // Append the HTML code
$('body').append(html); $('body').append(html);
return true; return true;
} catch(e) { } catch(e) {
Console.error('Interface.showGeneralWait', e); Console.error('Interface.showGeneralWait', e);
@ -118,11 +119,11 @@ var Interface = (function () {
self.generateFileShare = function() { self.generateFileShare = function() {
try { try {
return '<input type="hidden" name="MAX_FILE_SIZE" value="' + Common.encodeQuotes(JAPPIX_MAX_FILE_SIZE) + '">' + return '<input type="hidden" name="MAX_FILE_SIZE" value="' + Common.encodeQuotes(JAPPIX_MAX_FILE_SIZE) + '">' +
'<input type="hidden" name="user" value="' + Common.encodeQuotes(Common.getXID()) + '" />' + '<input type="hidden" name="user" value="' + Common.encodeQuotes(Common.getXID()) + '" />' +
'<input type="hidden" name="location" value="' + Common.encodeQuotes(Utils.generateURL(JAPPIX_LOCATION)) + '" />' + '<input type="hidden" name="location" value="' + Common.encodeQuotes(Utils.generateURL(JAPPIX_LOCATION)) + '" />' +
'<input type="hidden" name="id" value="' + (new Date()).getTime() + '" />' + '<input type="hidden" name="id" value="' + (new Date()).getTime() + '" />' +
'<input type="file" name="file" required="" />' + '<input type="file" name="file" required="" />' +
'<input type="submit" value="' + Common._e("Send") + '" />'; '<input type="submit" value="' + Common._e("Send") + '" />';
} catch(e) { } catch(e) {
Console.error('Interface.generateFileShare', e); Console.error('Interface.generateFileShare', e);
@ -144,16 +145,16 @@ var Interface = (function () {
// We show the page-engine content // We show the page-engine content
$('.page-engine-chan').hide(); $('.page-engine-chan').hide();
$('#' + id).show(); $('#' + id).show();
// We edit the tab switcher // We edit the tab switcher
$('#page-switch .switcher').removeClass('activechan').addClass('chan'); $('#page-switch .switcher').removeClass('activechan').addClass('chan');
$('#page-switch .' + id).addClass('activechan').removeClass('chan'); $('#page-switch .' + id).addClass('activechan').removeClass('chan');
// Scroll down to the last message // Scroll down to the last message
if(id != 'channel') { if(id != 'channel') {
self.autoScroll(id); self.autoScroll(id);
} }
// Manage input focus // Manage input focus
self.inputFocus(); self.inputFocus();
} }
@ -176,18 +177,19 @@ var Interface = (function () {
try { try {
// Path // Path
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);
// Append the content // Append the content
$('#page-switch .more').append( $('#page-switch .more').append(
'<div class="more-content bubble removable">' + '<div class="more-content bubble removable">' +
$('#page-switch .chans').html() + $('#page-switch .chans').html() +
'</div>' '</div>'
); );
} catch(e) { } catch(e) {
@ -210,18 +212,18 @@ var Interface = (function () {
// Path // Path
var join_content = '#page-switch .join-content'; var join_content = '#page-switch .join-content';
var join_sel = $('#page-switch .join'); var join_sel = $('#page-switch .join');
// Yet displayed? // Yet displayed?
if(Common.exists(join_content)) if(Common.exists(join_content))
return Bubble.close(); return Bubble.close();
// Add the bubble // Add the bubble
Bubble.show(join_content); Bubble.show(join_content);
// Append the content // Append the content
join_sel.append( join_sel.append(
'<div class="join-content bubble removable">' + '<div class="join-content bubble removable">' +
'<input type="text" class="join-groupchat-xid" required="" placeholder="' + Common._e("Groupchat name") + '" />' + '<input type="text" class="join-groupchat-xid" required="" placeholder="' + Common._e("Groupchat name") + '" />' +
'</div>' '</div>'
); );
@ -232,11 +234,11 @@ var Interface = (function () {
if(e.keyCode == 13) { if(e.keyCode == 13) {
var this_sel = $(this); var this_sel = $(this);
var xid = $.trim(this_sel.val()); var xid = $.trim(this_sel.val());
if(xid) { if(xid) {
// Generate a correct XID // Generate a correct XID
xid = Common.generateXID(xid, 'groupchat'); xid = Common.generateXID(xid, 'groupchat');
Bubble.close(); Bubble.close();
Chat.checkCreate(xid, 'groupchat'); Chat.checkCreate(xid, 'groupchat');
} else { } else {
@ -272,14 +274,14 @@ var Interface = (function () {
// We define the variables // We define the variables
var selector = $('#' + hash + ' .message-area'); var selector = $('#' + hash + ' .message-area');
var oValue = selector.val(); var oValue = selector.val();
// Any old value? // Any old value?
if(oValue && !oValue.match(/^(.+)(\s)+$/)) { if(oValue && !oValue.match(/^(.+)(\s)+$/)) {
oValue += ' '; oValue += ' ';
} }
var nValue = oValue + smiley + ' '; var nValue = oValue + smiley + ' ';
// Put the new value and focus on it // Put the new value and focus on it
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
selector.val(nValue).focus(); selector.val(nValue).focus();
@ -322,7 +324,7 @@ var Interface = (function () {
if(type == 'groupchat') { if(type == 'groupchat') {
// Send our unavailable presence // Send our unavailable presence
Presence.send(xid + '/' + Name.getMUCNick(hash), 'unavailable'); Presence.send(xid + '/' + Name.getMUCNick(hash), 'unavailable');
// Remove all presence database entries for this groupchat // Remove all presence database entries for this groupchat
var db_regex = new RegExp(('^' + Connection.desktop_hash + '_') + 'presence' + ('_(.+)')); var db_regex = new RegExp(('^' + Connection.desktop_hash + '_') + 'presence' + ('_(.+)'));
@ -332,15 +334,15 @@ var Interface = (function () {
if(current.match(db_regex)) { if(current.match(db_regex)) {
var cXID = RegExp.$1; var cXID = RegExp.$1;
// If the pointer is on a presence from this groupchat // If the pointer is on a presence from this groupchat
if(Common.bareXID(cXID) == xid) { if(Common.bareXID(cXID) == xid) {
// Generate the hash for the current XID // Generate the hash for the current XID
var cHash = hex_md5(cXID); var cHash = hex_md5(cXID);
// Disable the message textarea // Disable the message textarea
$('#' + cHash + ' .message-area').attr('disabled', true); $('#' + cHash + ' .message-area').attr('disabled', true);
// Remove the presence for this XID // Remove the presence for this XID
DataStore.removeDB(Connection.desktop_hash, 'presence-stanza', cXID); DataStore.removeDB(Connection.desktop_hash, 'presence-stanza', cXID);
DataStore.removeDB(Connection.desktop_hash, 'presence-resources', cXID); DataStore.removeDB(Connection.desktop_hash, 'presence-resources', cXID);
@ -356,18 +358,18 @@ var Interface = (function () {
if(xid in MAM.map_states) { if(xid in MAM.map_states) {
delete MAM.map_states[xid]; delete MAM.map_states[xid];
} }
// Get the chat ID which is before // Get the chat ID which is before
var previous = $('#' + hash).prev().attr('id'); var previous = $('#' + hash).prev().attr('id');
// Remove the chat // Remove the chat
self.deleteThisChat(hash); self.deleteThisChat(hash);
// Reset the switcher // Reset the switcher
if(!Common.exists('#page-switch .switcher.activechan')) { if(!Common.exists('#page-switch .switcher.activechan')) {
self.switchChan(previous); self.switchChan(previous);
} }
// Reset the notifications // Reset the notifications
self.chanCleanNotify(hash); self.chanCleanNotify(hash);
} catch(e) { } catch(e) {
@ -397,32 +399,48 @@ var Interface = (function () {
var date = DateUtils.getXMPPTime('local'); var date = DateUtils.getXMPPTime('local');
var type = $('#' + hash).attr('data-type'); var type = $('#' + hash).attr('data-type');
var direction = $('html').attr('dir') || 'ltr'; var direction = $('html').attr('dir') || 'ltr';
var content_sel = $(content);
// Filter the content smileys // Filter the content smileys
$(content).find('img.emoticon').each(function() { content_sel.find('img.emoticon').each(function() {
$(this).replaceWith($(this).attr('alt')); $(this).replaceWith($(this).attr('alt'));
}); });
// Remove the useless attributes // Remove the useless attributes
$(content).removeAttr('data-type').removeAttr('data-stamp'); content_sel.removeAttr('data-type').removeAttr('data-stamp');
// Remove the content avatars // Remove the content avatars
$(content).find('.avatar-container').remove(); content_sel.find('.avatar-container').remove();
// Remove the content info
content_sel.find('.correction-edit, .message-marker, .corrected-info, .correction-label').remove();
// Remove the content click events // Remove the content click events
$(content).find('a').removeAttr('onclick'); content_sel.find('a').removeAttr('onclick');
// Extract the content HTML code // Extract the content HTML code
content = $(content).parent().html(); content = content_sel.parent().html();
// No avatar? // No avatar?
if(!avatar || !avatar.match(/data:/)) if(!avatar || !avatar.match(/data:/)) {
avatar = 'none'; avatar = 'none';
}
// POST the values to the server // POST the values to the server
$.post('./server/generate-chat.php', { 'content': content, 'xid': xid, 'nick': nick, 'avatar': avatar, 'date': date, 'type': type, 'direction': direction }, function(data) { $.post('./server/generate-chat.php', {
'content': content,
'xid': xid,
'nick': nick,
'avatar': avatar,
'date': date,
'type': type,
'direction': direction
}, function(data) {
// Handled! // Handled!
$(path + 'tooltip-waitlog').replaceWith('<a class="tooltip-actionlog" href="./server/download-chat.php?id=' + data + '" target="_blank">' + Common._e("Download file!") + '</a>'); $(path + 'tooltip-waitlog').replaceWith(
'<a class="tooltip-actionlog" href="./server/download-chat.php?id=' + data + '" target="_blank">' + Common._e("Download file!") + '</a>'
);
}); });
} catch(e) { } catch(e) {
Console.error('Interface.generateChatLog', e); Console.error('Interface.generateChatLog', e);
@ -433,6 +451,31 @@ var Interface = (function () {
}; };
/**
* Returns whether chan has focus or not
* @public
* @param {string} hash
* @return {boolean}
*/
self.hasChanFocus = function(hash) {
var has_focus = true;
try {
if(!$('#page-switch .' + hash).hasClass('activechan') ||
!Common.isFocused() ||
(self.chat_focus_hash != hash)) {
has_focus = false;
}
} catch(e) {
Console.error('Interface.hasChanFocus', e);
} finally {
return has_focus;
}
};
/** /**
* Notifies the user from a new incoming message * Notifies the user from a new incoming message
* @public * @public
@ -447,9 +490,9 @@ var Interface = (function () {
var chat_switch = '#page-switch .'; var chat_switch = '#page-switch .';
var tested = chat_switch + hash; var tested = chat_switch + hash;
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');
@ -457,17 +500,17 @@ var Interface = (function () {
$(tested).addClass('chan-unread'); $(tested).addClass('chan-unread');
} }
} }
// Count the number of pending messages // Count the number of pending messages
var pending = 1; var pending = 1;
if(Common.exists('#' + hash + '[data-counter]')) { if(Common.exists('#' + hash + '[data-counter]')) {
pending = parseInt($('#' + hash).attr('data-counter')) + 1; pending = parseInt($('#' + hash).attr('data-counter')) + 1;
} }
$('#' + hash).attr('data-counter', pending); $('#' + hash).attr('data-counter', pending);
} }
// Update the page title // Update the page title
self.updateTitle(); self.updateTitle();
} catch(e) { } catch(e) {
@ -487,11 +530,11 @@ var Interface = (function () {
try { try {
// Count the number of notifications // Count the number of notifications
var number = 0; var number = 0;
$('.one-counter[data-counter]').each(function() { $('.one-counter[data-counter]').each(function() {
number = number + parseInt($(this).attr('data-counter')); number = number + parseInt($(this).attr('data-counter'));
}); });
return number; return number;
} catch(e) { } catch(e) {
Console.error('Interface.pendingEvents', e); Console.error('Interface.pendingEvents', e);
@ -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);
} }
@ -532,14 +576,15 @@ var Interface = (function () {
// We remove the class that tell the user of a new message // We remove the class that tell the user of a new message
var chat_switch = '#page-switch .'; var chat_switch = '#page-switch .';
$(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');
// Update the page title // Update the page title
self.updateTitle(); self.updateTitle();
} catch(e) { } catch(e) {
@ -561,7 +606,7 @@ var Interface = (function () {
// Avoid a JS error // Avoid a JS error
if(Common.exists('#' + hash)) { if(Common.exists('#' + hash)) {
var container = document.getElementById('chat-content-' + hash); var container = document.getElementById('chat-content-' + hash);
// Scroll down! // Scroll down!
container.scrollTop = container.scrollHeight; container.scrollTop = container.scrollHeight;
} }
@ -583,24 +628,25 @@ var Interface = (function () {
try { try {
// Put a marker // Put a marker
Roster.blist_all = true; Roster.blist_all = true;
// We switch the two modes // We switch the two modes
$('.buddy-conf-more-display-unavailable').hide(); $('.buddy-conf-more-display-unavailable').hide();
$('.buddy-conf-more-display-available').show(); $('.buddy-conf-more-display-available').show();
// Security: reset all the groups toggle event // Security: reset all the groups toggle event
$('#roster .group-buddies').show(); $('#roster .group-buddies').show();
$('#roster .group span').text('-'); $('#roster .group span').text('-');
// We show the disconnected buddies // We show the disconnected buddies
$('.hidden-buddy').show(); $('.hidden-buddy').show();
// 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()) {
DataStore.setDB(Connection.desktop_hash, 'options', 'roster-showall', '1'); DataStore.setDB(Connection.desktop_hash, 'options', 'roster-showall', '1');
@ -624,25 +670,25 @@ var Interface = (function () {
try { try {
// Remove the marker // Remove the marker
Roster.blist_all = false; Roster.blist_all = false;
// We switch the two modes // We switch the two modes
$('.buddy-conf-more-display-available').hide(); $('.buddy-conf-more-display-available').hide();
$('.buddy-conf-more-display-unavailable').show(); $('.buddy-conf-more-display-unavailable').show();
// Security: reset all the groups toggle event // Security: reset all the groups toggle event
$('#roster .group-buddies').show(); $('#roster .group-buddies').show();
$('#roster .group span').text('-'); $('#roster .group span').text('-');
// We hide the disconnected buddies // We hide the disconnected buddies
$('.hidden-buddy').hide(); $('.hidden-buddy').hide();
// We check the groups to hide // We check the groups to hide
Roster.updateGroups(); Roster.updateGroups();
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()) {
DataStore.setDB(Connection.desktop_hash, 'options', 'roster-showall', '0'); DataStore.setDB(Connection.desktop_hash, 'options', 'roster-showall', '0');
@ -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

@ -20,6 +20,352 @@ var IQ = (function () {
var self = {}; var self = {};
/**
* Handles OOB request
* @private
* @param {string} iqType
* @param {string} iqID
* @param {object} iqNode
* @return {undefined}
*/
self._handleOOBRequest = function(iqFrom, iqID, iqNode) {
try {
/* REF: http://xmpp.org/extensions/xep-0066.html */
OOB.handle(iqFrom, iqID, 'iq', iqNode);
Console.log('Received IQ OOB request: ' + iqFrom);
} catch(e) {
Console.error('IQ._handleOOBRequest', e);
}
};
/**
* Handles OOB reply
* @private
* @param {object} iqResponse
* @param {string} iqFrom
* @param {string} iqType
* @param {string} iqID
* @param {object} iqNode
* @return {undefined}
*/
self._handleOOBReply = function(iqResponse, iqFrom, iqType, iqID, iqNode) {
try {
// Get the values
var oob_url = DataStore.getDB(Connection.desktop_hash, 'send/url', iqID);
var oob_desc = DataStore.getDB(Connection.desktop_hash, 'send/desc', iqID);
var notif_id = hex_md5(oob_url + oob_desc + iqType + iqFrom + iqID);
if($(iqNode).find('error').size()) {
// Error?
if($(iqNode).find('error not-acceptable').size()) {
// Rejected?
Notification.create('send_reject', iqFrom, [iqFrom, oob_url, 'iq', iqID, iqNode], oob_desc, notif_id);
} else {
// Failed?
Notification.create('send_fail', iqFrom, [iqFrom, oob_url, 'iq', iqID, iqNode], oob_desc, notif_id);
}
// Remove the file
$.get(oob_url + '&action=remove');
} else if(iqType == 'result') {
// Success?
Notification.create('send_accept', iqFrom, [iqFrom, oob_url, 'iq', iqID, iqNode], oob_desc, notif_id);
}
} catch(e) {
Console.error('IQ._handleOOBReply', e);
}
};
/**
* Handles Software Version
* @private
* @param {object} iqResponse
* @param {string} iqFrom
* @return {undefined}
*/
self._handleSoftwareVersion = function(iqResponse, iqFrom) {
try {
/* REF: http://xmpp.org/extensions/xep-0092.html */
iqQuery = iqResponse.setQuery(NS_VERSION);
iqQuery.appendChild(iqResponse.buildNode('name', {'xmlns': NS_VERSION}, Caps.disco_infos.identity.name));
iqQuery.appendChild(iqResponse.buildNode('version', {'xmlns': NS_VERSION}, JAPPIX_VERSION));
iqQuery.appendChild(iqResponse.buildNode('os', {'xmlns': NS_VERSION}, BrowserDetect.OS));
con.send(iqResponse);
Console.log('Received software version query: ' + iqFrom);
} catch(e) {
Console.error('IQ._handleSoftwareVersion', e);
}
};
/**
* Handles Last Activity
* @private
* @param {object} iqResponse
* @param {string} iqFrom
* @return {undefined}
*/
self._handleLastActivity = function(iqResponse, iqFrom) {
try {
/* REF: http://xmpp.org/extensions/xep-0012.html */
iqQuery = iqResponse.setQuery(NS_LAST);
iqQuery.setAttribute('seconds', DateUtils.getLastActivity());
con.send(iqResponse);
Console.log('Received last activity query: ' + iqFrom);
} catch(e) {
Console.error('IQ._handleLastActivity', e);
}
};
/**
* Handles Privacy Lists
* @private
* @param {object} iqResponse
* @param {string} iqFrom
* @param {string} iqQuery
* @return {undefined}
*/
self._handlePrivacyLists = function(iqResponse, iqFrom, iqQuery) {
try {
// REF : http://xmpp.org/extensions/xep-0016.html
// Roster push
con.send(iqResponse);
// Get the lists
$(iqQuery).find('list').each(function() {
Privacy.get($(this).attr('name'));
});
Console.log('Received privacy lists push: ' + iqFrom);
} catch(e) {
Console.error('IQ._handlePrivacyLists', e);
}
};
/**
* Handles Roster Push
* @private
* @param {object} iqResponse
* @param {string} iqFrom
* @param {string} iqQuery
* @return {undefined}
*/
self._handleRosterPush = function(iqResponse, iqFrom, iqQuery) {
try {
// REF : http://xmpp.org/extensions/xep-0092.html
// Roster push
con.send(iqResponse);
// Get the values
$(iqQuery).find('item').each(function() {
Roster.parse($(this), 'presence');
});
Console.log('Received roster push: ' + iqFrom);
} catch(e) {
Console.error('IQ._handleRosterPush', e);
}
};
/**
* Handles Roster Item Exchange
* @private
* @param {object} iqNode
* @param {string} iqFrom
* @return {undefined}
*/
self._handleRosterItemExchange = function(iqNode, iqFrom) {
try {
// Open a new notification
Notification.create('rosterx', iqFrom, [iqNode], '');
Console.log('Roster Item Exchange from: ' + iqFrom);
} catch(e) {
Console.error('IQ._handleRosterItemExchange', e);
}
};
/**
* Handles Disco Info
* @private
* @param {object} iqResponse
* @param {string} iqFrom
* @return {undefined}
*/
self._handleDiscoInfo = function(iqResponse, iqFrom) {
try {
/* REF: http://xmpp.org/extensions/xep-0030.html */
iqQuery = iqResponse.setQuery(NS_DISCO_INFO);
// We set the name of the client
iqQuery.appendChild(iqResponse.buildNode('identity', {
'category': Caps.disco_infos.identity.category,
'type': Caps.disco_infos.identity.type,
'name': Caps.disco_infos.identity.name,
'xmlns': NS_DISCO_INFO
}));
// We set all the supported features
var disco_infos = Caps.myDiscoInfos();
$.each(disco_infos, function(i, disco_info) {
iqQuery.appendChild(iqResponse.buildNode('feature', {'var': disco_info, 'xmlns': NS_DISCO_INFO}));
});
con.send(iqResponse);
Console.log('Received disco#infos query: ' + iqFrom);
} catch(e) {
Console.error('IQ._handleDiscoInfo', e);
}
};
/**
* Handles User Time
* @private
* @param {object} iqResponse
* @param {string} iqFrom
* @return {undefined}
*/
self._handleUserTime = function(iqResponse, iqFrom) {
try {
/* REF: http://xmpp.org/extensions/xep-0202.html */
var iqTime = iqResponse.appendNode('time', {
'xmlns': NS_URN_TIME
});
iqTime.appendChild(iqResponse.buildNode('tzo', {
'xmlns': NS_URN_TIME
}, DateUtils.getTZO()));
iqTime.appendChild(iqResponse.buildNode('utc', {
'xmlns': NS_URN_TIME
}, DateUtils.getXMPPTime('utc')));
con.send(iqResponse);
Console.log('Received local time query: ' + iqFrom);
} catch(e) {
Console.error('IQ._handleUserTime', e);
}
};
/**
* Handles Ping
* @private
* @param {object} iqResponse
* @param {string} iqFrom
* @return {undefined}
*/
self._handlePing = function(iqResponse, iqFrom) {
try {
/* REF: http://xmpp.org/extensions/xep-0199.html */
con.send(iqResponse);
Console.log('Received a ping: ' + iqFrom);
} catch(e) {
Console.error('IQ._handlePing', e);
}
};
/**
* Handles Jingle
* @private
* @param {string} iqFrom
* @return {undefined}
*/
self._handleJingle = function(iqFrom) {
try {
/* REF: http://xmpp.org/extensions/xep-0166.html */
// Handled via JSJaCJingle.route() (see above)
Console.log('Received a Jingle packet: ' + iqFrom);
} catch(e) {
Console.error('IQ._handleJingle', e);
}
};
/**
* Raises a not implemented error
* @private
* @param {object} iqResponse
* @param {object} iqNode
* @param {string} iqFrom
* @return {undefined}
*/
self._raiseNotImplemented = function(iqResponse, iqNode, iqFrom) {
try {
// Change IQ type
iqResponse.setType('error');
// Append stanza content
for(var c = 0; c < iqNode.childNodes.length; c++) {
iqResponse.getNode().appendChild(iqNode.childNodes.item(c).cloneNode(true));
}
// Append error content
var iqError = iqResponse.appendNode('error', {'xmlns': NS_CLIENT, 'code': '501', 'type': 'cancel'});
iqError.appendChild(iqResponse.buildNode('feature-not-implemented', {'xmlns': NS_STANZAS}));
iqError.appendChild(iqResponse.buildNode('text', {'xmlns': NS_STANZAS}, Common._e("The feature requested is not implemented by the recipient or server and therefore cannot be processed.")));
con.send(iqResponse);
Console.log('Received an unsupported IQ query from: ' + iqFrom);
} catch(e) {
Console.error('IQ._raiseNotImplemented', e);
}
};
/** /**
* Handles an incoming IQ packet * Handles an incoming IQ packet
* @public * @public
@ -37,190 +383,71 @@ var IQ = (function () {
var iqQuery = iq.getQuery(); var iqQuery = iq.getQuery();
var iqType = iq.getType(); var iqType = iq.getType();
// Handle Jingle packet?
JSJaCJingle_route(iq);
// Build the response // Build the response
var iqResponse = new JSJaCIQ(); var iqResponse = new JSJaCIQ();
iqResponse.setID(iqID); iqResponse.setID(iqID);
iqResponse.setTo(iqFrom); iqResponse.setTo(iqFrom);
iqResponse.setType('result'); iqResponse.setType('result');
// OOB request // OOB request
if((iqQueryXMLNS == NS_IQOOB) && (iqType == 'set')) { if((iqQueryXMLNS == NS_IQOOB) && (iqType == 'set')) {
/* REF: http://xmpp.org/extensions/xep-0066.html */ self._handleOOBRequest(iqFrom, iqID, iqNode);
OOB.handle(iqFrom, iqID, 'iq', iqNode);
Console.log('Received IQ OOB request: ' + iqFrom);
} }
// OOB reply // OOB reply
else if(DataStore.getDB(Connection.desktop_hash, 'send/url', iqID)) { else if(DataStore.getDB(Connection.desktop_hash, 'send/url', iqID)) {
// Get the values self._handleOOBReply(iqResponse, iqFrom, iqType, iqID, iqNode);
var oob_url = DataStore.getDB(Connection.desktop_hash, 'send/url', iqID);
var oob_desc = DataStore.getDB(Connection.desktop_hash, 'send/desc', iqID);
var notif_id = hex_md5(oob_url + oob_desc + iqType + iqFrom + iqID);
if($(iqNode).find('error').size()) {
// Error?
if($(iqNode).find('error not-acceptable').size()) {
// Rejected?
Notification.create('send_reject', iqFrom, [iqFrom, oob_url, 'iq', iqID, iqNode], oob_desc, notif_id);
} else {
// Failed?
Notification.create('send_fail', iqFrom, [iqFrom, oob_url, 'iq', iqID, iqNode], oob_desc, notif_id);
}
// Remove the file
$.get(oob_url + '&action=remove');
} else if(iqType == 'result') {
// Success?
Notification.create('send_accept', iqFrom, [iqFrom, oob_url, 'iq', iqID, iqNode], oob_desc, notif_id);
}
} }
// Software version query // Software version query
else if((iqQueryXMLNS == NS_VERSION) && (iqType == 'get')) { else if((iqQueryXMLNS == NS_VERSION) && (iqType == 'get')) {
/* REF: http://xmpp.org/extensions/xep-0092.html */ self._handleSoftwareVersion(iqResponse, iqFrom);
iqQuery = iqResponse.setQuery(NS_VERSION);
iqQuery.appendChild(iqResponse.buildNode('name', {'xmlns': NS_VERSION}, 'Jappix'));
iqQuery.appendChild(iqResponse.buildNode('version', {'xmlns': NS_VERSION}, JAPPIX_VERSION));
iqQuery.appendChild(iqResponse.buildNode('os', {'xmlns': NS_VERSION}, BrowserDetect.OS));
con.send(iqResponse);
Console.log('Received software version query: ' + iqFrom);
} }
// Last activity query // Last activity query
else if((iqQueryXMLNS == NS_LAST) && (iqType == 'get')) { else if((iqQueryXMLNS == NS_LAST) && (iqType == 'get')) {
/* REF: http://xmpp.org/extensions/xep-0012.html */ self._handleLastActivity(iqResponse, iqFrom);
iqQuery = iqResponse.setQuery(NS_LAST);
iqQuery.setAttribute('seconds', DateUtils.getLastActivity());
con.send(iqResponse);
Console.log('Received last activity query: ' + iqFrom);
} }
// Privacy lists push // Privacy lists push
else if((iqQueryXMLNS == NS_PRIVACY) && (iqType == 'set') && Common.isSafeStanza(iq)) { else if((iqQueryXMLNS == NS_PRIVACY) && (iqType == 'set') && Common.isSafeStanza(iq)) {
// REF : http://xmpp.org/extensions/xep-0016.html self._handlePrivacyLists(iqResponse, iqFrom, iqQuery);
// Roster push
con.send(iqResponse);
// Get the lists
$(iqQuery).find('list').each(function() {
Privacy.get($(this).attr('name'));
});
Console.log('Received privacy lists push: ' + iqFrom);
} }
// Roster push // Roster push
else if((iqQueryXMLNS == NS_ROSTER) && (iqType == 'set') && Common.isSafeStanza(iq)) { else if((iqQueryXMLNS == NS_ROSTER) && (iqType == 'set') && Common.isSafeStanza(iq)) {
// REF : http://xmpp.org/extensions/xep-0092.html self._handleRosterPush(iqResponse, iqFrom, iqQuery);
// Roster push
con.send(iqResponse);
// Get the values
$(iqQuery).find('item').each(function() {
Roster.parse($(this), 'presence');
});
Console.log('Received roster push: ' + iqFrom);
} }
// Roster Item Exchange query // Roster Item Exchange query
else if($(iqNode).find('x[xmlns="' + NS_ROSTERX + '"]').size()) { else if($(iqNode).find('x[xmlns="' + NS_ROSTERX + '"]').size()) {
// Open a new notification self._handleRosterItemExchange(iqNode, iqFrom);
Notification.create('rosterx', iqFrom, [iqNode], '');
Console.log('Roster Item Exchange from: ' + iqFrom);
} }
// Disco info query // Disco info query
else if((iqQueryXMLNS == NS_DISCO_INFO) && (iqType == 'get')) { else if((iqQueryXMLNS == NS_DISCO_INFO) && (iqType == 'get')) {
/* REF: http://xmpp.org/extensions/xep-0030.html */ self._handleDiscoInfo(iqResponse, iqFrom);
iqQuery = iqResponse.setQuery(NS_DISCO_INFO);
// We set the name of the client
iqQuery.appendChild(iqResponse.buildNode('identity', {
'category': 'client',
'type': 'web',
'name': 'Jappix',
'xmlns': NS_DISCO_INFO
}));
// We set all the supported features
var disco_infos = Caps.myDiscoInfos();
$.each(disco_infos, function(i, disco_info) {
iqQuery.appendChild(iqResponse.buildNode('feature', {'var': disco_info, 'xmlns': NS_DISCO_INFO}));
});
con.send(iqResponse);
Console.log('Received disco#infos query: ' + iqFrom);
} }
// User time query // User time query
else if($(iqNode).find('time').size() && (iqType == 'get')) { else if($(iqNode).find('time').size() && (iqType == 'get')) {
/* REF: http://xmpp.org/extensions/xep-0202.html */ self._handleUserTime(iqResponse, iqFrom);
var iqTime = iqResponse.appendNode('time', {'xmlns': NS_URN_TIME});
iqTime.appendChild(iqResponse.buildNode('tzo', {'xmlns': NS_URN_TIME}, DateUtils.getTZO()));
iqTime.appendChild(iqResponse.buildNode('utc', {'xmlns': NS_URN_TIME}, DateUtils.getXMPPTime('utc')));
con.send(iqResponse);
Console.log('Received local time query: ' + iqFrom);
} }
// Ping // Ping
else if($(iqNode).find('ping').size() && (iqType == 'get')) { else if($(iqNode).find('ping').size() && (iqType == 'get')) {
/* REF: http://xmpp.org/extensions/xep-0199.html */ self._handlePing(iqResponse, iqFrom);
con.send(iqResponse);
Console.log('Received a ping: ' + iqFrom);
} }
// Jingle // Jingle
else if($(iqNode).find('jingle').size()) { else if($(iqNode).find('jingle').size()) {
/* REF: http://xmpp.org/extensions/xep-0166.html */ self._handleJingle(iqFrom);
// Handled via JSJaCJingle_route() (see above)
Console.log('Received a Jingle packet: ' + iqFrom);
} }
// Not implemented // Not implemented
else if(!$(iqNode).find('error').size() && ((iqType == 'get') || (iqType == 'set'))) { else if(!$(iqNode).find('error').size() && ((iqType == 'get') || (iqType == 'set'))) {
// Change IQ type self._raiseNotImplemented(iqResponse, iqNode, iqFrom);
iqResponse.setType('error');
// Append stanza content
for(var c = 0; c < iqNode.childNodes.length; c++) {
iqResponse.getNode().appendChild(iqNode.childNodes.item(c).cloneNode(true));
}
// Append error content
var iqError = iqResponse.appendNode('error', {'xmlns': NS_CLIENT, 'code': '501', 'type': 'cancel'});
iqError.appendChild(iqResponse.buildNode('feature-not-implemented', {'xmlns': NS_STANZAS}));
iqError.appendChild(iqResponse.buildNode('text', {'xmlns': NS_STANZAS}, Common._e("The feature requested is not implemented by the recipient or server and therefore cannot be processed.")));
con.send(iqResponse);
Console.log('Received an unsupported IQ query from: ' + iqFrom);
} }
} catch(e) { } catch(e) {
Console.error('IQ.handle', e); Console.error('IQ.handle', e);

File diff suppressed because it is too large Load diff

View file

@ -72,7 +72,7 @@ feature.formdata = window.FormData !== undefined;
var hasProp = !!$.fn.prop; var hasProp = !!$.fn.prop;
// attr2 uses prop when it can but checks the return type for // attr2 uses prop when it can but checks the return type for
// an expected string. this accounts for the case where a form // an expected string. this accounts for the case where a form
// contains inputs with names like "action" or "method"; in those // contains inputs with names like "action" or "method"; in those
// cases "prop" returns the element // cases "prop" returns the element
$.fn.attr2 = function() { $.fn.attr2 = function() {
@ -461,7 +461,7 @@ $.fn.ajaxSubmit = function(options) {
var CLIENT_TIMEOUT_ABORT = 1; var CLIENT_TIMEOUT_ABORT = 1;
var SERVER_ABORT = 2; var SERVER_ABORT = 2;
function getDoc(frame) { function getDoc(frame) {
/* it looks like contentWindow or contentDocument do not /* it looks like contentWindow or contentDocument do not
* carry the protocol property in ie8, when running under ssl * carry the protocol property in ie8, when running under ssl
@ -469,9 +469,9 @@ $.fn.ajaxSubmit = function(options) {
* the protocol is know but not on the other two objects. strange? * the protocol is know but not on the other two objects. strange?
* "Same origin policy" http://en.wikipedia.org/wiki/Same_origin_policy * "Same origin policy" http://en.wikipedia.org/wiki/Same_origin_policy
*/ */
var doc = null; var doc = null;
// IE8 cascading access check // IE8 cascading access check
try { try {
if (frame.contentWindow) { if (frame.contentWindow) {
@ -507,8 +507,8 @@ $.fn.ajaxSubmit = function(options) {
// take a breath so that pending repaints get some cpu time before the upload starts // take a breath so that pending repaints get some cpu time before the upload starts
function doSubmit() { function doSubmit() {
// make sure form attrs are set // make sure form attrs are set
var t = $form.attr2('target'), var t = $form.attr2('target'),
a = $form.attr2('action'), a = $form.attr2('action'),
mp = 'multipart/form-data', mp = 'multipart/form-data',
et = $form.attr('enctype') || $form.attr('encoding') || mp; et = $form.attr('enctype') || $form.attr('encoding') || mp;
@ -619,7 +619,7 @@ $.fn.ajaxSubmit = function(options) {
if (xhr.aborted || callbackProcessed) { if (xhr.aborted || callbackProcessed) {
return; return;
} }
doc = getDoc(io); doc = getDoc(io);
if(!doc) { if(!doc) {
log('cannot access response document'); log('cannot access response document');

File diff suppressed because it is too large Load diff

View file

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

File diff suppressed because it is too large Load diff

View file

@ -13,12 +13,12 @@ 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
*/ */
/** /**
@ -71,18 +68,18 @@ XmlHttp.create = function () {
// Able to use CORS? // Able to use CORS?
if (window.XMLHttpRequest) { if (window.XMLHttpRequest) {
var req = new XMLHttpRequest(); var req = new XMLHttpRequest();
if (req.withCredentials !== undefined) if (req.withCredentials !== undefined)
return req; return req;
} }
// Fallback on JSONP // Fallback on JSONP
return new jXHR(); return new jXHR();
} }
// Might be local-domain? // Might be local-domain?
if (window.XMLHttpRequest) { if (window.XMLHttpRequest) {
var req = new XMLHttpRequest(); var req = new XMLHttpRequest();
// some versions of Moz do not support the readyState property // some versions of Moz do not support the readyState property
// and the onreadystate event so we patch it! // and the onreadystate event so we patch it!
if (req.readyState == null) { if (req.readyState == null) {
@ -93,7 +90,7 @@ XmlHttp.create = function () {
req.onreadystatechange(); req.onreadystatechange();
}, false); }, false);
} }
return req; return req;
} }
if (window.ActiveXObject) { if (window.ActiveXObject) {
@ -112,7 +109,7 @@ XmlHttp.create = function () {
XmlHttp.getPrefix = function() { XmlHttp.getPrefix = function() {
if (XmlHttp.prefix) // I know what you did last summer if (XmlHttp.prefix) // I know what you did last summer
return XmlHttp.prefix; return XmlHttp.prefix;
var prefixes = ["MSXML2", "Microsoft", "MSXML", "MSXML3"]; var prefixes = ["MSXML2", "Microsoft", "MSXML", "MSXML3"];
var o; var o;
for (var i = 0; i < prefixes.length; i++) { for (var i = 0; i < prefixes.length; i++) {
@ -123,7 +120,7 @@ XmlHttp.getPrefix = function() {
} }
catch (ex) {}; catch (ex) {};
} }
throw new Error("Could not find an installed XML parser"); throw new Error("Could not find an installed XML parser");
}; };
@ -156,7 +153,7 @@ XmlDocument.create = function (name,ns) {
} else if (window.ActiveXObject) { } else if (window.ActiveXObject) {
doc = new ActiveXObject(XmlDocument.getPrefix() + ".DomDocument"); doc = new ActiveXObject(XmlDocument.getPrefix() + ".DomDocument");
} }
if (!doc.documentElement || doc.documentElement.tagName != name || if (!doc.documentElement || doc.documentElement.tagName != name ||
(doc.documentElement.namespaceURI && (doc.documentElement.namespaceURI &&
doc.documentElement.namespaceURI != ns)) { doc.documentElement.namespaceURI != ns)) {
@ -168,7 +165,7 @@ XmlDocument.create = function (name,ns) {
doc.appendChild(doc.createElement(name)); doc.appendChild(doc.createElement(name));
} catch (dex) { } catch (dex) {
doc = document.implementation.createDocument(ns,name,null); doc = document.implementation.createDocument(ns,name,null);
if (doc.documentElement == null) if (doc.documentElement == null)
doc.appendChild(doc.createElement(name)); doc.appendChild(doc.createElement(name));
@ -179,7 +176,7 @@ XmlDocument.create = function (name,ns) {
} }
} }
} }
return doc; return doc;
} }
catch (ex) { } catch (ex) { }
@ -204,7 +201,7 @@ XmlDocument.getPrefix = function() {
} }
catch (ex) {}; catch (ex) {};
} }
throw new Error("Could not find an installed XML parser"); throw new Error("Could not find an installed XML parser");
}; };
@ -218,14 +215,14 @@ if (typeof(Document) != 'undefined' && window.DOMParser) {
* @private * @private
*/ */
Document.prototype.loadXML = function (s) { Document.prototype.loadXML = function (s) {
// parse the string to a new doc // parse the string to a new doc
var doc2 = (new DOMParser()).parseFromString(s, "text/xml"); var doc2 = (new DOMParser()).parseFromString(s, "text/xml");
// remove all initial children // remove all initial children
while (this.hasChildNodes()) while (this.hasChildNodes())
this.removeChild(this.lastChild); this.removeChild(this.lastChild);
// insert and import nodes // insert and import nodes
for (var i = 0; i < doc2.childNodes.length; i++) { for (var i = 0; i < doc2.childNodes.length; i++) {
this.appendChild(this.importNode(doc2.childNodes[i], true)); this.appendChild(this.importNode(doc2.childNodes[i], true));
@ -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
*/ */
/** /**
@ -334,10 +331,10 @@ Date.jab2date = function(ts) {
// Timestamp // Timestamp
if(!isNaN(ts)) if(!isNaN(ts))
return new Date(ts * 1000); return new Date(ts * 1000);
// Get the UTC date // Get the UTC date
var date = new Date(Date.UTC(ts.substr(0,4),ts.substr(5,2)-1,ts.substr(8,2),ts.substr(11,2),ts.substr(14,2),ts.substr(17,2))); var date = new Date(Date.UTC(ts.substr(0,4),ts.substr(5,2)-1,ts.substr(8,2),ts.substr(11,2),ts.substr(14,2),ts.substr(17,2)));
if (ts.substr(ts.length-6,1) != 'Z') { // there's an offset if (ts.substr(ts.length-6,1) != 'Z') { // there's an offset
var date_offset = date.getTimezoneOffset() * 60 * 1000; var date_offset = date.getTimezoneOffset() * 60 * 1000;
var offset = new Date(); var offset = new Date();
@ -370,7 +367,7 @@ Date.hrTime = function(ts) {
if (!Date.now) { if (!Date.now) {
Date.now = function() { return new Date().getTime(); } Date.now = function() { return new Date().getTime(); }
} }
/** /**
* somewhat opposit to {@link #hrTime} * somewhat opposit to {@link #hrTime}
* expects a javascript Date object as parameter and returns a jabber * expects a javascript Date object as parameter and returns a jabber
@ -1088,7 +1085,7 @@ function utf8t2d(t)
} }
return d; return d;
} }
// returns plaintext from an array of bytesrepresenting dezimal numbers, which // returns plaintext from an array of bytesrepresenting dezimal numbers, which
// represent an UTF-8 encoded text; browser which does not understand unicode // represent an UTF-8 encoded text; browser which does not understand unicode
// like NN401 will show "?"-signs instead // like NN401 will show "?"-signs instead
@ -1206,7 +1203,7 @@ function cnonce(size) {
JSJAC_HAVEKEYS = true; // whether to use keys JSJAC_HAVEKEYS = true; // whether to use keys
JSJAC_NKEYS = 16; // number of keys to generate JSJAC_NKEYS = 16; // number of keys to generate
JSJAC_INACTIVITY = 300; // qnd hack to make suspend/resume JSJAC_INACTIVITY = 300; // qnd hack to make suspend/resume
// work more smoothly with polling // work more smoothly with polling
JSJAC_ERR_COUNT = 10; // number of retries in case of connection JSJAC_ERR_COUNT = 10; // number of retries in case of connection
// errors // errors
@ -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
@ -1293,7 +1290,7 @@ JSJaCJSON.toString = function (obj) {
a[a.length] = v; a[a.length] = v;
b = true; b = true;
} }
} catch(e) { } catch(e) {
} }
} }
} }
@ -1334,7 +1331,7 @@ JSJaCJSON.toString = function (obj) {
} }
} }
} }
a[a.length] = '}'; a[a.length] = '}';
return a.join(''); return a.join('');
} }
@ -1362,7 +1359,7 @@ switch (typeof(obj)) {
return s.object(obj); return s.object(obj);
case 'array': case 'array':
return s.array(obj); return s.array(obj);
} }
}; };
@ -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;
@ -2502,7 +2499,7 @@ function JSJaCError(code,type,condition) {
* @constructor * @constructor
* @param {Function} func The hash function to be used for creating the keys * @param {Function} func The hash function to be used for creating the keys
* @param {Debugger} oDbg Reference to debugger implementation [optional] * @param {Debugger} oDbg Reference to debugger implementation [optional]
*/ */
function JSJaCKeys(func,oDbg) { function JSJaCKeys(func,oDbg) {
var seed = Math.random(); var seed = Math.random();
@ -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
*/ */
/** /**
@ -2751,30 +2748,30 @@ JSJaCConnection.prototype.connected = function() { return this._connected; };
*/ */
JSJaCConnection.prototype.disconnect = function() { JSJaCConnection.prototype.disconnect = function() {
this._setStatus('disconnecting'); this._setStatus('disconnecting');
if (!this.connected()) if (!this.connected())
return; return;
this._connected = false; this._connected = false;
clearInterval(this._interval); clearInterval(this._interval);
clearInterval(this._inQto); clearInterval(this._inQto);
if (this._timeout) if (this._timeout)
clearTimeout(this._timeout); // remove timer clearTimeout(this._timeout); // remove timer
var slot = this._getFreeSlot(); var slot = this._getFreeSlot();
// Intentionally synchronous // Intentionally synchronous
this._req[slot] = this._setupRequest(false); this._req[slot] = this._setupRequest(false);
request = this._getRequestString(false, true); request = this._getRequestString(false, true);
this.oDbg.log("Disconnecting: " + request,4); this.oDbg.log("Disconnecting: " + request,4);
this._req[slot].r.send(request); this._req[slot].r.send(request);
try { try {
DataStore.removeDB(MINI_HASH, 'jsjac', 'state'); DataStore.removeDB(MINI_HASH, 'jsjac', 'state');
} catch (e) {} } catch (e) {}
this.oDbg.log("Disconnected: "+this._req[slot].r.responseText,2); this.oDbg.log("Disconnected: "+this._req[slot].r.responseText,2);
this._handleEvent('ondisconnect'); this._handleEvent('ondisconnect');
}; };
@ -3119,7 +3116,7 @@ JSJaCConnection.prototype.status = function() { return this._status; };
*/ */
JSJaCConnection.prototype.suspend = function(has_pause) { JSJaCConnection.prototype.suspend = function(has_pause) {
var data = this.suspendToData(has_pause); var data = this.suspendToData(has_pause);
try { try {
var c = DataStore.setDB(MINI_HASH, 'jsjac', 'state', JSJaCJSON.toString(data)); var c = DataStore.setDB(MINI_HASH, 'jsjac', 'state', JSJaCJSON.toString(data));
return c; return c;
@ -3136,7 +3133,7 @@ JSJaCConnection.prototype.suspend = function(has_pause) {
* @type Object * @type Object
*/ */
JSJaCConnection.prototype.suspendToData = function(has_pause) { JSJaCConnection.prototype.suspendToData = function(has_pause) {
// remove timers // remove timers
if(has_pause) { if(has_pause) {
clearTimeout(this._timeout); clearTimeout(this._timeout);
@ -3145,7 +3142,7 @@ JSJaCConnection.prototype.suspendToData = function(has_pause) {
this._suspend(); this._suspend();
} }
var u = ('_connected,_keys,_ID,_inQ,_pQueue,_regIDs,_errcnt,_inactivity,domain,username,resource,jid,fulljid,_sid,_httpbase,_timerval,_is_polling').split(','); var u = ('_connected,_keys,_ID,_inQ,_pQueue,_regIDs,_errcnt,_inactivity,domain,username,resource,jid,fulljid,_sid,_httpbase,_timerval,_is_polling').split(',');
u = u.concat(this._getSuspendVars()); u = u.concat(this._getSuspendVars());
var s = new Object(); var s = new Object();
@ -3162,12 +3159,12 @@ JSJaCConnection.prototype.suspendToData = function(has_pause) {
s[u[i]] = o; s[u[i]] = o;
} }
if(has_pause) { if(has_pause) {
this._connected = false; this._connected = false;
this._setStatus('suspending'); this._setStatus('suspending');
} }
return s; return s;
}; };
@ -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)
@ -3687,7 +3680,7 @@ JSJaCConnection.prototype._parseStreamFeatures = function(doc) {
this._handleEvent('ondisconnect'); this._handleEvent('ondisconnect');
return false; return false;
} }
this.mechs = new Object(); this.mechs = new Object();
var lMec1 = doc.getElementsByTagName("mechanisms"); var lMec1 = doc.getElementsByTagName("mechanisms");
this.has_sasl = false; this.has_sasl = false;
@ -3706,7 +3699,7 @@ JSJaCConnection.prototype._parseStreamFeatures = function(doc) {
this.oDbg.log("No support for SASL detected",2); this.oDbg.log("No support for SASL detected",2);
return false; return false;
} }
// Get the server CAPS (if available) // Get the server CAPS (if available)
this.server_caps=null; this.server_caps=null;
var sCaps = doc.getElementsByTagName("c"); var sCaps = doc.getElementsByTagName("c");
@ -3714,7 +3707,7 @@ JSJaCConnection.prototype._parseStreamFeatures = function(doc) {
var c_sCaps=sCaps.item(i); var c_sCaps=sCaps.item(i);
var x_sCaps=c_sCaps.getAttribute("xmlns"); var x_sCaps=c_sCaps.getAttribute("xmlns");
var v_sCaps=c_sCaps.getAttribute("ver"); var v_sCaps=c_sCaps.getAttribute("ver");
if ((x_sCaps == NS_CAPS) && v_sCaps) { if ((x_sCaps == NS_CAPS) && v_sCaps) {
this.server_caps=v_sCaps; this.server_caps=v_sCaps;
break; break;
@ -3723,10 +3716,10 @@ 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;
} }
return true; return 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
*/ */
/** /**
@ -4169,13 +4162,13 @@ JSJaCHttpBindingConnection.prototype._getStreamID = function(req) {
return; return;
} }
var body = req.responseXML.documentElement; var body = req.responseXML.documentElement;
// any session error? // any session error?
if(body.getAttribute('type') == 'terminate') { if(body.getAttribute('type') == 'terminate') {
this._handleEvent('onerror',JSJaCError('503','cancel','service-unavailable')); this._handleEvent('onerror',JSJaCError('503','cancel','service-unavailable'));
return; return;
} }
// extract stream id used for non-SASL authentication // extract stream id used for non-SASL authentication
if (body.getAttribute('authid')) { if (body.getAttribute('authid')) {
this.streamid = body.getAttribute('authid'); this.streamid = body.getAttribute('authid');
@ -4451,7 +4444,7 @@ JSJaCHttpBindingConnection.prototype._reInitStreamWait = function(req, cb) {
var featuresNL = doc.getElementsByTagName('stream:features'); var featuresNL = doc.getElementsByTagName('stream:features');
for (var i=0, l=featuresNL.length; i<l; i++) { for (var i=0, l=featuresNL.length; i<l; i++) {
if (featuresNL.item(i).namespaceURI == 'http://etherx.jabber.org/streams' || if (featuresNL.item(i).namespaceURI == 'http://etherx.jabber.org/streams' ||
featuresNL.item(i).getAttribute('xmlns') == featuresNL.item(i).getAttribute('xmlns') ==
'http://etherx.jabber.org/streams') { 'http://etherx.jabber.org/streams') {
var features = featuresNL.item(i); var features = featuresNL.item(i);
break; break;
@ -4461,7 +4454,7 @@ JSJaCHttpBindingConnection.prototype._reInitStreamWait = function(req, cb) {
var bind = features.getElementsByTagName('bind'); var bind = features.getElementsByTagName('bind');
for (var i=0, l=bind.length; i<l; i++) { for (var i=0, l=bind.length; i<l; i++) {
if (bind.item(i).namespaceURI == 'urn:ietf:params:xml:ns:xmpp-bind' || if (bind.item(i).namespaceURI == 'urn:ietf:params:xml:ns:xmpp-bind' ||
bind.item(i).getAttribute('xmlns') == bind.item(i).getAttribute('xmlns') ==
'urn:ietf:params:xml:ns:xmpp-bind') { 'urn:ietf:params:xml:ns:xmpp-bind') {
bind = bind.item(i); bind = bind.item(i);
break; break;
@ -4471,7 +4464,7 @@ JSJaCHttpBindingConnection.prototype._reInitStreamWait = function(req, cb) {
} }
this.oDbg.log(features); this.oDbg.log(features);
this.oDbg.log(bind); this.oDbg.log(bind);
if (features) { if (features) {
if (bind) { if (bind) {
cb(); cb();
@ -4865,7 +4858,26 @@ JSJaCWebSocketConnection.prototype._parseXml = function(s) {
this.oDbg.log('Parsing: ' + s, 4); this.oDbg.log('Parsing: ' + s, 4);
try { try {
doc = XmlDocument.create('stream', NS_STREAM); doc = XmlDocument.create('stream', NS_STREAM);
if(s.indexOf('<stream:stream') === -1) { if(s.trim() == '</stream:stream>') {
// Consider session as closed
this.oDbg.log("session terminated", 1);
clearTimeout(this._timeout); // remove timer
clearInterval(this._interval);
clearInterval(this._inQto);
try {
DataStore.removeDB(MINI_HASH, 'jsjac', 'state');
} catch (e) {}
this._connected = false;
this._handleEvent('onerror',JSJaCError('503','cancel','session-terminate'));
this.oDbg.log("Disconnected.",1);
this._handleEvent('ondisconnect');
return null;
} else if(s.indexOf('<stream:stream') === -1) {
// Wrap every stanza into stream element, so that XML namespaces work properly. // Wrap every stanza into stream element, so that XML namespaces work properly.
doc.loadXML("<stream:stream xmlns:stream='" + NS_STREAM + "' xmlns='jabber:client'>" + s + "</stream:stream>"); doc.loadXML("<stream:stream xmlns:stream='" + NS_STREAM + "' xmlns='jabber:client'>" + s + "</stream:stream>");
return doc.documentElement.firstChild; return doc.documentElement.firstChild;
@ -5018,3 +5030,61 @@ JSJaCWebSocketConnection.prototype._sendRaw = function(xml, cb, arg) {
return true; return true;
}; };
/*exported JSJaCUtils */
/**
* Various utilities put together so that they don't pollute global
* name space.
* @namespace
*/
var JSJaCUtils = {
/**
* XOR two strings of equal length.
* @param {string} s1 first string to XOR.
* @param {string} s2 second string to XOR.
* @return {string} s1 ^ s2.
*/
xor: function(s1, s2) {
/*jshint bitwise: false */
if(!s1) {
return s2;
}
if(!s2) {
return s1;
}
var result = '';
for(var i = 0; i < s1.length; i++) {
result += String.fromCharCode(s1.charCodeAt(i) ^ s2.charCodeAt(i));
}
return result;
},
/**
* Create nonce value of given size.
* @param {int} size size of the nonce that should be generated.
* @return {string} generated nonce.
*/
cnonce: function(size) {
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
var cnonce = '';
for (var i = 0; i < size; i++) {
cnonce += tab.charAt(Math.round(Math.random(new Date().getTime()) * (tab.length - 1)));
}
return cnonce;
},
/**
* Current timestamp.
* @return Seconds since 1.1.1970.
* @type int
*/
now: function() {
if (Date.now && typeof Date.now == 'function') {
return Date.now();
} else {
return new Date().getTime();
}
}
};

View file

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

View file

@ -32,25 +32,33 @@ var Links = (function () {
try { try {
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) {
Console.error('Links.apply', e); Console.error('Links.apply', 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 = {};
@ -48,7 +49,7 @@ var MAM = (function () {
try { try {
// Lock the archiving options // Lock the archiving options
$('#archiving').attr('disabled', true); $('#archiving').attr('disabled', true);
// Get the archiving configuration // Get the archiving configuration
var iq = new JSJaCIQ(); var iq = new JSJaCIQ();
iq.setType('get'); iq.setType('get');
@ -145,7 +146,7 @@ var MAM = (function () {
for(var c in args) { for(var c in args) {
if(args[c]) purge.appendChild(iq.buildNode(c, {'xmlns': NS_METRONOME_MAM_PURGE}, args[c])); if(args[c]) purge.appendChild(iq.buildNode(c, {'xmlns': NS_METRONOME_MAM_PURGE}, args[c]));
} }
con.send(iq, function(iq) { con.send(iq, function(iq) {
if(iq.getType() == 'result') { if(iq.getType() == 'result') {
Console.info('Archives purged (MAM).'); Console.info('Archives purged (MAM).');
@ -252,7 +253,7 @@ var MAM = (function () {
// Create MAM messages target // Create MAM messages target
var target_html = '<div class="mam-chunk" data-start="' + Common.encodeQuotes(start_stamp) + '" data-end="' + Common.encodeQuotes(start_end) + '"></div>'; var target_html = '<div class="mam-chunk" data-start="' + Common.encodeQuotes(start_stamp) + '" data-end="' + Common.encodeQuotes(start_end) + '"></div>';
var target_content_sel = $('#' + hex_md5(res_with) + ' .content'); var target_content_sel = $('#' + hex_md5(res_with) + ' .content');
var target_wait_sel = target_content_sel.find('.wait-mam'); var target_wait_sel = target_content_sel.find('.wait-mam');
@ -311,11 +312,16 @@ var MAM = (function () {
if(c_message[0]) { if(c_message[0]) {
// Re-build a proper JSJaC message stanza // Re-build a proper JSJaC message stanza
var message = JSJaCPacket.wrapNode(c_message[0]); var message = JSJaCPacket.wrapNode(c_message[0]);
var message_node = message.getNode();
// Check message type // Check message type
var type = message.getType() || 'chat'; var type = message.getType() || 'chat';
if(type == 'chat') { if(type == 'chat') {
// Display function
var c_display_fn;
var c_display_msg_bool = false;
// Read message data // Read message data
var xid = Common.bareXID(Common.getStanzaFrom(message)); var xid = Common.bareXID(Common.getStanzaFrom(message));
var id = message.getID(); var id = message.getID();
@ -331,50 +337,100 @@ var MAM = (function () {
var hash = hex_md5(xid); var hash = hex_md5(xid);
var body = message.getBody(); var body = message.getBody();
// Read delay (required since we deal w/ a past message!) // Content message?
var time, stamp; if(body) {
var delay = c_delay.attr('stamp'); // Read delay (required since we deal w/ a past message!)
var time, stamp;
var delay = c_delay.attr('stamp');
if(delay) { if(delay) {
time = DateUtils.relative(delay); time = DateUtils.relative(delay);
stamp = DateUtils.extractStamp(Date.jab2date(delay)); stamp = DateUtils.extractStamp(Date.jab2date(delay));
}
// Last-minute checks before display
if(time && stamp && body) {
var mam_chunk_path = '#' + hash + ' .mam-chunk';
// No chat auto-scroll?
var no_scroll = Common.exists(mam_chunk_path);
// Select the custom target
var c_target_sel = function() {
return $(mam_chunk_path).filter(function() {
return $(this).attr('data-start') <= stamp && $(this).attr('data-end') >= stamp;
}).filter(':first');
};
// Display the message in that target
var c_msg_display = function() {
Message.display(type, from_xid, hash, b_name.htmlEnc(), body, time, stamp, 'old-message', true, null, mode, null, c_target_sel(), no_scroll);
};
// Hack: do not display the message in case we would duplicate it w/ current session messages
// only used when initiating a new chat, avoids collisions
if(!(xid in self.map_states) && $('#' + hash).find('.one-line.user-message:last').text() == body) {
return;
} }
if(c_target_sel().size()) { // Last-minute checks before display
if(time && stamp) {
var mam_chunk_path = '#' + hash + ' .mam-chunk';
// Markable message?
var is_markable = Markers.hasRequestMarker(message_node);
// No chat auto-scroll?
var no_scroll = Common.exists(mam_chunk_path);
// Select the custom target
var c_target_sel = function() {
return $(mam_chunk_path).filter(function() {
return $(this).attr('data-start') <= stamp && $(this).attr('data-end') >= stamp;
}).filter(':first');
};
// Display the message in that target // Display the message in that target
c_msg_display(); c_display_fn = function() {
// Display message
Message.display(
type,
from_xid,
hash,
b_name.htmlEnc(),
body,
time,
stamp,
'old-message',
true,
null,
mode,
id + '-mam',
c_target_sel(),
no_scroll,
undefined,
undefined,
undefined,
is_markable
);
self.map_messages[id] = 1;
};
c_display_msg_bool = c_target_sel().size() ? true : false;
// Hack: do not display the message in case we would duplicate it w/ current session messages
// only used when initiating a new chat, avoids collisions
if(!(xid in self.map_states) && $('#' + hash).find('.one-line.user-message:last').text() == body) {
return;
}
}
} else if(Markers.hasResponseMarker(message_node)) {
// Marked message? (by other party)
if(mode == 'him') {
var marked_message_id = Markers.getMessageID(message_node);
c_display_fn = function() {
var is_mam_marker = true;
Markers.handle(
from_xid,
message_node,
is_mam_marker
);
};
c_display_msg_bool = (self.map_messages[marked_message_id] === 1) ? true : false;
}
}
// Display message?
if(typeof c_display_fn == 'function') {
if(c_display_msg_bool === true) {
// Display message now
c_display_fn();
} else { } else {
// Delay display (we may not have received the MAM reply ATM) // Delay display (we may not have received the MAM reply ATM)
if(typeof self.msg_queue[xid] != 'object') { if(typeof self.msg_queue[xid] != 'object') {
self.msg_queue[xid] = []; self.msg_queue[xid] = [];
} }
self.msg_queue[xid].push(c_msg_display); self.msg_queue[xid].push(c_display_fn);
} }
} }
} }

View file

@ -0,0 +1,428 @@
/*
Jappix - An open social platform
Implementation of XEP-0333: Chat Markers
-------------------------------------------------
License: AGPL
Author: Valérian Saliou
*/
// Bundle
var Markers = (function () {
/**
* Alias of this
* @private
*/
var self = {};
/* Constants */
self.MARK_TYPE_MARKABLE = 'markable';
self.MARK_TYPE_RECEIVED = 'received';
self.MARK_TYPE_DISPLAYED = 'displayed';
self.MARK_TYPE_ACKNOWLEDGED = 'acknowledged';
self.MARK_TYPES = {};
self.MARK_TYPES[self.MARK_TYPE_MARKABLE] = 1;
self.MARK_TYPES[self.MARK_TYPE_RECEIVED] = 1;
self.MARK_TYPES[self.MARK_TYPE_DISPLAYED] = 1;
self.MARK_TYPES[self.MARK_TYPE_ACKNOWLEDGED] = 1;
/**
* Returns whether entity supports message markers
* @public
* @param {string} xid
* @return {boolean}
*/
self.hasSupport = function(xid) {
var has_support = false;
try {
has_support = true ? $('#' + hex_md5(xid)).attr('data-markers') == 'true' : false;
} catch(e) {
Console.error('Markers.hasSupport', e);
} finally {
return has_support;
}
};
/**
* Returns whether request message is marked or not
* @public
* @param {object} message
* @return {boolean}
*/
self.hasRequestMarker = function(message) {
var has_request_marker = false;
try {
has_request_marker = ($(message).find('markable[xmlns="' + NS_URN_MARKERS + '"]').size() ? true : false);
} catch(e) {
Console.error('Markers.hasRequestMarker', e);
} finally {
return has_request_marker;
}
};
/**
* Returns whether response message is marked or not
* @public
* @param {object} message
* @return {boolean}
*/
self.hasResponseMarker = function(message) {
var has_response_marker = false;
try {
var marker_sel = $(message).find('[xmlns="' + NS_URN_MARKERS + '"]');
if(marker_sel.size()) {
var mark_type = marker_sel.prop('tagName').toLowerCase();
switch(mark_type) {
case self.MARK_TYPE_RECEIVED:
case self.MARK_TYPE_DISPLAYED:
case self.MARK_TYPE_ACKNOWLEDGED:
has_response_marker = true;
break;
}
}
} catch(e) {
Console.error('Markers.hasResponseMarker', e);
} finally {
return has_response_marker;
}
};
/**
* Returns the marked message ID
* @public
* @param {object} message
* @return {boolean}
*/
self.getMessageID = function(message) {
var message_id = null;
try {
message_id = $(message).find('[xmlns="' + NS_URN_MARKERS + '"]').attr('id');
} catch(e) {
Console.error('Markers.getMessageID', e);
} finally {
return message_id;
}
};
/**
* Marks a message
* @public
* @param {object} message
* @return {undefined}
*/
self.mark = function(message) {
try {
message.appendNode('markable', {
'xmlns': NS_URN_MARKERS
});
} catch(e) {
Console.error('Markers.mark', e);
}
};
/**
* Changes received message status (once received or read)
* @public
* @param {string} mark_type
* @param {object} message_id
* @return {undefined}
*/
self.change = function(to, mark_type, message_id, message_sel) {
try {
if(!(mark_type in self.MARK_TYPES)) {
throw 'Marker type (' + mark_type + ') not supported, aborting.';
}
// Store mark state
message_sel.attr('data-mark', mark_type);
var message = new JSJaCMessage();
message.setType('chat');
message.setTo(to);
message.appendNode(mark_type, {
'xmlns': NS_URN_MARKERS,
'id': message_id
});
con.send(message);
Console.debug('Markers.change', 'Changed marker to: ' + mark_type + ' for message with ID: ' + message_id + ' from: ' + to);
} catch(e) {
Console.error('Markers.change', e);
}
};
/**
* Handles marker change coming from Carbons
* @public
* @param {string} message
* @return {undefined}
*/
self.handleCarbonChange = function(message) {
try {
// Check the marker element is existing
var marker_sel = $(message).find('[xmlns="' + NS_URN_MARKERS + '"]');
if(marker_sel.size()) {
var xid = Common.bareXID(message.getTo());
var mark_type = marker_sel.prop('tagName').toLowerCase();
var mark_handle = false;
// Filter allowed markers
switch(mark_type) {
case self.MARK_TYPE_RECEIVED:
case self.MARK_TYPE_DISPLAYED:
case self.MARK_TYPE_ACKNOWLEDGED:
mark_handle = true;
break;
}
if(mark_handle === true) {
var mark_message_id = marker_sel.attr('id');
var message_sel = $('#' + hex_md5(xid) + ' .content .one-line[data-mode="him"][data-markable="true"]').filter(function() {
return ($(this).attr('data-id') + '') === (mark_message_id + '');
}).filter(':last');
if(!message_sel.size()) {
Console.warn('Markers.handleCarbonChange', 'Unknown message marker to keep in sync with Carbons for: ' + xid);
return false;
}
// Store mark state
message_sel.attr('data-mark', mark_type);
Console.debug('Markers.handleCarbonChange', 'Received Carbons chat marker (' + mark_type + ') from another resource for: ' + from);
}
}
} catch(e) {
Console.error('Markers.handleCarbonChange', e);
}
};
/**
* Handles a marked message
* @public
* @param {string} from
* @param {object} message
* @param {boolean} is_mam_marker
* @return {undefined}
*/
self.handle = function(from, message, is_mam_marker, 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

@ -18,7 +18,7 @@ var Me = (function () {
* @private * @private
*/ */
var self = {}; var self = {};
/** /**
* Opens the Me tools * Opens the Me tools
@ -29,32 +29,32 @@ var Me = (function () {
try { try {
// Popup HTML content // Popup HTML content
var html = var html =
'<div class="top">' + Common._e("Public profile") + '</div>' + '<div class="top">' + Common._e("Public profile") + '</div>' +
'<div class="content">' + '<div class="content">' +
'<a class="me-images logo" href="https://me.jappix.com/" target="_blank"></a>' + '<a class="me-images logo" href="https://me.jappix.com/" target="_blank"></a>' +
'<div class="infos">' + '<div class="infos">' +
'<p class="infos-title">' + Common._e("Your profile anywhere on the Web.") + '</p>' + '<p class="infos-title">' + Common._e("Your profile anywhere on the Web.") + '</p>' +
'<p>' + Common.printf(Common._e("%s is a Jappix.com service which makes your XMPP profile public. It is easier to share it. No XMPP account is required to view your social channel, your current position and your contact details."), '<a href="https://me.jappix.com/" target="_blank">Jappix Me</a>') + '</p>' + '<p>' + Common.printf(Common._e("%s is a Jappix.com service which makes your XMPP profile public. It is easier to share it. No XMPP account is required to view your social channel, your current position and your contact details."), '<a href="https://me.jappix.com/" target="_blank">Jappix Me</a>') + '</p>' +
'<p>' + Common._e("Furthermore, every picture you post in your social channel is added to a beautiful picture timeline. You can now view the pictures you shared year by year.") + '</p>' + '<p>' + Common._e("Furthermore, every picture you post in your social channel is added to a beautiful picture timeline. You can now view the pictures you shared year by year.") + '</p>' +
'<p>' + Common._e("You can also use your XMPP avatar as a single avatar for every website, blog and forum you use. When you change it on XMPP, the new avatar appears everywhere. What a genius improvement!") + '</p>' + '<p>' + Common._e("You can also use your XMPP avatar as a single avatar for every website, blog and forum you use. When you change it on XMPP, the new avatar appears everywhere. What a genius improvement!") + '</p>' +
'</div>' + '</div>' +
'<a class="go one-button" href="https://me.jappix.com/new" target="_blank">' + Common._e("Yay, let's create your public profile!") + '</a>' + '<a class="go one-button" href="https://me.jappix.com/new" target="_blank">' + Common._e("Yay, let's create your public profile!") + '</a>' +
'</div>' + '</div>' +
'<div class="bottom">' + '<div class="bottom">' +
'<a href="#" class="finish">' + Common._e("Close") + '</a>' + '<a href="#" class="finish">' + Common._e("Close") + '</a>' +
'</div>'; '</div>';
// Create the popup // Create the popup
Popup.create('me', html); Popup.create('me', html);
// Associate the events // Associate the events
self.instance(); self.instance();
Console.log('Public profile tool opened.'); Console.log('Public profile tool opened.');
} catch(e) { } catch(e) {
Console.error('Me.open', e); Console.error('Me.open', e);
@ -73,7 +73,7 @@ var Me = (function () {
try { try {
// Destroy the popup // Destroy the popup
Popup.destroy('me'); Popup.destroy('me');
// We finished // We finished
Welcome.is_done = false; Welcome.is_done = false;
} catch(e) { } catch(e) {
@ -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

File diff suppressed because it is too large Load diff

View file

@ -31,41 +31,40 @@ var Mobile = (function () {
try { try {
// Reset the panels // Reset the panels
self.resetPanel(); self.resetPanel();
// Get the values // Get the values
var xid = aForm.xid.value; var xid = aForm.xid.value;
var username, domain; var username, domain;
// A domain is specified // A domain is specified
if(xid.indexOf('@') != -1) { if(xid.indexOf('@') != -1) {
username = self.getXIDNick(xid); username = self.getXIDNick(xid);
domain = self.getXIDHost(xid); domain = self.getXIDHost(xid);
// Domain is locked and not the same // Domain is locked and not the same
if((LOCK_HOST == 'on') && (domain != HOST_MAIN)) { if((LOCK_HOST == 'on') && (domain != HOST_MAIN)) {
self.showThis('error'); self.showThis('error');
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;
} }
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) {
// Show the info notification // Show the info notification
self.showThis('info'); self.showThis('info');
if(HOST_WEBSOCKET && typeof window.WebSocket != 'undefined') { if(HOST_WEBSOCKET && typeof window.WebSocket != 'undefined') {
// WebSocket supported & configured // WebSocket supported & configured
con = new JSJaCWebSocketConnection({ con = new JSJaCWebSocketConnection({
@ -73,16 +72,16 @@ var Mobile = (function () {
}); });
} else { } else {
var httpbase = (HOST_BOSH_MAIN || HOST_BOSH); var httpbase = (HOST_BOSH_MAIN || HOST_BOSH);
// Check BOSH origin // Check BOSH origin
BOSH_SAME_ORIGIN = Origin.isSame(httpbase); BOSH_SAME_ORIGIN = Origin.isSame(httpbase);
// We create the new http-binding connection // We create the new http-binding connection
con = new JSJaCHttpBindingConnection({ con = new JSJaCHttpBindingConnection({
httpbase: httpbase httpbase: httpbase
}); });
} }
// And we handle everything that happen // And we handle everything that happen
con.registerHandler('message', self.handleMessage); con.registerHandler('message', self.handleMessage);
con.registerHandler('presence', self.handlePresence); con.registerHandler('presence', self.handlePresence);
@ -90,7 +89,7 @@ var Mobile = (function () {
con.registerHandler('onconnect', self.handleConnected); con.registerHandler('onconnect', self.handleConnected);
con.registerHandler('onerror', self.handleError); con.registerHandler('onerror', self.handleError);
con.registerHandler('ondisconnect', self.handleDisconnected); con.registerHandler('ondisconnect', self.handleDisconnected);
// We retrieve what the user typed in the login inputs // We retrieve what the user typed in the login inputs
oArgs = {}; oArgs = {};
oArgs.username = username; oArgs.username = username;
@ -104,11 +103,11 @@ var Mobile = (function () {
if(reg) { if(reg) {
oArgs.register = true; oArgs.register = true;
} }
// We connect ! // We connect !
con.connect(oArgs); con.connect(oArgs);
} }
// Not enough parameters // Not enough parameters
else { else {
self.showThis('error'); self.showThis('error');
@ -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
@ -195,7 +218,7 @@ var Mobile = (function () {
// Hide the opened panels // Hide the opened panels
self.hideThis('info'); self.hideThis('info');
self.hideThis('error'); self.hideThis('error');
//Show the target panel //Show the target panel
if(id) { if(id) {
self.showThis(id); self.showThis(id);
@ -217,7 +240,7 @@ var Mobile = (function () {
try { try {
// Reset the "secret" input values // Reset the "secret" input values
document.getElementById('pwd').value = ''; document.getElementById('pwd').value = '';
// Remove the useless DOM elements // Remove the useless DOM elements
var body = document.getElementsByTagName('body')[0]; var body = document.getElementsByTagName('body')[0];
body.removeChild(document.getElementById('talk')); body.removeChild(document.getElementById('talk'));
@ -296,24 +319,25 @@ var Mobile = (function () {
try { try {
var type = msg.getType(); var type = msg.getType();
if(type == 'chat' || type == 'normal') { if(type == 'chat' || type == 'normal') {
// Get the body // Get the body
var body = msg.getBody(); var body = msg.getBody();
if(body) { if(body) {
// Get the values // Get the values
var xid = self.cutResource(msg.getFrom()); var xid = self.cutResource(msg.getFrom());
var hash = hex_md5(xid); var hash = hex_md5(xid);
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);
// Display the message // Display the message
self.displayMessage(xid, body, nick, hash); self.displayMessage(xid, body, nick, hash);
} }
@ -339,35 +363,31 @@ var Mobile = (function () {
var hash = hex_md5(xid); var hash = hex_md5(xid);
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':
self.displayPresence(hash, show); self.displayPresence(hash, show);
break; break;
case 'away': case 'away':
self.displayPresence(hash, show); self.displayPresence(hash, show);
break; break;
case 'xa': case 'xa':
self.displayPresence(hash, show); self.displayPresence(hash, show);
break; break;
case 'dnd': case 'dnd':
self.displayPresence(hash, show); self.displayPresence(hash, show);
break; break;
default: default:
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);
@ -391,7 +411,7 @@ var Mobile = (function () {
var iqQueryXMLNS = iq.getQueryXMLNS(); var iqQueryXMLNS = iq.getQueryXMLNS();
var iqType = iq.getType(); var iqType = iq.getType();
var iqQuery; var iqQuery;
// Create the response // Create the response
var iqResponse = new JSJaCIQ(); var iqResponse = new JSJaCIQ();
@ -400,43 +420,43 @@ var Mobile = (function () {
iqResponse.setTo(iqFrom); iqResponse.setTo(iqFrom);
iqResponse.setType('result'); iqResponse.setType('result');
} }
// Disco#infos query // Disco#infos query
if((iqQueryXMLNS == NS_DISCO_INFO) && (iqType == 'get')) { if((iqQueryXMLNS == NS_DISCO_INFO) && (iqType == 'get')) {
/* 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(iq.appendNode('identity', { iqQuery.appendChild(iq.appendNode('identity', {
'category': 'client', 'category': 'client',
'type': 'mobile', 'type': 'mobile',
'name': 'Jappix Mobile' 'name': 'Jappix Mobile'
})); }));
// We set all the supported features // We set all the supported features
var fArray = new Array( var fArray = new Array(
NS_DISCO_INFO, NS_DISCO_INFO,
NS_VERSION NS_VERSION
); );
for(var i in fArray) { for(var i in fArray) {
iqQuery.appendChild(iq.buildNode('feature', {'var': fArray[i]})); iqQuery.appendChild(iq.buildNode('feature', {'var': fArray[i]}));
} }
con.send(iqResponse); con.send(iqResponse);
} }
// Software version query // Software version query
else if((iqQueryXMLNS == NS_VERSION) && (iqType == 'get')) { else if((iqQueryXMLNS == NS_VERSION) && (iqType == 'get')) {
/* REF: http://xmpp.org/extensions/xep-0092.html */ /* REF: http://xmpp.org/extensions/xep-0092.html */
iqQuery = iqResponse.setQuery(NS_VERSION); iqQuery = iqResponse.setQuery(NS_VERSION);
iqQuery.appendChild(iq.buildNode('name', 'Jappix Mobile')); iqQuery.appendChild(iq.buildNode('name', 'Jappix Mobile'));
iqQuery.appendChild(iq.buildNode('version', JAPPIX_VERSION)); iqQuery.appendChild(iq.buildNode('version', JAPPIX_VERSION));
iqQuery.appendChild(iq.buildNode('os', BrowserDetect.OS)); iqQuery.appendChild(iq.buildNode('os', BrowserDetect.OS));
con.send(iqResponse); con.send(iqResponse);
} }
} catch(e) { } catch(e) {
@ -457,27 +477,27 @@ var Mobile = (function () {
// Reset the elements // Reset the elements
self.hideThis('home'); self.hideThis('home');
self.resetPanel(); self.resetPanel();
// Create the talk page // Create the talk page
document.getElementsByTagName('body')[0].innerHTML += document.getElementsByTagName('body')[0].innerHTML +=
'<div id="talk">' + '<div id="talk">' +
'<div class="header">' + '<div class="header">' +
'<div class="mobile-images"></div>' + '<div class="mobile-images"></div>' +
'<button onclick="Mobile.doLogout();">' + self._e("Disconnect") + '</button>' + '<button onclick="Mobile.doLogout();">' + self._e("Disconnect") + '</button>' +
'</div>' + '</div>' +
'<div id="roster"></div>' + '<div id="roster"></div>' +
'</div>' + '</div>' +
'<div id="chat">' + '<div id="chat">' +
'<div class="header">' + '<div class="header">' +
'<div class="mobile-images"></div>' + '<div class="mobile-images"></div>' +
'<button onclick="Mobile.returnToRoster();">' + self._e("Previous") + '</button>' + '<button onclick="Mobile.returnToRoster();">' + self._e("Previous") + '</button>' +
'</div>' + '</div>' +
'<div id="chans"></div>' + '<div id="chans"></div>' +
'</div>'; '</div>';
// Get the roster items // Get the roster items
self.getRoster(); self.getRoster();
} catch(e) { } catch(e) {
@ -514,7 +534,7 @@ var Mobile = (function () {
try { try {
// Reset the elements // Reset the elements
self.resetDOM(); self.resetDOM();
// Show the home page // Show the home page
self.showThis('home'); self.showThis('home');
} catch(e) { } catch(e) {
@ -536,15 +556,17 @@ var Mobile = (function () {
// Error: send presence anyway // Error: send presence anyway
if(!iq || (iq.getType() != 'result')) if(!iq || (iq.getType() != 'result'))
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
var iqNode = iq.getNode(); var iqNode = iq.getNode();
var bItems = iqNode.getElementsByTagName('item'); var bItems = iqNode.getElementsByTagName('item');
// Display each elements from the roster // Display each elements from the roster
for(var i = 0; i < bItems.length; i++) { for(var i = 0; i < bItems.length; i++) {
// Get the values // Get the values
@ -552,22 +574,34 @@ var Mobile = (function () {
xid = current.getAttribute('jid').htmlEnc(); xid = current.getAttribute('jid').htmlEnc();
nick = current.getAttribute('name'); nick = current.getAttribute('name');
hash = hex_md5(xid); hash = hex_md5(xid);
// No defined nick? // No defined nick?
if(!nick) if(!nick) {
nick = self.getDirectNick(xid); nick = self.getDirectNick(xid);
}
// Display the values
oneBuddy = document.createElement('a'); roster_buddies.push({
oneID = 'buddy-' + hash; 'xid': xid,
oneBuddy.setAttribute('href', '#'); 'hash': hash,
oneBuddy.setAttribute('id', oneID); 'nick': nick
oneBuddy.setAttribute('class', 'one-buddy'); });
oneBuddy.setAttribute('onclick', 'return Mobile.chat(\'' + self.encodeOnclick(xid) + '\', \'' + self.encodeOnclick(nick) + '\');');
oneBuddy.innerHTML = nick.htmlEnc();
roster.appendChild(oneBuddy);
} }
// Sort the values
self.sortRoster(roster_buddies);
// Display the values
for(var j = 0; j < roster_buddies.length; j++) {
cur_buddy = roster_buddies[j];
self.displayRoster(
roster,
cur_buddy.xid,
cur_buddy.hash,
cur_buddy.nick
);
}
// Start handling buddies presence // Start handling buddies presence
self.sendPresence('', 'available', 1); self.sendPresence('', 'available', 1);
} catch(e) { } catch(e) {
@ -589,7 +623,7 @@ var Mobile = (function () {
var body = aForm.body.value; var body = aForm.body.value;
var xid = aForm.xid.value; var xid = aForm.xid.value;
var hash = hex_md5(xid); var hash = hex_md5(xid);
if(body && xid) { if(body && xid) {
// Send the message // Send the message
var aMsg = new JSJaCMessage(); var aMsg = new JSJaCMessage();
@ -597,10 +631,10 @@ var Mobile = (function () {
aMsg.setType('chat'); aMsg.setType('chat');
aMsg.setBody(body); aMsg.setBody(body);
con.send(aMsg); con.send(aMsg);
// Clear our input // Clear our input
aForm.body.value = ''; aForm.body.value = '';
// Display the message we sent // Display the message we sent
self.displayMessage(xid, body, 'me', hash); self.displayMessage(xid, body, 'me', hash);
} }
@ -626,7 +660,7 @@ var Mobile = (function () {
try { try {
var presence = new JSJaCPresence(); var presence = new JSJaCPresence();
if(type) if(type)
presence.setType(type); presence.setType(type);
if(show) if(show)
@ -635,7 +669,7 @@ var Mobile = (function () {
presence.setPriority(priority); presence.setPriority(priority);
if(status) if(status)
presence.setStatus(status); presence.setStatus(status);
con.send(presence); con.send(presence);
} catch(e) { } catch(e) {
Console.error('Mobile.sendPresence', e); Console.error('Mobile.sendPresence', e);
@ -655,7 +689,7 @@ var Mobile = (function () {
iq = new JSJaCIQ(); iq = new JSJaCIQ();
iq.setType('get'); iq.setType('get');
iq.setQuery(NS_ROSTER); iq.setQuery(NS_ROSTER);
con.send(iq, self.handleRoster); con.send(iq, self.handleRoster);
} catch(e) { } catch(e) {
Console.error('Mobile.getRoster', e); Console.error('Mobile.getRoster', e);
@ -692,7 +726,7 @@ var Mobile = (function () {
try { try {
var path = 'buddy-' + hash; var path = 'buddy-' + hash;
if(self.exists(path)) { if(self.exists(path)) {
return document.getElementById(path).innerHTML; return document.getElementById(path).innerHTML;
} else { } else {
@ -718,15 +752,16 @@ var Mobile = (function () {
try { try {
// Get the index of our char to explode // Get the index of our char to explode
var index = toStr.indexOf(toEx); var index = toStr.indexOf(toEx);
// 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;
} catch(e) { } catch(e) {
@ -798,13 +833,13 @@ var Mobile = (function () {
try { try {
// Encode in HTML // Encode in HTML
msg = msg.htmlEnc(); msg = msg.htmlEnc();
// Highlighted text // Highlighted text
msg = msg.replace(/(\s|^)\*(.+)\*(\s|$)/gi,'$1<em>$2</em>$3'); msg = msg.replace(/(\s|^)\*(.+)\*(\s|$)/gi,'$1<em>$2</em>$3');
// Links // Links
msg = Links.apply(msg, 'mini'); msg = Links.apply(msg, 'mini');
return msg; return msg;
} catch(e) { } catch(e) {
Console.error('Mobile.filter', e); Console.error('Mobile.filter', e);
@ -827,19 +862,20 @@ var Mobile = (function () {
try { try {
// Get the path // Get the path
var path = 'content-' + hash; var path = 'content-' + hash;
// 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>';
document.getElementById(path).innerHTML += html; document.getElementById(path).innerHTML += html;
// Scroll to the last element // Scroll to the last element
document.getElementById(path).lastChild.scrollIntoView(); document.getElementById(path).lastChild.scrollIntoView();
} catch(e) { } catch(e) {
@ -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
@ -859,7 +950,7 @@ var Mobile = (function () {
try { try {
// Hide the chats // Hide the chats
self.hideThis('chat'); self.hideThis('chat');
// Show the roster // Show the roster
self.showThis('talk'); self.showThis('talk');
} catch(e) { } catch(e) {
@ -880,15 +971,16 @@ var Mobile = (function () {
try { try {
// Hide the roster page // Hide the roster page
self.hideThis('talk'); self.hideThis('talk');
// Hide the other chats // Hide the other chats
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');
self.showThis(hash); self.showThis(hash);
@ -913,7 +1005,7 @@ var Mobile = (function () {
// Define the variables // Define the variables
var chat = document.getElementById('chans'); var chat = document.getElementById('chans');
var oneChat = document.createElement('div'); var oneChat = document.createElement('div');
// Apply the DOM modification // Apply the DOM modification
oneChat.setAttribute('id', 'chat-' + hash); oneChat.setAttribute('id', 'chat-' + hash);
oneChat.setAttribute('class', 'one-chat'); oneChat.setAttribute('class', 'one-chat');
@ -937,17 +1029,18 @@ var Mobile = (function () {
try { try {
var hash = hex_md5(xid); var hash = hex_md5(xid);
// 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);
} }
// Switch to the chat // Switch to the chat
self.chatSwitch('chat-' + hash); self.chatSwitch('chat-' + hash);
} catch(e) { } catch(e) {
@ -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

@ -31,129 +31,130 @@ var MUCAdmin = (function () {
try { try {
// Popup HTML content // Popup HTML content
var html_full = var html_full =
'<div class="top">' + Common._e("MUC administration") + '</div>' + '<div class="top">' + Common._e("MUC administration") + '</div>' +
'<div class="content">' + '<div class="content">' +
'<div class="head mucadmin-head">' + '<div class="head mucadmin-head">' +
'<div class="head-text mucadmin-head-text">' + Common._e("You administrate this room") + '</div>' + '<div class="head-text mucadmin-head-text">' + Common._e("You administrate this room") + '</div>' +
'<div class="mucadmin-head-jid">' + xid + '</div>' + '<div class="mucadmin-head-jid">' + xid + '</div>' +
'</div>' + '</div>' +
'<div class="mucadmin-forms">' + '<div class="mucadmin-forms">' +
'<div class="mucadmin-topic">' + '<div class="mucadmin-topic">' +
'<fieldset>' + '<fieldset>' +
'<legend>' + Common._e("Subject") + '</legend>' + '<legend>' + Common._e("Subject") + '</legend>' +
'<label for="topic-text">' + Common._e("Enter new subject") + '</label>' + '<label for="topic-text">' + Common._e("Enter new subject") + '</label>' +
'<textarea id="topic-text" name="room-topic" rows="8" cols="60" ></textarea>' + '<textarea id="topic-text" name="room-topic" rows="8" cols="60" ></textarea>' +
'</fieldset>' + '</fieldset>' +
'</div>' + '</div>' +
'<div class="mucadmin-conf">' + '<div class="mucadmin-conf">' +
'<fieldset>' + '<fieldset>' +
'<legend>' + Common._e("Configuration") + '</legend>' + '<legend>' + Common._e("Configuration") + '</legend>' +
'<div class="results mucadmin-results"></div>' + '<div class="results mucadmin-results"></div>' +
'</fieldset>' + '</fieldset>' +
'</div>' + '</div>' +
'<div class="mucadmin-aut">' + '<div class="mucadmin-aut">' +
'<fieldset>' + '<fieldset>' +
'<legend>' + Common._e("Authorizations") + '</legend>' + '<legend>' + Common._e("Authorizations") + '</legend>' +
'<label>' + Common._e("Member list") + '</label>' + '<label>' + Common._e("Member list") + '</label>' +
'<div class="aut-member aut-group">' + '<div class="aut-member aut-group">' +
'<a href="#" class="aut-add" onclick="return MUCAdmin.addInput(\'\', \'member\');">' + Common._e("Add an input") + '</a>' + '<a href="#" class="aut-add" onclick="return MUCAdmin.addInput(\'\', \'member\');">' + Common._e("Add an input") + '</a>' +
'</div>' + '</div>' +
'<label>' + Common._e("Owner list") + '</label>' + '<label>' + Common._e("Owner list") + '</label>' +
'<div class="aut-owner aut-group">' + '<div class="aut-owner aut-group">' +
'<a href="#" class="aut-add" onclick="return MUCAdmin.addInput(\'\', \'owner\');">' + Common._e("Add an input") + '</a>' + '<a href="#" class="aut-add" onclick="return MUCAdmin.addInput(\'\', \'owner\');">' + Common._e("Add an input") + '</a>' +
'</div>' + '</div>' +
'<label>' + Common._e("Administrator list") + '</label>' + '<label>' + Common._e("Administrator list") + '</label>' +
'<div class="aut-admin aut-group">' + '<div class="aut-admin aut-group">' +
'<a href="#" class="aut-add" onclick="return MUCAdmin.addInput(\'\', \'admin\');">' + Common._e("Add an input") + '</a>' + '<a href="#" class="aut-add" onclick="return MUCAdmin.addInput(\'\', \'admin\');">' + Common._e("Add an input") + '</a>' +
'</div>' + '</div>' +
'<label>' + Common._e("Outcast list") + '</label>' + '<label>' + Common._e("Outcast list") + '</label>' +
'<div class="aut-outcast aut-group">' + '<div class="aut-outcast aut-group">' +
'<a href="#" class="aut-add" onclick="return MUCAdmin.addInput(\'\', \'outcast\');">' + Common._e("Add an input") + '</a>' + '<a href="#" class="aut-add" onclick="return MUCAdmin.addInput(\'\', \'outcast\');">' + Common._e("Add an input") + '</a>' +
'</div>' + '</div>' +
'</fieldset>' + '</fieldset>' +
'</div>' + '</div>' +
'<div class="mucadmin-others">' + '<div class="mucadmin-others">' +
'<fieldset>' + '<fieldset>' +
'<legend>' + Common._e("Others") + '</legend>' + '<legend>' + Common._e("Others") + '</legend>' +
'<label>' + Common._e("Destroy this MUC") + '</label>' + '<label>' + Common._e("Destroy this MUC") + '</label>' +
'<a href="#" onclick="return MUCAdmin.destroy();">' + Common._e("Yes, let's do it!") + '</a>' + '<a href="#" onclick="return MUCAdmin.destroy();">' + Common._e("Yes, let's do it!") + '</a>' +
'</fieldset>' + '</fieldset>' +
'</div>' + '</div>' +
'</div>' + '</div>' +
'</div>' + '</div>' +
'<div class="bottom">' + '<div class="bottom">' +
'<div class="wait wait-medium"></div>' + '<div class="wait wait-medium"></div>' +
'<a href="#" class="finish save">' + Common._e("Save") + '</a>' + '<a href="#" class="finish save">' + Common._e("Save") + '</a>' +
'<a href="#" class="finish cancel">' + Common._e("Cancel") + '</a>' + '<a href="#" class="finish cancel">' + Common._e("Cancel") + '</a>' +
'</div>'; '</div>';
var html_partial = var html_partial =
'<div class="top">' + Common._e("MUC administration") + '</div>' + '<div class="top">' + Common._e("MUC administration") + '</div>' +
'<div class="content">' + '<div class="content">' +
'<div class="head mucadmin-head">' + '<div class="head mucadmin-head">' +
'<div class="head-text mucadmin-head-text">' + Common._e("You administrate this room") + '</div>' + '<div class="head-text mucadmin-head-text">' + Common._e("You administrate this room") + '</div>' +
'<div class="mucadmin-head-jid">' + xid + '</div>' + '<div class="mucadmin-head-jid">' + xid + '</div>' +
'</div>' + '</div>' +
'<div class="mucadmin-forms">' + '<div class="mucadmin-forms">' +
'<div class="mucadmin-aut">' + '<div class="mucadmin-aut">' +
'<fieldset>' + '<fieldset>' +
'<legend>' + Common._e("Authorizations") + '</legend>' + '<legend>' + Common._e("Authorizations") + '</legend>' +
'<label>' + Common._e("Member list") + '</label>' + '<label>' + Common._e("Member list") + '</label>' +
'<div class="aut-member aut-group">' + '<div class="aut-member aut-group">' +
'<a href="#" class="aut-add" onclick="return MUCAdmin.addInput(\'\', \'member\');">' + Common._e("Add an input") + '</a>' + '<a href="#" class="aut-add" onclick="return MUCAdmin.addInput(\'\', \'member\');">' + Common._e("Add an input") + '</a>' +
'</div>' + '</div>' +
'<label>' + Common._e("Outcast list") + '</label>' + '<label>' + Common._e("Outcast list") + '</label>' +
'<div class="aut-outcast aut-group">' + '<div class="aut-outcast aut-group">' +
'<a href="#" class="aut-add" onclick="return MUCAdmin.addInput(\'\', \'outcast\');">' + Common._e("Add an input") + '</a>' + '<a href="#" class="aut-add" onclick="return MUCAdmin.addInput(\'\', \'outcast\');">' + Common._e("Add an input") + '</a>' +
'</div>' + '</div>' +
'</fieldset>' + '</fieldset>' +
'</div>' + '</div>' +
'</div>' + '</div>' +
'</div>' + '</div>' +
'<div class="bottom">' + '<div class="bottom">' +
'<div class="wait wait-medium"></div>' + '<div class="wait wait-medium"></div>' +
'<a href="#" class="finish save">' + Common._e("Save") + '</a>' + '<a href="#" class="finish save">' + Common._e("Save") + '</a>' +
'<a href="#" class="finish cancel">' + Common._e("Cancel") + '</a>' + '<a href="#" class="finish cancel">' + Common._e("Cancel") + '</a>' +
'</div>'; '</div>';
// Create the popup // Create the popup
if(aff == 'owner') if(aff == 'owner')
Popup.create('mucadmin', html_full); Popup.create('mucadmin', html_full);
if(aff == 'admin') if(aff == 'admin')
Popup.create('mucadmin', html_partial); Popup.create('mucadmin', html_partial);
// Associate the events // Associate the events
self.instance(); self.instance();
// We get the affiliated user's privileges // We get the affiliated user's privileges
if(aff == 'owner') { if(aff == 'owner') {
self.query(xid, 'member'); self.query(xid, 'member');
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') {
@ -196,10 +197,10 @@ var MUCAdmin = (function () {
try { try {
var path = $(element).parent(); var path = $(element).parent();
// We first hide the container of the input // We first hide the container of the input
path.hide(); path.hide();
// Then, we add a special class to the input // Then, we add a special class to the input
path.find('input').addClass('aut-dustbin'); path.find('input').addClass('aut-dustbin');
} catch(e) { } catch(e) {
@ -222,20 +223,20 @@ var MUCAdmin = (function () {
try { try {
var hash = hex_md5(xid + affiliation); var hash = hex_md5(xid + affiliation);
// Add the HTML code // Add the HTML code
$('#mucadmin .aut-' + affiliation + ' .aut-add').after( $('#mucadmin .aut-' + affiliation + ' .aut-add').after(
'<div class="one-aut ' + hash + '">' + '<div class="one-aut ' + hash + '">' +
'<input id="aut-' + affiliation + '" name="' + affiliation + '" type="text" class="mucadmin-i" value="' + xid + '" />' + '<input id="aut-' + affiliation + '" name="' + affiliation + '" type="text" class="mucadmin-i" value="' + xid + '" />' +
'<a href="#" class="aut-remove">[-]</a>' + '<a href="#" class="aut-remove">[-]</a>' +
'</div>' '</div>'
); );
// Click event // Click event
$('#mucadmin .' + hash + ' .aut-remove').click(function() { $('#mucadmin .' + hash + ' .aut-remove').click(function() {
return self.removeInput(this); return self.removeInput(this);
}); });
// Focus on the input we added // Focus on the input we added
if(!xid) { if(!xid) {
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
@ -265,14 +266,14 @@ var MUCAdmin = (function () {
// We parse the received xml // We parse the received xml
var xid = $(this).attr('jid'); var xid = $(this).attr('jid');
var affiliation = $(this).attr('affiliation'); var affiliation = $(this).attr('affiliation');
// We create one input for one XID // We create one input for one XID
self.addInput(xid, affiliation); self.addInput(xid, affiliation);
}); });
// Hide the wait icon // Hide the wait icon
$('#mucadmin .wait').hide(); $('#mucadmin .wait').hide();
Console.log('MUC admin items received: ' + Common.fullXID(Common.getStanzaFrom(iq))); Console.log('MUC admin items received: ' + Common.fullXID(Common.getStanzaFrom(iq)));
} catch(e) { } catch(e) {
Console.error('MUCAdmin.handleAuth', e); Console.error('MUCAdmin.handleAuth', e);
@ -293,16 +294,16 @@ var MUCAdmin = (function () {
try { try {
// Show the wait icon // Show the wait icon
$('#mucadmin .wait').show(); $('#mucadmin .wait').show();
// New IQ // New IQ
var iq = new JSJaCIQ(); var iq = new JSJaCIQ();
iq.setTo(xid); iq.setTo(xid);
iq.setType('get'); iq.setType('get');
var iqQuery = iq.setQuery(NS_MUC_ADMIN); var iqQuery = iq.setQuery(NS_MUC_ADMIN);
iqQuery.appendChild(iq.buildNode('item', {'affiliation': type, 'xmlns': NS_MUC_ADMIN})); iqQuery.appendChild(iq.buildNode('item', {'affiliation': type, 'xmlns': NS_MUC_ADMIN}));
con.send(iq, self.handleAuth); con.send(iq, self.handleAuth);
} catch(e) { } catch(e) {
Console.error('MUCAdmin.query', e); Console.error('MUCAdmin.query', e);
@ -322,7 +323,7 @@ var MUCAdmin = (function () {
try { try {
// We get the new topic // We get the new topic
var topic = $('.mucadmin-topic textarea').val(); var topic = $('.mucadmin-topic textarea').val();
// We send the new topic if not blank // We send the new topic if not blank
if(topic) { if(topic) {
var m = new JSJaCMessage(); var m = new JSJaCMessage();
@ -330,7 +331,7 @@ var MUCAdmin = (function () {
m.setType('groupchat'); m.setType('groupchat');
m.setSubject(topic); m.setSubject(topic);
con.send(m); con.send(m);
Console.info('MUC admin topic sent: ' + topic); Console.info('MUC admin topic sent: ' + topic);
} }
} catch(e) { } catch(e) {
@ -355,7 +356,7 @@ var MUCAdmin = (function () {
$.each(types, function(i) { $.each(types, function(i) {
// We get the current type // We get the current type
var tType = types[i]; var tType = types[i];
// We loop for all the elements // We loop for all the elements
$('.mucadmin-aut .aut-' + tType + ' input').each(function() { $('.mucadmin-aut .aut-' + tType + ' input').each(function() {
// We get the needed values // We get the needed values
@ -368,7 +369,7 @@ var MUCAdmin = (function () {
} }
}); });
}); });
Console.info('MUC admin authorizations form sent: ' + xid); Console.info('MUC admin authorizations form sent: ' + xid);
} catch(e) { } catch(e) {
Console.error('MUCAdmin.sendAuth', e); Console.error('MUCAdmin.sendAuth', e);
@ -397,13 +398,13 @@ var MUCAdmin = (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', { var item = iqQuery.appendChild(iq.buildNode('item', {
'jid': user_xid, 'jid': user_xid,
'affiliation': affiliation, 'affiliation': affiliation,
'xmlns': NS_MUC_ADMIN 'xmlns': NS_MUC_ADMIN
})); }));
con.send(iq, Errors.handleReply); con.send(iq, Errors.handleReply);
} catch(e) { } catch(e) {
Console.error('MUCAdmin.setAffiliation', e); Console.error('MUCAdmin.setAffiliation', e);
@ -426,20 +427,21 @@ var MUCAdmin = (function () {
var room = Common.fullXID(Common.getStanzaFrom(iq)); var room = Common.fullXID(Common.getStanzaFrom(iq));
var hash = hex_md5(room); var hash = hex_md5(room);
Interface.quitThisChat(room, hash, 'groupchat'); Interface.quitThisChat(room, hash, 'groupchat');
// We close the muc admin popup // We close the muc admin popup
self.close(); self.close();
// We tell the user that all is okay // We tell the user that all is okay
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);
} }
// We hide the wait icon // We hide the wait icon
$('#mucadmin .wait').hide(); $('#mucadmin .wait').hide();
} catch(e) { } catch(e) {
@ -460,14 +462,14 @@ var MUCAdmin = (function () {
try { try {
// We ask the server to delete the room // We ask the server to delete the room
var iq = new JSJaCIQ(); var iq = new JSJaCIQ();
iq.setTo(xid); iq.setTo(xid);
iq.setType('set'); iq.setType('set');
var iqQuery = iq.setQuery(NS_MUC_OWNER); var iqQuery = iq.setQuery(NS_MUC_OWNER);
iqQuery.appendChild(iq.buildNode('destroy', {'xmlns': NS_MUC_OWNER})); iqQuery.appendChild(iq.buildNode('destroy', {'xmlns': NS_MUC_OWNER}));
con.send(iq, self.handleDestroyIQ); con.send(iq, self.handleDestroyIQ);
Console.info('MUC admin destroy sent: ' + xid); Console.info('MUC admin destroy sent: ' + xid);
} catch(e) { } catch(e) {
Console.error('MUCAdmin.destroyIQ', e); Console.error('MUCAdmin.destroyIQ', e);
@ -488,10 +490,10 @@ var MUCAdmin = (function () {
try { try {
// We get the XID of the current room // We get the XID of the current room
var xid = $('#mucadmin .mucadmin-head-jid').text(); var xid = $('#mucadmin .mucadmin-head-jid').text();
// We show the wait icon // We show the wait icon
$('#mucadmin .wait').show(); $('#mucadmin .wait').show();
// We send the iq // We send the iq
self.destroyIQ(xid); self.destroyIQ(xid);
} catch(e) { } catch(e) {
@ -511,10 +513,10 @@ var MUCAdmin = (function () {
try { try {
// We get the XID of the current room // We get the XID of the current room
var xid = $('#mucadmin .mucadmin-head-jid').text(); var xid = $('#mucadmin .mucadmin-head-jid').text();
// We change the room topic // We change the room topic
self.sendTopic(xid); self.sendTopic(xid);
// We send the needed queries // We send the needed queries
DataForm.send('x', 'submit', 'submit', $('#mucadmin .mucadmin-results').attr('data-session'), xid, '', '', 'mucadmin'); DataForm.send('x', 'submit', 'submit', $('#mucadmin .mucadmin-results').attr('data-session'), xid, '', '', 'mucadmin');
self.sendAuth(xid); self.sendAuth(xid);
@ -535,7 +537,7 @@ var MUCAdmin = (function () {
try { try {
// We send the new options // We send the new options
self.send(); self.send();
// And we quit the popup // And we quit the popup
return self.close(); return self.close();
} catch(e) { } catch(e) {
@ -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

@ -29,10 +29,10 @@ var Music = (function () {
try { try {
var path = '.music-content'; var path = '.music-content';
// Show the music bubble // Show the music bubble
Bubble.show(path); Bubble.show(path);
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
$(path + ' input').focus(); $(path + ' input').focus();
}); });
@ -58,71 +58,70 @@ var Music = (function () {
var path = '.music-content '; var path = '.music-content ';
var content = path + '.list'; var content = path + '.list';
var path_type = content + ' .' + type; var path_type = content + ' .' + type;
// Create the result container // Create the result container
if(!Common.exists(path_type)) { if(!Common.exists(path_type)) {
var code = '<div class="' + type + '"></div>'; var code = '<div class="' + type + '"></div>';
if(type == 'local') if(type == 'local') {
$(content).prepend(code); $(content).prepend(code);
else } else {
$(content).append(code); $(content).append(code);
}
} }
// Fill the results // Fill the results
$(xml).find('track').each(function() { $(xml).find('track').each(function() {
// Parse the XML // Parse the XML
var id = $(this).find('id').text(); var this_sel = $(this);
var title = $(this).find('name').text();
var artist = $(this).find('artist').text(); var id = this_sel.find('id').text() || hex_md5(uri);
var source = $(this).find('source').text(); var title = this_sel.find('name').text();
var duration = $(this).find('duration').text(); var artist = this_sel.find('artist').text();
var uri = $(this).find('url').text(); var source = this_sel.find('source').text();
var mime = $(this).find('type').text(); var duration = this_sel.find('duration').text();
var uri = this_sel.find('url').text();
// No ID? var mime = this_sel.find('type').text() || 'audio/ogg';
if(!id)
id = hex_md5(uri);
// No MIME?
if(!mime)
mime = 'audio/ogg';
// Local URL? // Local URL?
if(type == 'local') if(type == 'local') {
uri = Utils.generateURL(uri); uri = Utils.generateURL(uri);
}
// Append the HTML code // Append the HTML code
$(path_type).append('<a href="#" class="song" data-id="' + id + '">' + title + '</a>'); $(path_type).append('<a href="#" class="song" data-id="' + id + '">' + title + '</a>');
// 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() {
return self.add(id, title, artist, source, duration, uri, mime, type); return self.add(id, title, artist, source, duration, uri, mime, type);
}); });
}); });
// The search is finished // The search is finished
if(Common.exists(content + ' .jamendo') && Common.exists(content + ' .local')) { if(Common.exists(content + ' .jamendo') && Common.exists(content + ' .local')) {
// Get the result values // Get the result values
var jamendo = $(content + ' .jamendo').text(); var jamendo = $(content + ' .jamendo').text();
var local = $(content + ' .local').text(); var local = $(content + ' .local').text();
// Enable the input // Enable the input
$(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);
@ -140,24 +139,27 @@ var Music = (function () {
try { try {
var path = '.music-content '; var path = '.music-content ';
// We get the input string // We get the input string
var string = $(path + 'input').val(); var string = $(path + 'input').val();
// We lock the search input // We lock the search input
$(path + 'input').attr('disabled', true); $(path + 'input').attr('disabled', true);
// We reset the results // We reset the results
$(path + '.list div').remove(); $(path + '.list div').remove();
$(path + '.no-results').hide(); $(path + '.no-results').hide();
// Get the Jamendo results // Get the Jamendo results
$.get('./server/music-search.php', {searchquery: string, location: 'jamendo'}, function(data) { $.get('./server/music-search.php', {searchquery: string, location: 'jamendo'}, function(data) {
self.parse(data, 'jamendo'); self.parse(data, 'jamendo');
}); });
// 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,35 +179,37 @@ 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.');
} }
} catch(e) { } catch(e) {
@ -236,42 +240,39 @@ var Music = (function () {
if(Features.enabledPEP()) { if(Features.enabledPEP()) {
var iq = new JSJaCIQ(); var iq = new JSJaCIQ();
iq.setType('set'); iq.setType('set');
// Create the main PubSub nodes // Create the main PubSub nodes
var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB}); var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB});
var publish = pubsub.appendChild(iq.buildNode('publish', {'node': NS_TUNE, 'xmlns': NS_PUBSUB})); var publish = pubsub.appendChild(iq.buildNode('publish', {'node': NS_TUNE, 'xmlns': NS_PUBSUB}));
var item = publish.appendChild(iq.buildNode('item', {'xmlns': NS_PUBSUB})); var item = publish.appendChild(iq.buildNode('item', {'xmlns': NS_PUBSUB}));
var tune = item.appendChild(iq.buildNode('tune', {'xmlns': NS_TUNE})); var tune = item.appendChild(iq.buildNode('tune', {'xmlns': NS_TUNE}));
// 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));
} }
} }
} }
con.send(iq); con.send(iq);
Console.info('New tune sent: ' + title); Console.info('New tune sent: ' + title);
} }
} catch(e) { } catch(e) {
@ -298,27 +299,29 @@ 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');
// We set the actived class // We set the actived class
$('#top-content .music').addClass('actived'); $('#top-content .music').addClass('actived');
// We set a current played track indicator // We set a current played track indicator
$(path + '.list a').removeClass('playing'); $(path + '.list a').removeClass('playing');
$(path + 'a[data-id="' + id + '"]').addClass('playing'); $(path + 'a[data-id="' + id + '"]').addClass('playing');
// We publish what we listen // We publish what we listen
self.publish(title, artist, source, duration, uri); self.publish(title, artist, source, duration, uri);
} catch(e) { } catch(e) {
@ -345,7 +348,7 @@ var Music = (function () {
if(e.keyCode == 13 && $(this).val()) { if(e.keyCode == 13 && $(this).val()) {
self.search(); self.search();
} }
// Escape : quit // Escape : quit
if(e.keyCode == 27) { if(e.keyCode == 27) {
Bubble.close(); Bubble.close();

View file

@ -32,9 +32,9 @@ var Name = (function () {
var iq = new JSJaCIQ(); var iq = new JSJaCIQ();
iq.setType('get'); iq.setType('get');
iq.setTo(xid); iq.setTo(xid);
iq.appendNode('vCard', {'xmlns': NS_VCARD}); iq.appendNode('vCard', {'xmlns': NS_VCARD});
con.send(iq, self.handleAddUser); con.send(iq, self.handleAddUser);
} catch(e) { } catch(e) {
Console.error('Name.getAddUser', e); Console.error('Name.getAddUser', e);
@ -53,18 +53,20 @@ 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');
// Get the names // Get the names
if(iq.getType() == 'result') { if(iq.getType() == 'result') {
var full_name = self.generateBuddy(iq)[0]; var full_name = self.generateBuddy(iq)[0];
if(full_name) if(full_name) {
$('.add-contact-name').val(full_name); $('.add-contact-name').val(full_name);
}
} }
} catch(e) { } catch(e) {
Console.error('Name.handleAddUser', e); Console.error('Name.handleAddUser', e);
@ -85,29 +87,30 @@ 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) {
pFull = pGiven; pFull = pGiven;
// 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) {
Console.error('Name.generateBuddy', e); Console.error('Name.generateBuddy', e);
@ -127,29 +130,29 @@ var Name = (function () {
try { try {
// Initialize // Initialize
var cname, bname; var cname, bname;
// Cut the XID resource // Cut the XID resource
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) {
Console.error('Name.getBuddy', e); Console.error('Name.getBuddy', e);
@ -168,11 +171,12 @@ var Name = (function () {
try { try {
// Try to read the user nickname // Try to read the user nickname
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) {
Console.error('Name.getNick', e); Console.error('Name.getNick', e);
@ -191,11 +195,12 @@ var Name = (function () {
try { try {
// 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) {
Console.error('Name.get', e); Console.error('Name.get', e);

View file

@ -50,29 +50,26 @@ var Notification = (function () {
var notif = '#top-content .notifications'; var notif = '#top-content .notifications';
var nothing = '.notifications-content .nothing'; var nothing = '.notifications-content .nothing';
var empty = '.notifications-content .empty'; var empty = '.notifications-content .empty';
// Get the notifications number // Get the notifications number
var number = $('.one-notification').size(); var number = $('.one-notification').size();
// Remove the red notify bubble // Remove the red notify bubble
$(notif + ' .notify').remove(); $(notif + ' .notify').remove();
// Any notification? // Any notification?
if(number) { if(number) {
$(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();
// Purge the social inbox node // Purge the social inbox node
self.purge(); self.purge();
} }
// Update the page title // Update the page title
Interface.updateTitle(); Interface.updateTitle();
} catch(e) { } catch(e) {
@ -96,142 +93,144 @@ 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) {
id = hex_md5(type + from); id = hex_md5(type + from);
} }
// Generate the text to be displayed // Generate the text to be displayed
var text, action, code; var text, action, code;
var yes_path = 'href="#"'; var yes_path = 'href="#"';
// User things // User things
from = Common.bareXID(from); from = Common.bareXID(from);
var hash = hex_md5(from); var hash = hex_md5(from);
switch(type) { switch(type) {
case 'subscribe': case 'subscribe':
// Get the name to display // Get the name to display
var display_name = data[1]; var display_name = data[1];
if(!display_name) if(!display_name)
display_name = data[0]; display_name = data[0];
text = '<b>' + display_name.htmlEnc() + '</b> ' + Common._e("would like to add you as a friend.") + ' ' + Common._e("Do you accept?"); text = '<b>' + display_name.htmlEnc() + '</b> ' + Common._e("would like to add you as a friend.") + ' ' + Common._e("Do you accept?");
break; break;
case 'invite_room': case 'invite_room':
text = '<b>' + Name.getBuddy(from).htmlEnc() + '</b> ' + Common._e("would like you to join this chatroom:") + ' <em>' + data[0].htmlEnc() + '</em> ' + Common._e("Do you accept?"); text = '<b>' + Name.getBuddy(from).htmlEnc() + '</b> ' + Common._e("would like you to join this chatroom:") + ' <em>' + data[0].htmlEnc() + '</em> ' + Common._e("Do you accept?");
break; break;
case 'request': case 'request':
text = '<b>' + from.htmlEnc() + '</b> ' + Common._e("would like to get authorization.") + ' ' + Common._e("Do you accept?"); text = '<b>' + from.htmlEnc() + '</b> ' + Common._e("would like to get authorization.") + ' ' + Common._e("Do you accept?");
break; break;
case 'send': case 'send':
yes_path = 'href="' + Common.encodeQuotes(data[1]) + '" target="_blank"'; yes_path = 'href="' + Common.encodeQuotes(data[1]) + '" target="_blank"';
text = '<b>' + Name.getBuddy(from).htmlEnc() + '</b> ' + Common.printf(Common._e("would like to send you a file: “%s”.").htmlEnc(), '<em>' + Utils.truncate(body, 25).htmlEnc() + '</em>') + ' ' + Common._e("Do you accept?"); text = '<b>' + Name.getBuddy(from).htmlEnc() + '</b> ' + Common.printf(Common._e("would like to send you a file: “%s”.").htmlEnc(), '<em>' + Utils.truncate(body, 25).htmlEnc() + '</em>') + ' ' + Common._e("Do you accept?");
break; break;
case 'send_pending': case 'send_pending':
text = '<b>' + Name.getBuddy(from).htmlEnc() + '</b> ' + Common.printf(Common._e("has received a file exchange request: “%s”.").htmlEnc(), '<em>' + Utils.truncate(body, 25).htmlEnc() + '</em>'); text = '<b>' + Name.getBuddy(from).htmlEnc() + '</b> ' + Common.printf(Common._e("has received a file exchange request: “%s”.").htmlEnc(), '<em>' + Utils.truncate(body, 25).htmlEnc() + '</em>');
break; break;
case 'send_accept': case 'send_accept':
text = '<b>' + Name.getBuddy(from).htmlEnc() + '</b> ' + Common.printf(Common._e("has accepted to receive your file: “%s”.").htmlEnc(), '<em>' + Utils.truncate(body, 25).htmlEnc() + '</em>'); text = '<b>' + Name.getBuddy(from).htmlEnc() + '</b> ' + Common.printf(Common._e("has accepted to receive your file: “%s”.").htmlEnc(), '<em>' + Utils.truncate(body, 25).htmlEnc() + '</em>');
break; break;
case 'send_reject': case 'send_reject':
text = '<b>' + Name.getBuddy(from).htmlEnc() + '</b> ' + Common.printf(Common._e("has rejected to receive your file: “%s”.").htmlEnc(), '<em>' + Utils.truncate(body, 25).htmlEnc() + '</em>'); text = '<b>' + Name.getBuddy(from).htmlEnc() + '</b> ' + Common.printf(Common._e("has rejected to receive your file: “%s”.").htmlEnc(), '<em>' + Utils.truncate(body, 25).htmlEnc() + '</em>');
break; break;
case 'send_fail': case 'send_fail':
text = '<b>' + Name.getBuddy(from).htmlEnc() + '</b> ' + Common.printf(Common._e("could not receive your file: “%s”.").htmlEnc(), '<em>' + Utils.truncate(body, 25).htmlEnc() + '</em>'); text = '<b>' + Name.getBuddy(from).htmlEnc() + '</b> ' + Common.printf(Common._e("could not receive your file: “%s”.").htmlEnc(), '<em>' + Utils.truncate(body, 25).htmlEnc() + '</em>');
break; break;
case 'rosterx': case 'rosterx':
text = Common.printf(Common._e("Do you want to see the friends %s suggests you?").htmlEnc(), '<b>' + Name.getBuddy(from).htmlEnc() + '</b>'); text = Common.printf(Common._e("Do you want to see the friends %s suggests you?").htmlEnc(), '<b>' + Name.getBuddy(from).htmlEnc() + '</b>');
break; break;
case 'comment': case 'comment':
text = '<b>' + data[0].htmlEnc() + '</b> ' + Common.printf(Common._e("commented an item you follow: “%s”.").htmlEnc(), '<em>' + Utils.truncate(body, 25).htmlEnc() + '</em>'); text = '<b>' + data[0].htmlEnc() + '</b> ' + Common.printf(Common._e("commented an item you follow: “%s”.").htmlEnc(), '<em>' + Utils.truncate(body, 25).htmlEnc() + '</em>');
break; break;
case 'like': case 'like':
text = '<b>' + data[0].htmlEnc() + '</b> ' + Common.printf(Common._e("liked your post: “%s”.").htmlEnc(), '<em>' + Utils.truncate(body, 25).htmlEnc() + '</em>'); text = '<b>' + data[0].htmlEnc() + '</b> ' + Common.printf(Common._e("liked your post: “%s”.").htmlEnc(), '<em>' + Utils.truncate(body, 25).htmlEnc() + '</em>');
break; break;
case 'quote': case 'quote':
text = '<b>' + data[0].htmlEnc() + '</b> ' + Common.printf(Common._e("quoted you somewhere: “%s”.").htmlEnc(), '<em>' + Utils.truncate(body, 25).htmlEnc() + '</em>'); text = '<b>' + data[0].htmlEnc() + '</b> ' + Common.printf(Common._e("quoted you somewhere: “%s”.").htmlEnc(), '<em>' + Utils.truncate(body, 25).htmlEnc() + '</em>');
break; break;
case 'wall': case 'wall':
text = '<b>' + data[0].htmlEnc() + '</b> ' + Common.printf(Common._e("published on your wall: “%s”.").htmlEnc(), '<em>' + Utils.truncate(body, 25).htmlEnc() + '</em>'); text = '<b>' + data[0].htmlEnc() + '</b> ' + Common.printf(Common._e("published on your wall: “%s”.").htmlEnc(), '<em>' + Utils.truncate(body, 25).htmlEnc() + '</em>');
break; break;
case 'photo': case 'photo':
text = '<b>' + data[0].htmlEnc() + '</b> ' + Common.printf(Common._e("tagged you in a photo (%s).").htmlEnc(), '<em>' + Utils.truncate(body, 25).htmlEnc() + '</em>'); text = '<b>' + data[0].htmlEnc() + '</b> ' + Common.printf(Common._e("tagged you in a photo (%s).").htmlEnc(), '<em>' + Utils.truncate(body, 25).htmlEnc() + '</em>');
break; break;
case 'video': case 'video':
text = '<b>' + data[0].htmlEnc() + '</b> ' + Common.printf(Common._e("tagged you in a video (%s).").htmlEnc(), '<em>' + Utils.truncate(body, 25).htmlEnc() + '</em>'); text = '<b>' + data[0].htmlEnc() + '</b> ' + Common.printf(Common._e("tagged you in a video (%s).").htmlEnc(), '<em>' + Utils.truncate(body, 25).htmlEnc() + '</em>');
break; break;
case 'me_profile_new_success': case 'me_profile_new_success':
yes_path = 'href="' + Common.encodeQuotes(data[1]) + '" target="_blank"'; yes_path = 'href="' + Common.encodeQuotes(data[1]) + '" target="_blank"';
text = '<b>' + data[0].htmlEnc() + '</b> ' + Common._e("validated your account. Your public profile will be available in a few moments.").htmlEnc(); text = '<b>' + data[0].htmlEnc() + '</b> ' + Common._e("validated your account. Your public profile will be available in a few moments.").htmlEnc();
break; break;
case 'me_profile_remove_success': case 'me_profile_remove_success':
yes_path = 'href="' + Common.encodeQuotes(data[1]) + '" target="_blank"'; yes_path = 'href="' + Common.encodeQuotes(data[1]) + '" target="_blank"';
text = '<b>' + data[0].htmlEnc() + '</b> ' + Common._e("has removed your public profile after your request. We will miss you!").htmlEnc(); text = '<b>' + data[0].htmlEnc() + '</b> ' + Common._e("has removed your public profile after your request. We will miss you!").htmlEnc();
break; break;
case 'me_profile_update_success': case 'me_profile_update_success':
yes_path = 'href="' + Common.encodeQuotes(data[1]) + '" target="_blank"'; yes_path = 'href="' + Common.encodeQuotes(data[1]) + '" target="_blank"';
text = '<b>' + data[0].htmlEnc() + '</b> ' + Common._e("has saved your new public profile settings. They will be applied in a few moments.").htmlEnc(); text = '<b>' + data[0].htmlEnc() + '</b> ' + Common._e("has saved your new public profile settings. They will be applied in a few moments.").htmlEnc();
break; break;
case 'me_profile_check_error': case 'me_profile_check_error':
yes_path = 'href="' + Common.encodeQuotes(data[1]) + '" target="_blank"'; yes_path = 'href="' + Common.encodeQuotes(data[1]) + '" target="_blank"';
text = '<b>' + data[0].htmlEnc() + '</b> ' + Common._e("could not validate your account to create or update your public profile. Check your credentials.").htmlEnc(); text = '<b>' + data[0].htmlEnc() + '</b> ' + Common._e("could not validate your account to create or update your public profile. Check your credentials.").htmlEnc();
break; break;
default: default:
break; break;
} }
// No text? // No text?
if(!text) if(!text) {
return; return;
}
// Action links? // Action links?
switch(type) { switch(type) {
// Hide/Show actions // Hide/Show actions
@ -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;
@ -266,53 +266,55 @@ var Notification = (function () {
default: default:
action = '<a ' + yes_path + ' class="yes">' + Common._e("Yes") + '</a><a href="#" class="no">' + Common._e("No") + '</a>'; action = '<a ' + yes_path + ' class="yes">' + Common._e("Yes") + '</a><a href="#" class="no">' + Common._e("No") + '</a>';
} }
if(text) { if(text) {
// We display the notification // We display the notification
if(!Common.exists('.notifications-content .' + id)) { if(!Common.exists('.notifications-content .' + id)) {
// We create the html markup depending of the notification type // We create the html markup depending of the notification type
code = '<div class="one-notification ' + id + ' ' + hash + '" title="' + Common.encodeQuotes(body) + ' - ' + Common._e("This notification is only informative, maybe the data it links to have been removed.") + '" data-type="' + Common.encodeQuotes(type) + '">' + code = '<div class="one-notification ' + id + ' ' + hash + '" title="' + Common.encodeQuotes(body) + ' - ' + Common._e("This notification is only informative, maybe the data it links to have been removed.") + '" data-type="' + Common.encodeQuotes(type) + '">' +
'<div class="avatar-container">' + '<div class="avatar-container">' +
'<img class="avatar" src="' + './images/others/default-avatar.png' + '" alt="" />' + '<img class="avatar" src="' + './images/others/default-avatar.png' + '" alt="" />' +
'</div>' + '</div>' +
'<p class="notification-text">' + text + '</p>' + '<p class="notification-text">' + text + '</p>' +
'<p class="notification-actions">' + '<p class="notification-actions">' +
'<span class="talk-images" />' + '<span class="talk-images" />' +
action + action +
'</p>' + '</p>' +
'</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');
// The yes click function // The yes click 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
$('.' + id + ' a.no').click(function() { $('.' + id + ' a.no').click(function() {
return self.action(type, data, 'no', id); return self.action(type, data, 'no', id);
}); });
// Get the user avatar // Get the user avatar
Avatar.get(from, 'cache', 'true', 'forget'); Avatar.get(from, 'cache', 'true', 'forget');
} }
} }
// We tell the user he has a new pending notification // We tell the user he has a new pending notification
self.check(); self.check();
Console.info('New notification: ' + from); Console.info('New notification: ' + from);
} catch(e) { } catch(e) {
Console.error('Notification.new', e); Console.error('Notification.new', e);
@ -334,42 +336,37 @@ 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]);
// Append the marker // Append the marker
$('#channel .top.individual').append('<input type="hidden" name="comments" value="' + Common.encodeQuotes(data[1]) + '" />'); $('#channel .top.individual').append('<input type="hidden" name="comments" value="' + Common.encodeQuotes(data[1]) + '" />');
} }
self.remove(data[3]); self.remove(data[3]);
} }
// We remove the notification // We remove the notification
$('.notifications-content .' + id).remove(); $('.notifications-content .' + id).remove();
// We check if there's any other pending notification // We check if there's any other pending notification
self.closeEmpty(); self.closeEmpty();
self.check(); self.check();
@ -392,7 +389,7 @@ var Notification = (function () {
try { try {
// Remove notifications // Remove notifications
$('.one-notification').remove(); $('.one-notification').remove();
// Refresh // Refresh
self.closeEmpty(); self.closeEmpty();
self.check(); self.check();
@ -415,12 +412,12 @@ var Notification = (function () {
try { try {
var iq = new JSJaCIQ(); var iq = new JSJaCIQ();
iq.setType('get'); iq.setType('get');
var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB}); var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB});
pubsub.appendChild(iq.buildNode('items', {'node': NS_URN_INBOX, 'xmlns': NS_PUBSUB})); pubsub.appendChild(iq.buildNode('items', {'node': NS_URN_INBOX, 'xmlns': NS_PUBSUB}));
con.send(iq, self.handle); con.send(iq, self.handle);
Console.log('Getting social notifications...'); Console.log('Getting social notifications...');
} catch(e) { } catch(e) {
Console.error('Notification.get', e); Console.error('Notification.get', e);
@ -442,40 +439,44 @@ var Notification = (function () {
if((stanza.getType() == 'error') && $(stanza.getNode()).find('item-not-found').size()) { if((stanza.getType() == 'error') && $(stanza.getNode()).find('item-not-found').size()) {
// The node may not exist, create it! // The node may not exist, create it!
Pubsub.setup('', NS_URN_INBOX, '1', '1000000', 'whitelist', 'open', true); Pubsub.setup('', NS_URN_INBOX, '1', '1000000', 'whitelist', 'open', true);
Console.warn('Error while getting social notifications, trying to reconfigure the Pubsub node!'); Console.warn('Error while getting social notifications, trying to reconfigure the Pubsub node!');
} }
// Selector // Selector
var items = $(stanza.getNode()).find('item'); var items = $(stanza.getNode()).find('item');
// 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);
}); });
Console.info(items.size() + ' social notification(s) got!'); Console.info(items.size() + ' social notification(s) got!');
} catch(e) { } catch(e) {
Console.error('Notification.handle', e); Console.error('Notification.handle', e);
@ -499,38 +500,38 @@ var Notification = (function () {
try { try {
// Notification ID // Notification ID
var id = hex_md5(xid + text + DateUtils.getTimeStamp()); var id = hex_md5(xid + text + DateUtils.getTimeStamp());
// IQ // IQ
var iq = new JSJaCIQ(); var iq = new JSJaCIQ();
iq.setType('set'); iq.setType('set');
iq.setTo(xid); iq.setTo(xid);
// ATOM content // ATOM content
var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB}); var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB});
var publish = pubsub.appendChild(iq.buildNode('publish', {'node': NS_URN_INBOX, 'xmlns': NS_PUBSUB})); var publish = pubsub.appendChild(iq.buildNode('publish', {'node': NS_URN_INBOX, 'xmlns': NS_PUBSUB}));
var item = publish.appendChild(iq.buildNode('item', {'id': id, 'xmlns': NS_PUBSUB})); var item = publish.appendChild(iq.buildNode('item', {'id': id, 'xmlns': NS_PUBSUB}));
var entry = item.appendChild(iq.buildNode('entry', {'xmlns': NS_ATOM})); var entry = item.appendChild(iq.buildNode('entry', {'xmlns': NS_ATOM}));
// Notification author (us) // Notification author (us)
var author = entry.appendChild(iq.buildNode('author', {'xmlns': NS_ATOM})); var author = entry.appendChild(iq.buildNode('author', {'xmlns': NS_ATOM}));
author.appendChild(iq.buildNode('name', {'xmlns': NS_ATOM}, Name.get())); author.appendChild(iq.buildNode('name', {'xmlns': NS_ATOM}, Name.get()));
author.appendChild(iq.buildNode('uri', {'xmlns': NS_ATOM}, 'xmpp:' + Common.getXID())); author.appendChild(iq.buildNode('uri', {'xmlns': NS_ATOM}, 'xmpp:' + Common.getXID()));
// Notification content // Notification content
entry.appendChild(iq.buildNode('published', {'xmlns': NS_ATOM}, DateUtils.getXMPPTime('utc'))); entry.appendChild(iq.buildNode('published', {'xmlns': NS_ATOM}, DateUtils.getXMPPTime('utc')));
entry.appendChild(iq.buildNode('content', {'type': 'text', 'xmlns': NS_ATOM}, text)); entry.appendChild(iq.buildNode('content', {'type': 'text', 'xmlns': NS_ATOM}, text));
entry.appendChild(iq.buildNode('link', {'rel': 'via', 'title': type, 'href': href, 'xmlns': NS_ATOM})); entry.appendChild(iq.buildNode('link', {'rel': 'via', 'title': type, 'href': href, 'xmlns': NS_ATOM}));
// Any parent item? // Any parent item?
if(parent && parent[0] && parent[1] && parent[2]) { if(parent && parent[0] && parent[1] && parent[2]) {
// Generate the parent XMPP URI // Generate the parent XMPP URI
var parent_href = 'xmpp:' + parent[0] + '?;node=' + encodeURIComponent(parent[1]) + ';item=' + encodeURIComponent(parent[2]); var parent_href = 'xmpp:' + parent[0] + '?;node=' + encodeURIComponent(parent[1]) + ';item=' + encodeURIComponent(parent[2]);
entry.appendChild(iq.buildNode('link', {'rel': 'related', 'href': parent_href, 'xmlns': NS_ATOM})); entry.appendChild(iq.buildNode('link', {'rel': 'related', 'href': parent_href, 'xmlns': NS_ATOM}));
} }
con.send(iq); con.send(iq);
Console.log('Sending a social notification to ' + xid + ' (type: ' + type + ')...'); Console.log('Sending a social notification to ' + xid + ' (type: ' + type + ')...');
} catch(e) { } catch(e) {
Console.error('Notification.send', e); Console.error('Notification.send', e);
@ -550,11 +551,11 @@ var Notification = (function () {
try { try {
var iq = new JSJaCIQ(); var iq = new JSJaCIQ();
iq.setType('set'); iq.setType('set');
var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB}); var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB});
var retract = pubsub.appendChild(iq.buildNode('retract', {'node': NS_URN_INBOX, 'xmlns': NS_PUBSUB})); var retract = pubsub.appendChild(iq.buildNode('retract', {'node': NS_URN_INBOX, 'xmlns': NS_PUBSUB}));
retract.appendChild(iq.buildNode('item', {'id': id, 'xmlns': NS_PUBSUB})); retract.appendChild(iq.buildNode('item', {'id': id, 'xmlns': NS_PUBSUB}));
con.send(iq); con.send(iq);
} catch(e) { } catch(e) {
Console.error('Notification.remove', e); Console.error('Notification.remove', e);
@ -574,10 +575,10 @@ var Notification = (function () {
try { try {
var iq = new JSJaCIQ(); var iq = new JSJaCIQ();
iq.setType('set'); iq.setType('set');
var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB_OWNER}); var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB_OWNER});
pubsub.appendChild(iq.buildNode('purge', {'node': NS_URN_INBOX, 'xmlns': NS_PUBSUB_OWNER})); pubsub.appendChild(iq.buildNode('purge', {'node': NS_URN_INBOX, 'xmlns': NS_PUBSUB_OWNER}));
con.send(iq); con.send(iq);
} catch(e) { } catch(e) {
Console.error('Notification.purge', e); Console.error('Notification.purge', e);
@ -598,12 +599,12 @@ var Notification = (function () {
try { try {
// Process the new height // Process the new height
var max_height = $('#right-content').height() - 22; var max_height = $('#right-content').height() - 22;
// New height too small // New height too small
if(max_height < 250) { if(max_height < 250) {
max_height = 250; max_height = 250;
} }
// Apply the new height // Apply the new height
$('.notifications-content .tools-content-subitem').css('max-height', max_height); $('.notifications-content .tools-content-subitem').css('max-height', max_height);
} catch(e) { } catch(e) {

View file

@ -37,41 +37,42 @@ var OOB = (function () {
// Get some values // Get some values
var id = hex_md5(genID() + to + url + desc); var id = hex_md5(genID() + to + url + desc);
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);
DataStore.setDB(Connection.desktop_hash, 'send/desc', id, desc); DataStore.setDB(Connection.desktop_hash, 'send/desc', id, desc);
var aIQ = new JSJaCIQ(); var aIQ = new JSJaCIQ();
aIQ.setTo(Common.fullXID(to)); aIQ.setTo(Common.fullXID(to));
aIQ.setType('set'); aIQ.setType('set');
aIQ.setID(id); aIQ.setID(id);
// Append the query content // Append the query content
var aQuery = aIQ.setQuery(NS_IQOOB); var aQuery = aIQ.setQuery(NS_IQOOB);
aQuery.appendChild(aIQ.buildNode('url', {'xmlns': NS_IQOOB}, url)); aQuery.appendChild(aIQ.buildNode('url', {'xmlns': NS_IQOOB}, url));
aQuery.appendChild(aIQ.buildNode('desc', {'xmlns': NS_IQOOB}, desc)); aQuery.appendChild(aIQ.buildNode('desc', {'xmlns': NS_IQOOB}, desc));
con.send(aIQ); con.send(aIQ);
} }
// Message stanza? // Message stanza?
else { else {
var aMsg = new JSJaCMessage(); var aMsg = new JSJaCMessage();
aMsg.setTo(Common.bareXID(to)); aMsg.setTo(Common.bareXID(to));
// Append the content // Append the content
aMsg.setBody(desc); aMsg.setBody(desc);
var aX = aMsg.appendNode('x', {'xmlns': NS_XOOB}); var aX = aMsg.appendNode('x', {'xmlns': NS_XOOB});
aX.appendChild(aMsg.buildNode('url', {'xmlns': NS_XOOB}, url)); aX.appendChild(aMsg.buildNode('url', {'xmlns': NS_XOOB}, url));
con.send(aMsg); con.send(aMsg);
} }
Console.log('Sent OOB request to: ' + to + ' (' + desc + ')'); Console.log('Sent OOB request to: ' + to + ' (' + desc + ')');
} catch(e) { } catch(e) {
Console.error('OOB.send', e); Console.error('OOB.send', e);
@ -92,29 +93,25 @@ 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();
} }
// No desc? // No desc?
if(!desc) { if(!desc) {
desc = url; desc = url;
} }
// Open a new notification // Open a new notification
if(type && xid && url && desc) { if(type && xid && url && desc) {
Notification.create('send', xid, [xid, url, type, id, node], desc, hex_md5(xid + url + desc + id)); Notification.create('send', xid, [xid, url, type, id, node], desc, hex_md5(xid + url + desc + id));
@ -140,36 +137,43 @@ 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();
aIQ.setTo(to); aIQ.setTo(to);
aIQ.setID(id); aIQ.setID(id);
// OOB request accepted // OOB request accepted
if(choice == 'accept') { if(choice == 'accept') {
aIQ.setType('result'); aIQ.setType('result');
Console.info('Accepted file request from: ' + to); Console.info('Accepted file request from: ' + to);
} }
// OOB request rejected // OOB request rejected
else { else {
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);
} }
con.send(aIQ); con.send(aIQ);
} catch(e) { } catch(e) {
Console.error('OOB.reply', e); Console.error('OOB.reply', e);
@ -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,54 +217,55 @@ 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');
// Get the values // Get the values
var fID = dData.find('id').text(); var fID = dData.find('id').text();
var fURL = dData.find('url').text(); var fURL = dData.find('url').text();
var fDesc = dData.find('desc').text(); var fDesc = dData.find('desc').text();
// Get the OOB values // Get the OOB values
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 oob_type = $('#page-engine .chat-tools-file' + oob_has).attr('data-oob');
// Reset the file send tool
$('#page-engine .chat-tools-file' + oob_has).removeClass('mini');
$('#page-engine .bubble-file' + oob_has).remove();
// Not available?
if($('#page-engine .chat-tools-file' + oob_has).is(':hidden') && (oob_type == 'iq')) {
Board.openThisError(4);
// Remove the file we sent
if(fURL)
$.get(fURL + '&action=remove');
} }
var xid = page_engine_sel.find('.page-engine-chan' + oob_has).attr('data-xid');
var oob_type = page_engine_sel.find('.chat-tools-file' + oob_has).attr('data-oob');
// Reset the file send tool
page_engine_sel.find('.chat-tools-file' + oob_has).removeClass('mini');
page_engine_sel.find('.bubble-file' + oob_has).remove();
// Not available?
if(page_engine_sel.find('.chat-tools-file' + oob_has).is(':hidden') && (oob_type == 'iq')) {
Board.openThisError(4);
// Remove the file we sent
if(fURL) {
$.get(fURL + '&action=remove');
}
}
// Everything okay? // Everything okay?
else if(fURL && fDesc && !dData.find('error').size()) { else if(fURL && fDesc && !dData.find('error').size()) {
// Send the OOB request // Send the OOB request
self.send(xid, oob_type, fURL, fDesc); self.send(xid, oob_type, fURL, fDesc);
// Notify the sender // Notify the sender
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());
} }
} catch(e) { } catch(e) {

View file

@ -29,191 +29,191 @@ var Options = (function () {
try { try {
// Popup HTML content // Popup HTML content
var html = var html =
'<div class="top">' + Common._e("Edit options") + '</div>' + '<div class="top">' + Common._e("Edit options") + '</div>' +
'<div class="tab">' + '<div class="tab">' +
'<a href="#" class="tab-general tab-active" data-key="1">' + Common._e("General") + '</a>' + '<a href="#" class="tab-general tab-active" data-key="1">' + Common._e("General") + '</a>' +
'<a href="#" class="tab-channel pubsub-hidable pubsub-hidable-cn" data-key="2">' + Common._e("Channel") + '</a>' + '<a href="#" class="tab-channel pubsub-hidable pubsub-hidable-cn" data-key="2">' + Common._e("Channel") + '</a>' +
'<a href="#" class="tab-account" data-key="3">' + Common._e("Account") + '</a>' + '<a href="#" class="tab-account" data-key="3">' + Common._e("Account") + '</a>' +
'</div>' + '</div>' +
'<div class="content">' + '<div class="content">' +
'<div id="conf1" class="lap-active one-lap forms">' + '<div id="conf1" class="lap-active one-lap forms">' +
'<fieldset class="privacy">' + '<fieldset class="privacy">' +
'<legend>' + Common._e("Privacy") + '</legend>' + '<legend>' + Common._e("Privacy") + '</legend>' +
'<div class="geolocation">' + '<div class="geolocation">' +
'<label for="geolocation" class="pep-hidable">' + Common._e("Geolocation") + '</label>' + '<label for="geolocation" class="pep-hidable">' + Common._e("Geolocation") + '</label>' +
'<input id="geolocation" type="checkbox" class="pep-hidable" />' + '<input id="geolocation" type="checkbox" class="pep-hidable" />' +
'</div>' + '</div>' +
'<div class="archiving">' + '<div class="archiving">' +
'<label for="archiving" class="mam-hidable">' + Common._e("Message archiving") + '</label>' + '<label for="archiving" class="mam-hidable">' + Common._e("Message archiving") + '</label>' +
'<select id="archiving" class="mam-hidable">' + '<select id="archiving" class="mam-hidable">' +
'<option value="never">' + Common._e("Disabled") + '</option>' + '<option value="never">' + Common._e("Disabled") + '</option>' +
'<option value="roster">' + Common._e("Store friend chats") + '</option>' + '<option value="roster">' + Common._e("Store friend chats") + '</option>' +
'<option value="always">' + Common._e("Store all chats") + '</option>' + '<option value="always">' + Common._e("Store all chats") + '</option>' +
'</select>' + '</select>' +
'<a href="#" class="linked empty-archives mam-purge-hidable">' + Common._e("Remove all archives") + '</a>' + '<a href="#" class="linked empty-archives mam-purge-hidable">' + Common._e("Remove all archives") + '</a>' +
'</div>' + '</div>' +
'</fieldset>' + '</fieldset>' +
'<fieldset class="application">' + '<fieldset class="application">' +
'<legend>' + Common._e("Application") + '</legend>' + '<legend>' + Common._e("Application") + '</legend>' +
'<div class="sounds">' + '<div class="sounds">' +
'<label for="sounds">' + Common._e("Sounds") + '</label>' + '<label for="sounds">' + Common._e("Sounds") + '</label>' +
'<input id="sounds" type="checkbox" />' + '<input id="sounds" type="checkbox" />' +
'</div>' + '</div>' +
'<div class="showall">' + '<div class="showall">' +
'<label for="showall">' + Common._e("Show all friends") + '</label>' + '<label for="showall">' + Common._e("Show all friends") + '</label>' +
'<input id="showall" type="checkbox" />' + '<input id="showall" type="checkbox" />' +
'</div>' + '</div>' +
'<div class="groupchatpresence">' + '<div class="groupchatpresence">' +
'<label for="groupchatpresence">' + Common._e("Groupchat presence messages") + '</label>' + '<label for="groupchatpresence">' + Common._e("Groupchat presence messages") + '</label>' +
'<input id="groupchatpresence" type="checkbox" />' + '<input id="groupchatpresence" type="checkbox" />' +
'</div>' + '</div>' +
'<div class="noxhtmlimg">' + '<div class="noxhtmlimg">' +
'<label for="noxhtmlimg">' + Common._e("No chat images auto-load") + '</label>' + '<label for="noxhtmlimg">' + Common._e("No chat images auto-load") + '</label>' +
'<input id="noxhtmlimg" type="checkbox" />' + '<input id="noxhtmlimg" type="checkbox" />' +
'</div>' + '</div>' +
'<div class="integratemedias">' + '<div class="integratemedias">' +
'<label for="integratemedias">' + Common._e("Media integration") + '</label>' + '<label for="integratemedias">' + Common._e("Media integration") + '</label>' +
'<input id="integratemedias" type="checkbox" />' + '<input id="integratemedias" type="checkbox" />' +
'</div>' + '</div>' +
'<div class="localarchives mam-showable">' + '<div class="localarchives mam-showable">' +
'<label for="localarchives">' + Common._e("Keep local chat archives") + '</label>' + '<label for="localarchives">' + Common._e("Keep local chat archives") + '</label>' +
'<input id="localarchives" type="checkbox" />' + '<input id="localarchives" type="checkbox" />' +
'</div>' + '</div>' +
'<div class="xmpplinks">' + '<div class="xmpplinks">' +
'<label class="xmpplinks-hidable">' + Common._e("XMPP links") + '</label>' + '<label class="xmpplinks-hidable">' + Common._e("XMPP links") + '</label>' +
'<a href="#" class="linked xmpp-links xmpplinks-hidable">' + Common._e("Open XMPP links with Jappix") + '</a>' + '<a href="#" class="linked xmpp-links xmpplinks-hidable">' + Common._e("Open XMPP links with Jappix") + '</a>' +
'</div>' + '</div>' +
'</fieldset>' + '</fieldset>' +
'<div class="sub-ask sub-ask-mam sub-ask-element">' +
'<div class="sub-ask-top">' +
'<div class="sub-ask-title">' + Common._e("Remove all archives") + '</div>' +
'<a href="#" class="sub-ask-close">X</a>' +
'</div>' +
'<div class="sub-ask-content">' +
'<label>' + Common._e("Password") + '</label>' +
'<input type="password" class="purge-archives check-mam" required="" />' +
'</div>' +
'<a href="#" class="sub-ask-bottom">' + Common._e("Remove") + ' &raquo;</a>' +
'</div>' +
'</div>' +
'<div id="conf2" class="one-lap forms">' +
'<fieldset class="channel">' +
'<legend>' + Common._e("Channel") + '</legend>' +
'<div class="sub-ask sub-ask-mam sub-ask-element">' +
'<div class="sub-ask-top">' +
'<div class="sub-ask-title">' + Common._e("Remove all archives") + '</div>' +
'<a href="#" class="sub-ask-close">X</a>' +
'</div>' +
'<div class="sub-ask-content">' +
'<label>' + Common._e("Password") + '</label>' +
'<input type="password" class="purge-archives check-mam" required="" />' +
'</div>' +
'<a href="#" class="sub-ask-bottom">' + Common._e("Remove") + ' &raquo;</a>' +
'</div>' +
'</div>' +
'<div id="conf2" class="one-lap forms">' +
'<fieldset class="channel">' +
'<legend>' + Common._e("Channel") + '</legend>' +
'<div class="empty-channel">' + '<div class="empty-channel">' +
'<label>' + Common._e("Empty") + '</label>' + '<label>' + Common._e("Empty") + '</label>' +
'<a href="#" class="linked empty-channel">' + Common._e("Empty channel") + '</a>' + '<a href="#" class="linked empty-channel">' + Common._e("Empty channel") + '</a>' +
'</div>' +
'<div class="persistent">' +
'<label>' + Common._e("Persistent") + '</label>' +
'<input id="persistent" type="checkbox" />' +
'</div>' +
'<div class="maxnotices">' +
'<label>' + Common._e("Maximum notices") + '</label>' +
'<select id="maxnotices">' +
'<option value="1">1</option>' +
'<option value="100">100</option>' +
'<option value="1000">1000</option>' +
'<option value="10000">10000</option>' +
'<option value="100000">100000</option>' +
'<option value="1000000">1000000</option>' +
'</select>' +
'</div>' + '</div>' +
'</fieldset>' + '<div class="persistent">' +
'<label>' + Common._e("Persistent") + '</label>' +
'<div class="sub-ask sub-ask-empty sub-ask-element">' + '<input id="persistent" type="checkbox" />' +
'<div class="sub-ask-top">' + '</div>' +
'<div class="sub-ask-title">' + Common._e("Empty channel") + '</div>' +
'<a href="#" class="sub-ask-close">X</a>' + '<div class="maxnotices">' +
'</div>' + '<label>' + Common._e("Maximum notices") + '</label>' +
'<select id="maxnotices">' +
'<div class="sub-ask-content">' + '<option value="1">1</option>' +
'<label>' + Common._e("Password") + '</label>' + '<option value="100">100</option>' +
'<input type="password" class="purge-microblog check-empty" required="" />' + '<option value="1000">1000</option>' +
'</div>' + '<option value="10000">10000</option>' +
'<option value="100000">100000</option>' +
'<a href="#" class="sub-ask-bottom">' + Common._e("Empty") + ' &raquo;</a>' + '<option value="1000000">1000000</option>' +
'</div>' + '</select>' +
'</div>' + '</div>' +
'<div id="conf3" class="one-lap forms">' + '</fieldset>' +
'<fieldset>' +
'<legend>' + Common._e("Account") + '</legend>' + '<div class="sub-ask sub-ask-empty sub-ask-element">' +
'<div class="sub-ask-top">' +
'<label>' + Common._e("Password") + '</label>' + '<div class="sub-ask-title">' + Common._e("Empty channel") + '</div>' +
'<a href="#" class="linked change-password">' + Common._e("Change password") + '</a>' + '<a href="#" class="sub-ask-close">X</a>' +
'</div>' +
'<label>' + Common._e("Delete") + '</label>' +
'<a href="#" class="linked delete-account">' + Common._e("Delete account") + '</a>' + '<div class="sub-ask-content">' +
'</fieldset>' + '<label>' + Common._e("Password") + '</label>' +
'<input type="password" class="purge-microblog check-empty" required="" />' +
'<div class="sub-ask sub-ask-pass sub-ask-element">' + '</div>' +
'<div class="sub-ask-top">' +
'<div class="sub-ask-title">' + Common._e("Change password") + '</div>' + '<a href="#" class="sub-ask-bottom">' + Common._e("Empty") + ' &raquo;</a>' +
'<a href="#" class="sub-ask-close">X</a>' + '</div>' +
'</div>' + '</div>' +
'<div class="sub-ask-content">' + '<div id="conf3" class="one-lap forms">' +
'<label>' + Common._e("Old") + '</label>' + '<fieldset>' +
'<input type="password" class="password-change old" required="" />' + '<legend>' + Common._e("Account") + '</legend>' +
'<label>' + Common._e("New (2 times)") + '</label>' + '<label>' + Common._e("Password") + '</label>' +
'<input type="password" class="password-change new1" required="" />' + '<a href="#" class="linked change-password">' + Common._e("Change password") + '</a>' +
'<input type="password" class="password-change new2" required="" />' +
'</div>' + '<label>' + Common._e("Delete") + '</label>' +
'<a href="#" class="linked delete-account">' + Common._e("Delete account") + '</a>' +
'<a href="#" class="sub-ask-bottom">' + Common._e("Continue") + ' &raquo;</a>' + '</fieldset>' +
'</div>' +
'<div class="sub-ask sub-ask-pass sub-ask-element">' +
'<div class="sub-ask sub-ask-delete sub-ask-element">' + '<div class="sub-ask-top">' +
'<div class="sub-ask-top">' + '<div class="sub-ask-title">' + Common._e("Change password") + '</div>' +
'<div class="sub-ask-title">' + Common._e("Delete account") + '</div>' + '<a href="#" class="sub-ask-close">X</a>' +
'<a href="#" class="sub-ask-close">X</a>' + '</div>' +
'</div>' +
'<div class="sub-ask-content">' +
'<div class="sub-ask-content">' + '<label>' + Common._e("Old") + '</label>' +
'<label>' + Common._e("Password") + '</label>' + '<input type="password" class="password-change old" required="" />' +
'<input type="password" class="delete-account check-password" required="" />' +
'</div>' + '<label>' + Common._e("New (2 times)") + '</label>' +
'<input type="password" class="password-change new1" required="" />' +
'<a href="#" class="sub-ask-bottom">' + Common._e("Delete") + ' &raquo;</a>' + '<input type="password" class="password-change new2" required="" />' +
'</div>' + '</div>' +
'</div>' +
'</div>' + '<a href="#" class="sub-ask-bottom">' + Common._e("Continue") + ' &raquo;</a>' +
'</div>' +
'<div class="bottom">' +
'<div class="wait wait-medium"></div>' + '<div class="sub-ask sub-ask-delete sub-ask-element">' +
'<div class="sub-ask-top">' +
'<a href="#" class="finish save">' + Common._e("Save") + '</a>' + '<div class="sub-ask-title">' + Common._e("Delete account") + '</div>' +
'<a href="#" class="finish cancel">' + Common._e("Cancel") + '</a>' + '<a href="#" class="sub-ask-close">X</a>' +
'</div>' +
'<div class="sub-ask-content">' +
'<label>' + Common._e("Password") + '</label>' +
'<input type="password" class="delete-account check-password" required="" />' +
'</div>' +
'<a href="#" class="sub-ask-bottom">' + Common._e("Delete") + ' &raquo;</a>' +
'</div>' +
'</div>' +
'</div>' +
'<div class="bottom">' +
'<div class="wait wait-medium"></div>' +
'<a href="#" class="finish save">' + Common._e("Save") + '</a>' +
'<a href="#" class="finish cancel">' + Common._e("Cancel") + '</a>' +
'</div>'; '</div>';
// Create the popup // Create the popup
Popup.create('options', html); Popup.create('options', html);
// Apply the features // Apply the features
Features.apply('options'); Features.apply('options');
// Associate the events // Associate the events
self.instance(); self.instance();
} catch(e) { } catch(e) {
@ -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);
@ -332,25 +335,25 @@ var Options = (function () {
var integratemedias = DataStore.getDB(Connection.desktop_hash, 'options', 'integratemedias'); var integratemedias = DataStore.getDB(Connection.desktop_hash, 'options', 'integratemedias');
var localarchives = DataStore.getDB(Connection.desktop_hash, 'options', 'localarchives'); var localarchives = DataStore.getDB(Connection.desktop_hash, 'options', 'localarchives');
var status = DataStore.getDB(Connection.desktop_hash, 'options', 'presence-status'); var status = DataStore.getDB(Connection.desktop_hash, 'options', 'presence-status');
// Create an array to be looped // Create an array to be looped
var oType = ['sounds', 'geolocation', 'roster-showall', 'no-xhtml-images', 'groupchatpresence', 'integratemedias', 'localarchives', 'presence-status']; var oType = ['sounds', 'geolocation', 'roster-showall', 'no-xhtml-images', 'groupchatpresence', 'integratemedias', 'localarchives', 'presence-status'];
var oContent = [sounds, geolocation, showall, noxhtmlimg, groupchatpresence, integratemedias, localarchives, status]; var oContent = [sounds, geolocation, showall, noxhtmlimg, groupchatpresence, integratemedias, localarchives, status];
// New IQ // New IQ
var iq = new JSJaCIQ(); var iq = new JSJaCIQ();
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_OPTIONS})); var storage = query.appendChild(iq.buildNode('storage', {'xmlns': NS_OPTIONS}));
// Loop the array // Loop the array
for(var i in oType) { for(var i in oType) {
storage.appendChild(iq.buildNode('option', {'type': oType[i], 'xmlns': NS_OPTIONS}, oContent[i])); storage.appendChild(iq.buildNode('option', {'type': oType[i], 'xmlns': NS_OPTIONS}, oContent[i]));
} }
con.send(iq, self.handleStore); con.send(iq, self.handleStore);
Console.info('Storing options...'); Console.info('Storing options...');
} catch(e) { } catch(e) {
Console.error('Options.store', e); Console.error('Options.store', e);
@ -390,27 +393,27 @@ var Options = (function () {
try { try {
// We apply the sounds // We apply the sounds
var sounds = '0'; var sounds = '0';
if($('#sounds').filter(':checked').size()) { if($('#sounds').filter(':checked').size()) {
sounds = '1'; sounds = '1';
} }
DataStore.setDB(Connection.desktop_hash, 'options', 'sounds', sounds); DataStore.setDB(Connection.desktop_hash, 'options', 'sounds', sounds);
// We apply the geolocation // We apply the geolocation
if($('#geolocation').filter(':checked').size()) { if($('#geolocation').filter(':checked').size()) {
DataStore.setDB(Connection.desktop_hash, 'options', 'geolocation', '1'); DataStore.setDB(Connection.desktop_hash, 'options', 'geolocation', '1');
// We geolocate the user on the go // We geolocate the user on the go
PEP.geolocate(); PEP.geolocate();
} else { } else {
DataStore.setDB(Connection.desktop_hash, 'options', 'geolocation', '0'); DataStore.setDB(Connection.desktop_hash, 'options', 'geolocation', '0');
// We delete the geolocation informations // We delete the geolocation informations
PEP.sendPosition(); PEP.sendPosition();
DataStore.removeDB(Connection.desktop_hash, 'geolocation', 'now'); DataStore.removeDB(Connection.desktop_hash, 'geolocation', 'now');
} }
// We apply the roster show all // We apply the roster show all
if($('#showall').filter(':checked').size()) { if($('#showall').filter(':checked').size()) {
DataStore.setDB(Connection.desktop_hash, 'options', 'roster-showall', '1'); DataStore.setDB(Connection.desktop_hash, 'options', 'roster-showall', '1');
@ -419,11 +422,11 @@ var Options = (function () {
DataStore.setDB(Connection.desktop_hash, 'options', 'roster-showall', '0'); DataStore.setDB(Connection.desktop_hash, 'options', 'roster-showall', '0');
Interface.showOnlineBuddies('options'); Interface.showOnlineBuddies('options');
} }
// We apply the XHTML-IM images filter // We apply the XHTML-IM images filter
var noxhtmlimg = '1' ? $('#noxhtmlimg').filter(':checked').size() : '0'; var noxhtmlimg = '1' ? $('#noxhtmlimg').filter(':checked').size() : '0';
DataStore.setDB(Connection.desktop_hash, 'options', 'no-xhtml-images', noxhtmlimg); DataStore.setDB(Connection.desktop_hash, 'options', 'no-xhtml-images', noxhtmlimg);
// We apply the groupchat presence messages configuration // We apply the groupchat presence messages configuration
var groupchatpresence = '1' ? $('#groupchatpresence').filter(':checked').size() : '0'; var groupchatpresence = '1' ? $('#groupchatpresence').filter(':checked').size() : '0';
DataStore.setDB(Connection.desktop_hash, 'options', 'groupchatpresence', groupchatpresence); DataStore.setDB(Connection.desktop_hash, 'options', 'groupchatpresence', groupchatpresence);
@ -440,23 +443,23 @@ var Options = (function () {
if(localarchives === '0') { if(localarchives === '0') {
Message.flushLocalArchive(); Message.flushLocalArchive();
} }
// We apply the message archiving // We apply the message archiving
if(Features.enabledMAM()) { if(Features.enabledMAM()) {
MAM.setConfig($('#archiving').val() || 'never'); MAM.setConfig($('#archiving').val() || 'never');
} }
// We apply the microblog configuration // We apply the microblog configuration
var persist = '1' ? $('#persist').filter(':checked').size() : '0'; var persist = '1' ? $('#persist').filter(':checked').size() : '0';
var maximum = $('#maxnotices').val(); var maximum = $('#maxnotices').val();
if(Features.enabledPEP() && (Features.enabledPubSub() || Features.enabledPubSubCN())) { if(Features.enabledPEP() && (Features.enabledPubSub() || Features.enabledPubSubCN())) {
Pubsub.setup('', NS_URN_MBLOG, persist, maximum, '', '', false); Pubsub.setup('', NS_URN_MBLOG, persist, maximum, '', '', false);
} }
// We send the options to the database // We send the options to the database
self.store(); self.store();
// Close the options // Close the options
self.close(); self.close();
} catch(e) { } catch(e) {
@ -479,13 +482,13 @@ var Options = (function () {
try { try {
// Remove the general wait item // Remove the general wait item
Interface.removeGeneralWait(); Interface.removeGeneralWait();
// If no errors // If no errors
if(!Errors.handleReply(iq)) { if(!Errors.handleReply(iq)) {
Connection.clearLastSession(); Connection.clearLastSession();
Connection.quit(); Connection.quit();
Board.openThisInfo(1); Board.openThisInfo(1);
Console.info('Password changed.'); Console.info('Password changed.');
} else { } else {
Console.warn('Password not changed.'); Console.warn('Password not changed.');
@ -510,45 +513,49 @@ var Options = (function () {
var password0 = $('#options .old').val(); var password0 = $('#options .old').val();
var password1 = $('#options .new1').val(); var password1 = $('#options .new1').val();
var password2 = $('#options .new2').val(); var password2 = $('#options .new2').val();
if ((password1 == password2) && (password0 == Utils.getPassword())) { if ((password1 == password2) && (password0 == Utils.getPassword())) {
// We show the waiting image // We show the waiting image
Interface.showGeneralWait(); Interface.showGeneralWait();
// We send the IQ // We send the IQ
var iq = new JSJaCIQ(); var iq = new JSJaCIQ();
iq.setTo(Utils.getServer()); iq.setTo(Utils.getServer());
iq.setType('set'); iq.setType('set');
var iqQuery = iq.setQuery(NS_REGISTER); var iqQuery = iq.setQuery(NS_REGISTER);
iqQuery.appendChild(iq.buildNode('username', {'xmlns': NS_REGISTER}, con.username)); iqQuery.appendChild(iq.buildNode('username', {'xmlns': NS_REGISTER}, con.username));
iqQuery.appendChild(iq.buildNode('password', {'xmlns': NS_REGISTER}, password1)); iqQuery.appendChild(iq.buildNode('password', {'xmlns': NS_REGISTER}, password1));
con.send(iq, self.handlePwdChange); con.send(iq, self.handlePwdChange);
Console.info('Password change sent.'); Console.info('Password change sent.');
} else { } else {
$('.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);
@ -570,14 +577,14 @@ var Options = (function () {
try { try {
// Remove the general wait item // Remove the general wait item
Interface.removeGeneralWait(); Interface.removeGeneralWait();
// If no errors // If no errors
if(!Errors.handleReply(iq)) { if(!Errors.handleReply(iq)) {
Connection.clearLastSession(); Connection.clearLastSession();
Talk.destroy(); Talk.destroy();
Board.openThisInfo(2); Board.openThisInfo(2);
Connection.logout(); Connection.logout();
Console.info('Account deleted.'); Console.info('Account deleted.');
} else { } else {
Console.warn('Account not deleted.'); Console.warn('Account not deleted.');
@ -599,7 +606,7 @@ var Options = (function () {
try { try {
var pwd_input_sel = $('#options .check-mam'); var pwd_input_sel = $('#options .check-mam');
var password = pwd_input_sel.val(); var password = pwd_input_sel.val();
if(password == Utils.getPassword()) { if(password == Utils.getPassword()) {
MAM.purgeArchives(); MAM.purgeArchives();
@ -611,13 +618,14 @@ var Options = (function () {
$('#options .sub-ask-mam .sub-ask-close').click(); $('#options .sub-ask-mam .sub-ask-close').click();
} 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);
@ -640,31 +648,32 @@ var Options = (function () {
try { try {
var pwd_input_sel = $('#options .check-empty'); var pwd_input_sel = $('#options .check-empty');
var password = pwd_input_sel.val(); var password = pwd_input_sel.val();
if(password == Utils.getPassword()) { if(password == Utils.getPassword()) {
// Send the IQ to remove the item (and get eventual error callback) // Send the IQ to remove the item (and get eventual error callback)
var iq = new JSJaCIQ(); var iq = new JSJaCIQ();
iq.setType('set'); iq.setType('set');
var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB_OWNER}); var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB_OWNER});
pubsub.appendChild(iq.buildNode('purge', {'node': NS_URN_MBLOG, 'xmlns': NS_PUBSUB_OWNER})); pubsub.appendChild(iq.buildNode('purge', {'node': NS_URN_MBLOG, 'xmlns': NS_PUBSUB_OWNER}));
con.send(iq, self.handleMicroblogPurge); con.send(iq, self.handleMicroblogPurge);
// Hide the tool // Hide the tool
pwd_input_sel.val(''); pwd_input_sel.val('');
$('#options .sub-ask-empty .sub-ask-close').click(); $('#options .sub-ask-empty .sub-ask-close').click();
Console.info('Microblog purge sent.'); Console.info('Microblog purge sent.');
} 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);
@ -688,7 +697,7 @@ var Options = (function () {
if(!Errors.handleReply(iq)) { if(!Errors.handleReply(iq)) {
// Remove the microblog items // Remove the microblog items
$('.one-update.update_' + hex_md5(Common.getXID())).remove(); $('.one-update.update_' + hex_md5(Common.getXID())).remove();
Console.info('Microblog purged.'); Console.info('Microblog purged.');
} else { } else {
Console.warn('Microblog not purged.'); Console.warn('Microblog not purged.');
@ -711,32 +720,31 @@ var Options = (function () {
try { try {
var password = $('#options .check-password').val(); var password = $('#options .check-password').val();
if(password == Utils.getPassword()) { if(password == Utils.getPassword()) {
// We show the waiting image // We show the waiting image
Interface.showGeneralWait(); Interface.showGeneralWait();
// We send the IQ // We send the IQ
var iq = new JSJaCIQ(); var iq = new JSJaCIQ();
iq.setType('set'); iq.setType('set');
var iqQuery = iq.setQuery(NS_REGISTER); var iqQuery = iq.setQuery(NS_REGISTER);
iqQuery.appendChild(iq.buildNode('remove', {'xmlns': NS_REGISTER})); iqQuery.appendChild(iq.buildNode('remove', {'xmlns': NS_REGISTER}));
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);
@ -761,70 +769,78 @@ var Options = (function () {
var enabled_pubsub_cn = Features.enabledPubSubCN(); var enabled_pubsub_cn = Features.enabledPubSubCN();
var enabled_pep = Features.enabledPEP(); var enabled_pep = Features.enabledPEP();
var sWait = $('#options .content'); var sWait = $('#options .content');
// Show the waiting items if necessary // Show the waiting items if necessary
if(enabled_mam || (enabled_pep && (enabled_pubsub || enabled_pubsub_cn))) { if(enabled_mam || (enabled_pep && (enabled_pubsub || enabled_pubsub_cn))) {
$('#options .wait').show(); $('#options .wait').show();
$('#options .finish:first').addClass('disabled'); $('#options .finish:first').addClass('disabled');
} }
// We get the archiving configuration // We get the archiving configuration
if(enabled_mam) { if(enabled_mam) {
sWait.addClass('mam'); sWait.addClass('mam');
MAM.getConfig(); MAM.getConfig();
} }
// We get the microblog configuration // We get the microblog configuration
if((enabled_pubsub || enabled_pubsub_cn) && enabled_pep) { if((enabled_pubsub || enabled_pubsub_cn) && enabled_pep) {
sWait.addClass('microblog'); sWait.addClass('microblog');
Microblog.getConfig(); Microblog.getConfig();
} }
// 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);
} }
@ -845,80 +861,80 @@ var Options = (function () {
// Yet active? // Yet active?
if($(this).hasClass('tab-active')) if($(this).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).attr('data-key'));
return self.switchTab(key); return self.switchTab(key);
}); });
$('#options .linked').click(function() { $('#options .linked').click(function() {
$('#options .sub-ask').hide(); $('#options .sub-ask').hide();
$('#options .forms').removeClass('in_background'); $('#options .forms').removeClass('in_background');
}); });
$('#options .xmpp-links').click(function() { $('#options .xmpp-links').click(function() {
Utils.xmppLinksHandler(); Utils.xmppLinksHandler();
return false; return false;
}); });
$('#options .empty-archives').click(function() { $('#options .empty-archives').click(function() {
var selector = '#options .sub-ask-mam'; var selector = '#options .sub-ask-mam';
$(selector).show(); $(selector).show();
$('#options .forms').addClass('in_background'); $('#options .forms').addClass('in_background');
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
$(selector + ' input').focus(); $(selector + ' input').focus();
}); });
return false; return false;
}); });
$('#options .empty-channel').click(function() { $('#options .empty-channel').click(function() {
var selector = '#options .sub-ask-empty'; var selector = '#options .sub-ask-empty';
$(selector).show(); $(selector).show();
$('#options .forms').addClass('in_background'); $('#options .forms').addClass('in_background');
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
$(selector + ' input').focus(); $(selector + ' input').focus();
}); });
return false; return false;
}); });
$('#options .change-password').click(function() { $('#options .change-password').click(function() {
var selector = '#options .sub-ask-pass'; var selector = '#options .sub-ask-pass';
$(selector).show(); $(selector).show();
$('#options .forms').addClass('in_background'); $('#options .forms').addClass('in_background');
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
$(selector + ' input:first').focus(); $(selector + ' input:first').focus();
}); });
return false; return false;
}); });
$('#options .delete-account').click(function() { $('#options .delete-account').click(function() {
var selector = '#options .sub-ask-delete'; var selector = '#options .sub-ask-delete';
$(selector).show(); $(selector).show();
$('#options .forms').addClass('in_background'); $('#options .forms').addClass('in_background');
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
$(selector + ' input').focus(); $(selector + ' input').focus();
}); });
return false; return false;
}); });
$('#options .sub-ask-pass .sub-ask-bottom').click(function() { $('#options .sub-ask-pass .sub-ask-bottom').click(function() {
return self.sendNewPassword(); return self.sendNewPassword();
}); });
$('#options .sub-ask-mam .sub-ask-bottom').click(function() { $('#options .sub-ask-mam .sub-ask-bottom').click(function() {
return self.purgeMyArchives(); return self.purgeMyArchives();
}); });
@ -926,48 +942,55 @@ var Options = (function () {
$('#options .sub-ask-empty .sub-ask-bottom').click(function() { $('#options .sub-ask-empty .sub-ask-bottom').click(function() {
return self.purgeMyMicroblog(); return self.purgeMyMicroblog();
}); });
$('#options .sub-ask-delete .sub-ask-bottom').click(function() { $('#options .sub-ask-delete .sub-ask-bottom').click(function() {
return self.deleteMyAccount(); return self.deleteMyAccount();
}); });
$('#options .sub-ask-close').click(function() { $('#options .sub-ask-close').click(function() {
$('#options .sub-ask').hide(); $('#options .sub-ask').hide();
$('#options .forms').removeClass('in_background'); $('#options .forms').removeClass('in_background');
return false; return false;
}); });
$('#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;
}); });
// The keyup events // The keyup events
$('#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
self.load(); self.load();
} catch(e) { } catch(e) {

File diff suppressed because it is too large Load diff

View file

@ -34,27 +34,27 @@ var Popup = (function () {
if(Common.exists('#' + id)) { if(Common.exists('#' + id)) {
return false; return false;
} }
// Popop on top of another one? // Popop on top of another one?
var top_of = Common.exists('div.lock:has(div.popup)'); var top_of = Common.exists('div.lock:has(div.popup)');
// Append the popup code // Append the popup code
$('body').append( $('body').append(
'<div id="' + id + '" class="lock removable">' + '<div id="' + id + '" class="lock removable">' +
'<div class="popup">' + '<div class="popup">' +
content + content +
'</div>' + '</div>' +
'</div>' '</div>'
); );
// Avoids darker popup background (if on top of another popup) // Avoids darker popup background (if on top of another popup)
if(top_of) { if(top_of) {
$('#' + id).css('background', 'transparent'); $('#' + id).css('background', 'transparent');
} }
// Attach popup events // Attach popup events
self.instance(id); self.instance(id);
return true; return true;
} catch(e) { } catch(e) {
Console.error('Popup.create', e); Console.error('Popup.create', e);
@ -74,10 +74,10 @@ var Popup = (function () {
try { try {
// Stop the popup timers // Stop the popup timers
$('#' + id + ' *').stopTime(); $('#' + id + ' *').stopTime();
// Remove the popup // Remove the popup
$('#' + id).remove(); $('#' + id).remove();
// Manage input focus // Manage input focus
Interface.inputFocus(); Interface.inputFocus();
} catch(e) { } catch(e) {
@ -102,7 +102,7 @@ var Popup = (function () {
if($(evt.target).is('.lock:not(.unavoidable)')) { if($(evt.target).is('.lock:not(.unavoidable)')) {
// Destroy the popup // Destroy the popup
self.destroy(id); self.destroy(id);
return false; return false;
} }
}); });

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -40,12 +40,12 @@ var Pubsub = (function () {
// Create the PubSub node // Create the PubSub node
var iq = new JSJaCIQ(); var iq = new JSJaCIQ();
iq.setType('set'); iq.setType('set');
// Any external entity? // Any external entity?
if(entity) { if(entity) {
iq.setTo(entity); iq.setTo(entity);
} }
// Create it? // Create it?
var pubsub; var pubsub;
@ -55,38 +55,38 @@ var Pubsub = (function () {
} else { } else {
pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB_OWNER}); pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB_OWNER});
} }
// Configure it! // Configure it!
var configure = pubsub.appendChild(iq.buildNode('configure', {'node': node, 'xmlns': NS_PUBSUB})); var configure = pubsub.appendChild(iq.buildNode('configure', {'node': node, 'xmlns': NS_PUBSUB}));
var x = configure.appendChild(iq.buildNode('x', {'xmlns': NS_XDATA, 'type': 'submit'})); var x = configure.appendChild(iq.buildNode('x', {'xmlns': NS_XDATA, 'type': 'submit'}));
var field1 = x.appendChild(iq.buildNode('field', {'var': 'FORM_TYPE', 'type': 'hidden', 'xmlns': NS_XDATA})); var field1 = x.appendChild(iq.buildNode('field', {'var': 'FORM_TYPE', 'type': 'hidden', 'xmlns': NS_XDATA}));
field1.appendChild(iq.buildNode('value', {'xmlns': NS_XDATA}, NS_PUBSUB_NC)); field1.appendChild(iq.buildNode('value', {'xmlns': NS_XDATA}, NS_PUBSUB_NC));
// Persist items? // Persist items?
if(persist) { if(persist) {
var field2 = x.appendChild(iq.buildNode('field', {'var': 'pubsub#persist_items', 'xmlns': NS_XDATA})); var field2 = x.appendChild(iq.buildNode('field', {'var': 'pubsub#persist_items', 'xmlns': NS_XDATA}));
field2.appendChild(iq.buildNode('value', {'xmlns': NS_XDATA}, persist)); field2.appendChild(iq.buildNode('value', {'xmlns': NS_XDATA}, persist));
} }
// Maximum items? // Maximum items?
if(maximum) { if(maximum) {
var field3 = x.appendChild(iq.buildNode('field', {'var': 'pubsub#max_items', 'xmlns': NS_XDATA})); var field3 = x.appendChild(iq.buildNode('field', {'var': 'pubsub#max_items', 'xmlns': NS_XDATA}));
field3.appendChild(iq.buildNode('value', {'xmlns': NS_XDATA}, maximum)); field3.appendChild(iq.buildNode('value', {'xmlns': NS_XDATA}, maximum));
} }
// Access rights? // Access rights?
if(access) { if(access) {
var field4 = x.appendChild(iq.buildNode('field', {'var': 'pubsub#access_model', 'xmlns': NS_XDATA})); var field4 = x.appendChild(iq.buildNode('field', {'var': 'pubsub#access_model', 'xmlns': NS_XDATA}));
field4.appendChild(iq.buildNode('value', {'xmlns': NS_XDATA}, access)); field4.appendChild(iq.buildNode('value', {'xmlns': NS_XDATA}, access));
} }
// Publish rights? // Publish rights?
if(publish) { if(publish) {
var field5 = x.appendChild(iq.buildNode('field', {'var': 'pubsub#publish_model', 'xmlns': NS_XDATA})); var field5 = x.appendChild(iq.buildNode('field', {'var': 'pubsub#publish_model', 'xmlns': NS_XDATA}));
field5.appendChild(iq.buildNode('value', {'xmlns': NS_XDATA}, publish)); field5.appendChild(iq.buildNode('value', {'xmlns': NS_XDATA}, publish));
} }
con.send(iq); con.send(iq);
} catch(e) { } catch(e) {
Console.error('Pubsub.setup', e); Console.error('Pubsub.setup', e);

View file

@ -106,16 +106,17 @@ var Receipts = (function () {
var aMsg = new JSJaCMessage(); var aMsg = new JSJaCMessage();
aMsg.setTo(to); aMsg.setTo(to);
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});
con.send(aMsg); con.send(aMsg);
Console.log('Sent received to: ' + to); Console.log('Sent received to: ' + to);
} catch(e) { } catch(e) {
Console.error('Receipts.sendReceived', e); Console.error('Receipts.sendReceived', e);
@ -136,18 +137,18 @@ var Receipts = (function () {
try { try {
// Line selector // Line selector
var path = $('#' + hash + ' .one-line[data-id="' + id + '"]'); var path = $('#' + hash + ' .one-line[data-id="' + id + '"]');
// Add a received marker // Add a received marker
path.attr('data-received', 'true') path.attr('data-received', 'true')
.removeAttr('data-lost'); .removeAttr('data-lost');
// Group selector // Group selector
var group = path.parent(); var group = path.parent();
// Remove the group marker // Remove the group marker
if(!group.find('.one-line[data-lost]').size()) { if(!group.find('.one-line[data-lost]').size()) {
group.find('b.name').removeClass('talk-images') group.find('b.name').removeClass('talk-images')
.removeAttr('title'); .removeAttr('title');
} }
} catch(e) { } catch(e) {
Console.error('Receipts.messageReceived', e); Console.error('Receipts.messageReceived', e);
@ -170,14 +171,19 @@ var Receipts = (function () {
try { try {
// Fire a check 10 seconds later // Fire a check 10 seconds later
$('#' + hash + ' .one-line[data-id="' + id + '"]').oneTime('10s', function() { $('#' + hash + ' .one-line[data-id="' + id + '"]').oneTime('10s', function() {
var this_sel = $(this);
// Not received? // Not received?
if($(this).attr('data-received') != 'true') { if(this_sel.attr('data-received') != 'true') {
// Add a "lost" marker // Add a "lost" marker
$(this).attr('data-lost', 'true'); this_sel.attr('data-lost', 'true');
// Add a warn on the buddy-name // Add a warn on the buddy-name
$(this).parent().find('b.name').addClass('talk-images') this_sel.parent().find('b.name').addClass('talk-images')
.attr('title', Common._e("Your friend seems not to have received your message(s)!")); .attr(
'title',
Common._e("Your friend seems not to have received your message(s)!")
);
} }
}); });
} catch(e) { } catch(e) {

File diff suppressed because it is too large Load diff

View file

@ -18,7 +18,7 @@ var RosterX = (function () {
* @private * @private
*/ */
var self = {}; var self = {};
/** /**
* Opens the rosterx tools * Opens the rosterx tools
@ -30,32 +30,32 @@ var RosterX = (function () {
try { try {
// Popup HTML content // Popup HTML content
var html = var html =
'<div class="top">' + Common._e("Suggested friends") + '</div>' + '<div class="top">' + Common._e("Suggested friends") + '</div>' +
'<div class="content">' + '<div class="content">' +
'<div class="rosterx-head">' + '<div class="rosterx-head">' +
'<a href="#" class="uncheck">' + Common._e("Uncheck all") + '</a>' + '<a href="#" class="uncheck">' + Common._e("Uncheck all") + '</a>' +
'<a href="#" class="check">' + Common._e("Check all") + '</a>' + '<a href="#" class="check">' + Common._e("Check all") + '</a>' +
'</div>' + '</div>' +
'<div class="results"></div>' + '<div class="results"></div>' +
'</div>' + '</div>' +
'<div class="bottom">' + '<div class="bottom">' +
'<a href="#" class="finish save">' + Common._e("Save") + '</a>' + '<a href="#" class="finish save">' + Common._e("Save") + '</a>' +
'<a href="#" class="finish cancel">' + Common._e("Cancel") + '</a>' + '<a href="#" class="finish cancel">' + Common._e("Cancel") + '</a>' +
'</div>'; '</div>';
// Create the popup // Create the popup
Popup.create('rosterx', html); Popup.create('rosterx', html);
// Associate the events // Associate the events
self.instance(); self.instance();
// Parse the data // Parse the data
self.parse(data); self.parse(data);
Console.log('Roster Item Exchange popup opened.'); Console.log('Roster Item Exchange popup opened.');
} catch(e) { } catch(e) {
Console.error('RosterX.open', e); Console.error('RosterX.open', e);
@ -94,37 +94,47 @@ var RosterX = (function () {
try { try {
// Main selector // Main selector
var x = $(data).find('x[xmlns="' + NS_ROSTERX + '"]:first'); var x = $(data).find('x[xmlns="' + NS_ROSTERX + '"]:first');
// 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,24 +156,27 @@ 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(
'<div class="oneresult">' + '<div class="oneresult">' +
'<input type="checkbox" checked="" data-name="' + Common.encodeQuotes(nick) + '" data-xid="' + Common.encodeQuotes(xid) + '" data-action="' + Common.encodeQuotes(action) + '" data-group="' + Common.encodeQuotes(group) + '" />' + '<input type="checkbox" checked="" data-name="' + Common.encodeQuotes(nick) + '" data-xid="' + Common.encodeQuotes(xid) + '" data-action="' + Common.encodeQuotes(action) + '" data-group="' + Common.encodeQuotes(group) + '" />' +
'<span class="name">' + nick.htmlEnc() + '</span>' + '<span class="name">' + nick.htmlEnc() + '</span>' +
'<span class="xid">' + xid.htmlEnc() + '</span>' + '<span class="xid">' + xid.htmlEnc() + '</span>' +
'<span class="action ' + action + ' talk-images"></span>' + '<span class="action ' + action + ' talk-images"></span>' +
'</div>' '</div>'
); );
@ -178,31 +191,33 @@ 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());
}); });
} }
// Process the asked action // Process the asked action
var roster_item = $('#roster .' + hex_md5(xid)); var roster_item = $('#roster .' + hex_md5(xid));
switch(action) { switch(action) {
// Buddy add // Buddy add
case 'add': case 'add':
@ -210,29 +225,31 @@ var RosterX = (function () {
Presence.sendSubscribe(xid, 'subscribe'); Presence.sendSubscribe(xid, 'subscribe');
Roster.send(xid, '', nick, group_arr); Roster.send(xid, '', nick, group_arr);
} }
break; break;
// Buddy edit // Buddy edit
case 'modify': case 'modify':
if(Common.exists(roster_item)) if(Common.exists(roster_item))
Roster.send(xid, '', nick, group_arr); Roster.send(xid, '', nick, group_arr);
break; break;
// Buddy delete // Buddy delete
case 'delete': case 'delete':
if(Common.exists(roster_item)) if(Common.exists(roster_item))
Roster.send(xid, 'remove'); Roster.send(xid, 'remove');
break; break;
} }
}); });
// Close the popup // Close the popup
self.close(); self.close();
} catch(e) { } catch(e) {
Console.error('RosterX.save', e); Console.error('RosterX.save', e);
} finally {
return false;
} }
}; };
@ -248,18 +265,26 @@ 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;
}); });
} catch(e) { } catch(e) {

View file

@ -37,34 +37,34 @@ var Search = (function () {
if(!query) { if(!query) {
return; return;
} }
// Wildcard (*) submitted // Wildcard (*) submitted
if(query == '*') { if(query == '*') {
query = ''; query = '';
} }
// Replace forbidden characters in regex // Replace forbidden characters in regex
query = Common.escapeRegex(query); query = Common.escapeRegex(query);
// Create an empty array // Create an empty array
var results = []; var results = [];
// Search regex // Search regex
var regex = new RegExp('((^)|( ))' + query, 'gi'); var regex = new RegExp('((^)|( ))' + query, 'gi');
// Search in the roster // Search in the roster
var buddies = Roster.getAllBuddies(); var buddies = Roster.getAllBuddies();
for(var i in buddies) { for(var i in buddies) {
var xid = buddies[i]; var xid = buddies[i];
var nick = Name.getBuddy(xid); var nick = Name.getBuddy(xid);
// Buddy match our search, and not yet in the array // Buddy match our search, and not yet in the array
if(nick.match(regex) && !Utils.existArrayValue(results, xid)) { if(nick.match(regex) && !Utils.existArrayValue(results, xid)) {
results.push(xid); results.push(xid);
} }
} }
// Return the results array // Return the results array
return results; return results;
} catch(e) { } catch(e) {
@ -104,17 +104,18 @@ var Search = (function () {
try { try {
// Remove the search tool // Remove the search tool
self.resetBuddy(destination); self.resetBuddy(destination);
// Define a selector // Define a selector
var input = $(destination + ' input'); var input = $(destination + ' input');
var value = input.val(); var value = input.val();
// 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() {
input.val(old + xid).focus(); input.val(old + xid).focus();
@ -139,56 +140,57 @@ var Search = (function () {
try { try {
// Reset the search engine // Reset the search engine
self.resetBuddy(destination); self.resetBuddy(destination);
// Get the entered value // Get the entered value
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);
// Display each result (if any) // Display each result (if any)
if(entered && entered.length) { if(entered && entered.length) {
// Set a special class to the search input // Set a special class to the search input
$(destination + ' input').addClass('suggested'); $(destination + ' input').addClass('suggested');
// Append each found buddy in the container // Append each found buddy in the container
var regex = new RegExp('((^)|( ))' + value, 'gi'); var regex = new RegExp('((^)|( ))' + value, 'gi');
// Initialize the code generation // Initialize the code generation
var code = '<ul>'; var code = '<ul>';
for(var b in entered) { for(var b in entered) {
// Get some values from the XID // Get some values from the XID
var current = Name.getBuddy(entered[b]).htmlEnc(); var current = Name.getBuddy(entered[b]).htmlEnc();
current = current.replace(regex, '<b>$&</b>'); current = current.replace(regex, '<b>$&</b>');
// Add the current element to the global code // Add the current element to the global code
code += '<li onclick="return Search.addBuddy(\'' + Utils.encodeOnclick(destination) + '\', \'' + Utils.encodeOnclick(entered[b]) + '\');" data-xid="' + Common.encodeQuotes(entered[b]) + '">' + current + '</li>'; code += '<li onclick="return Search.addBuddy(\'' + Utils.encodeOnclick(destination) + '\', \'' + Utils.encodeOnclick(entered[b]) + '\');" data-xid="' + Common.encodeQuotes(entered[b]) + '">' + current + '</li>';
} }
// Finish the code generation // Finish the code generation
code += '</ul>'; code += '</ul>';
// Creates the code in the DOM // Creates the code in the DOM
$(destination).append(code); $(destination).append(code);
// Put the hover on the first element // Put the hover on the first element
$(destination + ' ul li:first').addClass('hovered'); $(destination + ' ul li:first').addClass('hovered');
// Hover event, to not to remove this onblur and loose the click event // Hover event, to not to remove this onblur and loose the click event
$(destination + ' ul li').hover(function() { $(destination + ' ul li').hover(function() {
$(destination + ' ul li').removeClass('hovered'); $(destination + ' ul li').removeClass('hovered');
$(this).addClass('hovered'); $(this).addClass('hovered');
// Add a marker for the blur event // Add a marker for the blur event
$(destination + ' ul').attr('mouse-hover', 'true'); $(destination + ' ul').attr('mouse-hover', 'true');
}, function() { }, function() {
$(this).removeClass('hovered'); $(this).removeClass('hovered');
// Remove the mouse over marker // Remove the mouse over marker
$(destination + ' ul').removeAttr('mouse-hover'); $(destination + ' ul').removeAttr('mouse-hover');
}); });
@ -212,52 +214,53 @@ var Search = (function () {
try { try {
// Down arrow: 40 // Down arrow: 40
// Up arrown: 38 // Up arrown: 38
// Initialize // Initialize
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');
// Create the path & get its size // Create the path & get its size
var path = destination + ' ul li'; var path = destination + ' ul li';
var pSize = $(path).size(); var pSize = $(path).size();
// Define the i value // Define the i value
var i = 0; var i = 0;
// Switching yet launched // Switching yet launched
if(Common.exists(path + '.hovered')) { if(Common.exists(path + '.hovered')) {
var index = $(path).attr('data-hovered'); var index = $(path).attr('data-hovered');
if(index) if(index) {
i = parseInt(index); i = parseInt(index);
}
if(code == 40)
if(code == 40) {
i++; i++;
else } else {
i--; i--;
}
} else if(code == 38) {
i = pSize - 1;
} }
else if(code == 38)
i = pSize - 1;
// We must not override the maximum i limit // We must not override the maximum i limit
if(i >= pSize) if(i >= pSize) {
i = 0; i = 0;
} else if(i < 0) {
// We must not have negative i
else if(i < 0)
i = pSize - 1; i = pSize - 1;
}
// Modify the list // Modify the list
$(path + '.hovered').removeClass('hovered'); $(path + '.hovered').removeClass('hovered');
$(path).eq(i).addClass('hovered'); $(path).eq(i).addClass('hovered');
// Store the i index // Store the i index
$(path).attr('data-hovered', i); $(path).attr('data-hovered', i);
} catch(e) { } catch(e) {
@ -280,20 +283,22 @@ var Search = (function () {
try { try {
// Put a marker // Put a marker
self.search_filtered = true; self.search_filtered = true;
// Show the buddies that match the search string // Show the buddies that match the search string
var rFilter = self.processBuddy(vFilter); var rFilter = self.processBuddy(vFilter);
// Hide all the buddies // Hide all the buddies
$('#roster .buddy').hide(); $('#roster .buddy').hide();
// 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);
@ -312,14 +317,15 @@ var Search = (function () {
try { try {
// Remove the marker // Remove the marker
self.search_filtered = false; self.search_filtered = false;
// Show all the buddies // Show all the buddies
$('#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();
} catch(e) { } catch(e) {
@ -342,26 +348,24 @@ var Search = (function () {
var input = $('#roster .filter input'); var input = $('#roster .filter input');
var cancel = $('#roster .filter a'); var cancel = $('#roster .filter a');
var value = input.val(); var value = input.val();
// Security: reset all the groups, empty or not, deployed or not // Security: reset all the groups, empty or not, deployed or not
$('#roster .one-group, #roster .group-buddies').show(); $('#roster .one-group, #roster .group-buddies').show();
$('#roster .group span').text('-'); $('#roster .group span').text('-');
// 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);
} }
// Update the groups // Update the groups
Roster.updateGroups(); Roster.updateGroups();
} catch(e) { } catch(e) {
@ -384,25 +388,25 @@ var Search = (function () {
var array = []; var array = [];
var i = 0; var i = 0;
var nearest = 0; var nearest = 0;
// Add the stamp values to the array // Add the stamp values to the array
$(element).each(function() { $(element).each(function() {
var current_stamp = parseInt($(this).attr('data-stamp')); var current_stamp = parseInt($(this).attr('data-stamp'));
// Push it! // Push it!
array.push(current_stamp); array.push(current_stamp);
}); });
// Sort the array // Sort the array
array.sort(); array.sort();
// Get the nearest stamp value // Get the nearest stamp value
while(stamp > array[i]) { while(stamp > array[i]) {
nearest = array[i]; nearest = array[i];
i++; i++;
} }
return nearest; return nearest;
} catch(e) { } catch(e) {
Console.error('Search.sortElementByStamp', e); Console.error('Search.sortElementByStamp', e);

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,103 +88,21 @@ 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;
} catch(e) { } catch(e) {
Console.error('Smileys.links', e); Console.error('Smileys.links', e);

View file

@ -33,10 +33,10 @@ var Storage = (function () {
try { try {
var iq = new JSJaCIQ(); var iq = new JSJaCIQ();
iq.setType('get'); iq.setType('get');
var iqQuery = iq.setQuery(NS_PRIVATE); var iqQuery = iq.setQuery(NS_PRIVATE);
iqQuery.appendChild(iq.buildNode('storage', {'xmlns': type})); iqQuery.appendChild(iq.buildNode('storage', {'xmlns': type}));
con.send(iq, self.handle); con.send(iq, self.handle);
} catch(e) { } catch(e) {
Console.error('Storage.get', e); Console.error('Storage.get', e);
@ -56,111 +56,126 @@ var Storage = (function () {
try { try {
var handleXML = iq.getQuery(); var handleXML = iq.getQuery();
var handleFrom = Common.fullXID(Common.getStanzaFrom(iq)); var handleFrom = Common.fullXID(Common.getStanzaFrom(iq));
// Define some vars // Define some vars
var options = $(handleXML).find('storage[xmlns="' + NS_OPTIONS + '"]'); var options = $(handleXML).find('storage[xmlns="' + NS_OPTIONS + '"]');
var inbox = $(handleXML).find('storage[xmlns="' + NS_INBOX + '"]'); var inbox = $(handleXML).find('storage[xmlns="' + NS_INBOX + '"]');
var bookmarks = $(handleXML).find('storage[xmlns="' + NS_BOOKMARKS + '"]'); var bookmarks = $(handleXML).find('storage[xmlns="' + NS_BOOKMARKS + '"]');
var rosternotes = $(handleXML).find('storage[xmlns="' + NS_ROSTERNOTES + '"]'); var rosternotes = $(handleXML).find('storage[xmlns="' + NS_ROSTERNOTES + '"]');
// No options and node not yet configured // No options and node not yet configured
if(options.size() && !options.find('option').size() && (iq.getType() != 'error')) { if(options.size() && !options.find('option').size() && (iq.getType() != 'error')) {
Welcome.open(); Welcome.open();
} }
// 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';
// We display the storage // We display the storage
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
if(options.size()) { if(options.size()) {
Console.log('Options received.'); Console.log('Options received.');
// Now, get the inbox // Now, get the inbox
self.get(NS_INBOX); self.get(NS_INBOX);
// Geolocate the user // Geolocate the user
PEP.geolocate(); PEP.geolocate();
$('.options-hidable').show(); $('.options-hidable').show();
} }
// Inbox received // Inbox received
else if(inbox.size()) { else if(inbox.size()) {
Console.log('Inbox received.'); Console.log('Inbox received.');
// Send the first presence! // Send the first presence!
Presence.sendFirst(DataStore.getDB(Connection.desktop_hash, 'checksum', 1)); Presence.sendFirst(DataStore.getDB(Connection.desktop_hash, 'checksum', 1));
// Check we have new messages (play a sound if any unread messages) // Check we have new messages (play a sound if any unread messages)
if(Inbox.checkMessages()) { if(Inbox.checkMessages()) {
Audio.play('notification'); Audio.play('notification');
} }
$('.inbox-hidable').show(); $('.inbox-hidable').show();
} }
// Bookmarks received // Bookmarks received
else if(bookmarks.size()) { else if(bookmarks.size()) {
// Join the groupchats the admin defined (if any) // Join the groupchats the admin defined (if any)
Groupchat.joinConf(); Groupchat.joinConf();
Console.log('Bookmarks received.'); Console.log('Bookmarks received.');
} }
// Roster notes received (for logger) // Roster notes received (for logger)
else if(rosternotes.size()) { else if(rosternotes.size()) {
Console.log('Roster notes received.'); Console.log('Roster notes received.');

View file

@ -29,17 +29,21 @@ var System = (function () {
try { try {
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) {
Console.error('System.location', e); Console.error('System.location', e);

View file

@ -51,236 +51,241 @@ 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();
// Generate the HTML code // Generate the HTML code
var html = var html =
'<div id="talk" class="removable">' + '<div id="talk" class="removable">' +
'<div id="top-content">' + '<div id="top-content">' +
'<div class="tools tools-logo talk-images"></div>' + '<div class="tools tools-logo talk-images"></div>' +
'<div class="tools tools-all">'; '<div class="tools tools-all">';
if(!anonymous) html += if(!anonymous) html +=
'<a href="#" onclick="return Inbox.open();" class="inbox-hidable">' + Common._e("Messages") + '</a>' + '<a href="#" onclick="return Inbox.open();" class="inbox-hidable">' + Common._e("Messages") + '</a>' +
'<a href="#" onclick="return vCard.open();" class="vcard">' + Common._e("Profile") + '</a>' + '<a href="#" onclick="return vCard.open();" class="vcard">' + Common._e("Profile") + '</a>' +
'<a href="#" onclick="return Options.open();" class="options-hidable">' + Common._e("Options") + '</a>' + '<a href="#" onclick="return Options.open();" class="options-hidable">' + Common._e("Options") + '</a>' +
'<a href="#" onclick="return Connection.normalQuit();" class="quit">' + Common._e("Disconnect") + '</a>'; '<a href="#" onclick="return Connection.normalQuit();" class="quit">' + Common._e("Disconnect") + '</a>';
else html += else html +=
'<a href="./">' + Common._e("Disconnect") + '</a>'; '<a href="./">' + Common._e("Disconnect") + '</a>';
html += html +=
'</div>'; '</div>';
if(!anonymous && document.createElement('audio').canPlayType) html += if(!anonymous && document.createElement('audio').canPlayType) html +=
'<div class="tools-all ibubble">' + '<div class="tools-all ibubble">' +
'<div class="tools music talk-images" onclick="return Music.open();"></div>' + '<div class="tools music talk-images" onclick="return Music.open();"></div>' +
'<div class="music-content tools-content bubble hidable">' + '<div class="music-content tools-content bubble hidable">' +
'<div class="tools-content-subarrow talk-images"></div>' + '<div class="tools-content-subarrow talk-images"></div>' +
'<div class="tools-content-subitem">' + '<div class="tools-content-subitem">' +
'<div class="player">' + '<div class="player">' +
'<a href="#" class="stop talk-images" onclick="return Music.action(\'stop\');"></a>' + '<a href="#" class="stop talk-images" onclick="return Music.action(\'stop\');"></a>' +
'</div>' + '</div>' +
'<div class="list">' + '<div class="list">' +
'<p class="no-results">' + Common._e("No result!") + '</p>' + '<p class="no-results">' + Common._e("No result!") + '</p>' +
'</div>' + '</div>' +
'<div class="search">' + '<div class="search">' +
'<input type="text" />' + '<input type="text" />' +
'</div>' + '</div>' +
'</div>' + '</div>' +
'</div>' + '</div>' +
'</div>';
if(!anonymous) html +=
'<div class="tools-all ibubble">' +
'<div class="tools notifications talk-images" onclick="return Bubble.show(\'.notifications-content\');"></div>' +
'<div class="notifications-content tools-content bubble hidable">' +
'<div class="tools-content-subarrow talk-images"></div>' +
'<div class="tools-content-subitem">' +
'<a class="empty" href="#" onclick="return Notification.clear();">' + Common._e("Empty") + '</a>' +
'<p class="nothing">' + Common._e("No notifications.") + '</p>' +
'</div>' +
'</div>' +
'</div>'; '</div>';
if(!anonymous) html += if(!anonymous) html +=
'<div class="tools-all">' + '<div class="tools-all ibubble">' +
'<div class="tools jingle talk-images" onclick="return Jingle.open();">' + '<div class="tools notifications talk-images" onclick="return Bubble.show(\'.notifications-content\');"></div>' +
'<span class="streaming-items">' +
'<span class="counter" data-default="00:00:00">00:00:00</span>' +
'<a class="stop" href="#" onclick="return Jingle.stop();">' + Common._e("Stop") + '</a>' +
'</span>' +
'</div>' +
'<div class="jingle-content tools-content">' + '<div class="notifications-content tools-content bubble hidable">' +
'<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>' + '<a class="empty" href="#" onclick="return Notification.clear();">' + Common._e("Empty") + '</a>' +
'<p class="nothing">' + Common._e("No notifications.") + '</p>' +
'</div>' +
'</div>' +
'</div>'; '</div>';
if(!anonymous) html +=
'<div class="tools-all">' +
'<div class="tools call talk-images" onclick="return Call.open();">' +
'<span class="streaming-items">' +
'<span class="counter" data-default="00:00:00">00:00:00</span>' +
'<a class="stop" href="#" onclick="return Call.stop();">' + Common._e("Stop") + '</a>' +
'</span>' +
'</div>' +
'<div class="call-content tools-content">' +
'<div class="tools-content-subarrow talk-images"></div>' +
'<div class="tools-content-subitem"></div>' +
'</div>' +
'</div>';
html += html +=
'</div>' + '</div>' +
'<div id="main-content">' + '<div id="main-content">' +
'<div id="left-content">'; '<div id="left-content">';
if(!anonymous) html += if(!anonymous) html +=
'<div id="roster">' + '<div id="roster">' +
'<div class="content"></div>' + '<div class="content"></div>' +
'<div class="filter">' + '<div class="filter">' +
'<input type="text" placeholder="' + Common._e("Filter") + '" />' + '<input type="text" placeholder="' + Common._e("Filter") + '" />' +
'<a href="#">x</a>' + '<a href="#">x</a>' +
'</div>' + '</div>' +
'<div class="foot ibubble">' + '<div class="foot ibubble">' +
'<div class="roster-add roster-icon">' + '<div class="roster-add roster-icon">' +
'<a href="#" class="add talk-images" title="' + Common._e("Add a friend") + '"></a>' + '<a href="#" class="add talk-images" title="' + Common._e("Add a friend") + '"></a>' +
'</div>' + '</div>' +
'<div class="roster-join roster-icon">' + '<div class="roster-join roster-icon">' +
'<a href="#" class="join talk-images" title="' + Common._e("Join a chat") + '"></a>' + '<a href="#" class="join talk-images" title="' + Common._e("Join a chat") + '"></a>' +
'</div>' + '</div>' +
'<div class="roster-groupchat roster-icon">' + '<div class="roster-groupchat roster-icon">' +
'<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-more roster-icon">' + '<div class="roster-muji roster-icon muji-hidable">' +
'<a href="#" class="more talk-images" title="' + Common._e("More stuff") + '"></a>' + '<a href="#" class="muji talk-images" title="' + Common._e("Audio/video conference") + '"></a>' +
'</div>' + '</div>' +
'<div style="clear: both;"></div>' + '<div class="roster-more roster-icon">' +
'</div>' + '<a href="#" class="more talk-images" title="' + Common._e("More stuff") + '"></a>' +
'</div>' +
'<div style="clear: both;"></div>' +
'</div>' +
'</div>'; '</div>';
html += html +=
'<div id="my-infos">' + '<div id="my-infos">' +
'<div class="content">' + '<div class="content">' +
'<div class="element f-presence ibubble">' + '<div class="element f-presence ibubble">' +
'<a href="#" class="icon picker disabled" data-value="available">' + '<a href="#" class="icon picker disabled" data-value="available">' +
'<span class="talk-images"></span>' + '<span class="talk-images"></span>' +
'</a>' + '</a>' +
'<input id="presence-status" type="text" placeholder="' + Common._e("Status") + '" disabled="" />' + '<input id="presence-status" type="text" placeholder="' + Common._e("Status") + '" disabled="" />' +
'</div>'; '</div>';
if(!anonymous) html += if(!anonymous) html +=
'<div class="element f-mood pep-hidable ibubble">' + '<div class="element f-mood pep-hidable ibubble">' +
'<a href="#" class="icon picker" data-value="happy">' + '<a href="#" class="icon picker" data-value="happy">' +
'<span class="talk-images"></span>' + '<span class="talk-images"></span>' +
'</a>' + '</a>' +
'<input id="mood-text" type="text" placeholder="' + Common._e("Mood") + '" />' + '<input id="mood-text" type="text" placeholder="' + Common._e("Mood") + '" />' +
'</div>' + '</div>' +
'<div class="element f-activity pep-hidable ibubble">' + '<div class="element f-activity pep-hidable ibubble">' +
'<a href="#" class="icon picker" data-value="exercising">' + '<a href="#" class="icon picker" data-value="exercising">' +
'<span class="talk-images activity-exercising"></span>' + '<span class="talk-images activity-exercising"></span>' +
'</a>' + '</a>' +
'<input id="activity-text" type="text" placeholder="' + Common._e("Activity") + '" />' + '<input id="activity-text" type="text" placeholder="' + Common._e("Activity") + '" />' +
'</div>'; '</div>';
html += html +=
'</div>' + '</div>' +
'</div>' + '</div>' +
'</div>' + '</div>' +
'<div id="right-content">' + '<div id="right-content">' +
'<div id="page-switch">' + '<div id="page-switch">' +
'<div class="chans">'; '<div class="chans">';
if(!anonymous) html += if(!anonymous) html +=
'<div class="channel switcher activechan" onclick="return Interface.switchChan(\'channel\');">' + '<div class="channel switcher activechan" onclick="return Interface.switchChan(\'channel\');">' +
'<div class="icon talk-images"></div>' + '<div class="icon talk-images"></div>' +
'<div class="name">' + Common._e("Channel") + '</div>' + '<div class="name">' + Common._e("Channel") + '</div>' +
'</div>'; '</div>';
html += html +=
'</div>'; '</div>';
if(anonymous) html += if(anonymous) html +=
'<div class="join ibubble">' + '<div class="join ibubble">' +
'<div class="join-button talk-images" onclick="return Interface.loadJoinGroupchat();" title="' + Common._e("Join groupchat") + '"></div>' + '<div class="join-button talk-images" onclick="return Interface.loadJoinGroupchat();" title="' + Common._e("Join groupchat") + '"></div>' +
'</div>'; '</div>';
html += html +=
'<div class="more ibubble">' + '<div class="more ibubble">' +
'<div class="more-button talk-images" onclick="return Interface.loadChatSwitch();" title="' + Common._e("All tabs") + '"></div>' + '<div class="more-button talk-images" onclick="return Interface.loadChatSwitch();" title="' + Common._e("All tabs") + '"></div>' +
'</div>' + '</div>' +
'</div>' + '</div>' +
'<div id="page-engine">'; '<div id="page-engine">';
if(!anonymous) html += if(!anonymous) html +=
'<div id="channel" class="page-engine-chan" style="display: block;">' + '<div id="channel" class="page-engine-chan" style="display: block;">' +
'<div class="top mixed ' + hex_md5(Common.getXID()) + '">' + '<div class="top mixed ' + hex_md5(Common.getXID()) + '">' +
'<div class="avatar-container">' + '<div class="avatar-container">' +
'<img class="avatar" src="' + './images/others/default-avatar.png' + '" alt="" />' + '<img class="avatar" src="' + './images/others/default-avatar.png' + '" alt="" />' +
'</div>' + '</div>' +
'<div class="update">' + '<div class="update">' +
'<p>' + Common._e("What\'s up with you?") + '</p>' + '<p>' + Common._e("What\'s up with you?") + '</p>' +
'<div class="microblog-body">' + '<div class="microblog-body">' +
'<input class="focusable" type="text" name="microblog_body" placeholder="' + Common._e("Type something you want to share with your friends...") + '" disabled="" />' + '<input class="focusable" type="text" name="microblog_body" placeholder="' + Common._e("Type something you want to share with your friends...") + '" disabled="" />' +
'</div>' + '</div>' +
'<div class="one-microblog-icon ibubble">' + '<div class="one-microblog-icon ibubble">' +
'<a href="#" onclick="return Bubble.show(\'#attach\');" title="' + Common._e("Attach a file") + '" class="postit attach talk-images"></a>' + '<a href="#" onclick="return Bubble.show(\'#attach\');" title="' + Common._e("Attach a file") + '" class="postit attach talk-images"></a>' +
'<form id="attach" class="bubble hidable" action="./server/file-share.php" method="post" enctype="multipart/form-data">' + '<form id="attach" class="bubble hidable" action="./server/file-share.php" method="post" enctype="multipart/form-data">' +
'<div class="attach-subarrow talk-images"></div>' + '<div class="attach-subarrow talk-images"></div>' +
'<div class="attach-subitem">' + '<div class="attach-subitem">' +
'<p class="attach-p">' + Common._e("Attach a file") + '</p>' + '<p class="attach-p">' + Common._e("Attach a file") + '</p>' +
Interface.generateFileShare() + Interface.generateFileShare() +
'</div>' + '</div>' +
'</form>' + '</form>' +
'</div>' + '</div>' +
'</div>' + '</div>' +
'</div>' + '</div>' +
'<div class="content mixed"></div>' + '<div class="content mixed"></div>' +
'<div class="footer">' + '<div class="footer">' +
'<div class="sync talk-images">' + Common._e("You are synchronized with your network.") + '</div>' + '<div class="sync talk-images">' + Common._e("You are synchronized with your network.") + '</div>' +
'<div class="unsync talk-images">' + Common._e("Cannot send anything: you can only receive notices!") + '</div>' + '<div class="unsync talk-images">' + Common._e("Cannot send anything: you can only receive notices!") + '</div>' +
'<div class="fetch wait-small">' + Common._e("Fetching the social channel...") + '</div>' + '<div class="fetch wait-small">' + Common._e("Fetching the social channel...") + '</div>' +
'</div>' + '</div>' +
'</div>'; '</div>';
html += html +=
'</div>' + '</div>' +
'</div>' + '</div>' +
'</div>' + '</div>' +
'</div>'; '</div>';
// Create the HTML code // Create the HTML code
$('body').prepend(html); $('body').prepend(html);
// Adapt the roster size // Adapt the roster size
Roster.adapt(); Roster.adapt();
// Create JS events // Create JS events
self.events(); self.events();
// Start the auto idle functions // Start the auto idle functions
Presence.liveIdle(); Presence.liveIdle();
return true; return true;
} catch(e) { } catch(e) {
Console.error('Talk.create', e); Console.error('Talk.create', e);
@ -299,25 +304,25 @@ var Talk = (function () {
try { try {
// Reset our database // Reset our database
DataStore.resetDB(); DataStore.resetDB();
// Reset some vars // Reset some vars
STANZA_ID = 1; STANZA_ID = 1;
Roster.blist_all = false; Roster.blist_all = false;
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();
// Kill the auto idle functions // Kill the auto idle functions
Presence.dieIdle(); Presence.dieIdle();
// We renitalise the html markup as its initiale look // We renitalise the html markup as its initiale look
$('.removable').remove(); $('.removable').remove();
Interface.title('home'); Interface.title('home');
// Finally we show the homepage // Finally we show the homepage
$('#home').show(); $('#home').show();
} catch(e) { } catch(e) {

View file

@ -35,27 +35,28 @@ var Tooltip = (function () {
var path = '#' + hash; var path = '#' + hash;
var path_tooltip = path + ' .chat-tools-' + type; var path_tooltip = path + ' .chat-tools-' + type;
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 = '';
var content = ''; var content = '';
switch(type) { switch(type) {
// Smileys // Smileys
case 'smileys': case 'smileys':
title = Common._e("Smiley insertion"); title = Common._e("Smiley insertion");
content = Smileys.links(hash); content = Smileys.links(hash);
break; break;
// Style // Style
case 'style': case 'style':
title = Common._e("Change style"); title = Common._e("Change style");
// Generate fonts list // Generate fonts list
var fonts = { var fonts = {
'arial': 'Arial, Helvetica, sans-serif', 'arial': 'Arial, Helvetica, sans-serif',
@ -80,106 +81,106 @@ var Tooltip = (function () {
'webdings': 'Webdings, sans-serif', 'webdings': 'Webdings, sans-serif',
'wingdings': 'Wingdings, \'Zapf Dingbats\', sans-serif' 'wingdings': 'Wingdings, \'Zapf Dingbats\', sans-serif'
}; };
var fonts_html = '<div class="font-list">'; var fonts_html = '<div class="font-list">';
// No fonts // No fonts
fonts_html += '<a href="#">' + Common._e("None") + '</a>'; fonts_html += '<a href="#">' + Common._e("None") + '</a>';
// Available fonts // Available fonts
$.each(fonts, function(id_name, full_name) { $.each(fonts, function(id_name, full_name) {
// Generate short name // Generate short name
var short_name = full_name; var short_name = full_name;
if(short_name.match(/,/)) { if(short_name.match(/,/)) {
var name_split = short_name.split(','); var name_split = short_name.split(',');
short_name = $.trim(name_split[0]); short_name = $.trim(name_split[0]);
} }
short_name = short_name.replace(/([^a-z0-9\s]+)/gi, ''); short_name = short_name.replace(/([^a-z0-9\s]+)/gi, '');
// Add this to the HTML // Add this to the HTML
fonts_html += '<a href="#" data-value="' + Common.encodeQuotes(id_name) + '" data-font="' + Common.encodeQuotes(full_name) + '" style="font-family: ' + Common.encodeQuotes(full_name) + ';">' + short_name.htmlEnc() + '</a>'; fonts_html += '<a href="#" data-value="' + Common.encodeQuotes(id_name) + '" data-font="' + Common.encodeQuotes(full_name) + '" style="font-family: ' + Common.encodeQuotes(full_name) + ';">' + short_name.htmlEnc() + '</a>';
}); });
fonts_html += '</div>'; fonts_html += '</div>';
content = content =
'<label class="font">' + '<label class="font">' +
'<div class="font-icon talk-images"></div>' + '<div class="font-icon talk-images"></div>' +
'<div class="fontsize-change">' + '<div class="fontsize-change">' +
'<a class="fontsize-current" href="#">12</a>' + '<a class="fontsize-current" href="#">12</a>' +
'<div class="fontsize-list">' + '<div class="fontsize-list">' +
'<a href="#" class="reset talk-images"></a>' + '<a href="#" class="reset talk-images"></a>' +
'<a href="#" data-value="10" style="font-size: 10px;">10</a>' + '<a href="#" data-value="10" style="font-size: 10px;">10</a>' +
'<a href="#" data-value="12" style="font-size: 12px;">12</a>' + '<a href="#" data-value="12" style="font-size: 12px;">12</a>' +
'<a href="#" data-value="14" style="font-size: 14px;">14</a>' + '<a href="#" data-value="14" style="font-size: 14px;">14</a>' +
'<a href="#" data-value="16" style="font-size: 16px;">16</a>' + '<a href="#" data-value="16" style="font-size: 16px;">16</a>' +
'<a href="#" data-value="18" style="font-size: 18px;">18</a>' + '<a href="#" data-value="18" style="font-size: 18px;">18</a>' +
'</div>' + '</div>' +
'</div>' + '</div>' +
'<div class="font-change">' + '<div class="font-change">' +
'<a class="font-current" href="#">' + Common._e("None") + '</a>' + '<a class="font-current" href="#">' + Common._e("None") + '</a>' +
fonts_html + fonts_html +
'</div>' + '</div>' +
'</label>' + '</label>' +
'<label class="bold"><input type="checkbox" class="bold" />' + Common._e("Text in bold") + '</label>' + '<label class="bold"><input type="checkbox" class="bold" />' + Common._e("Text in bold") + '</label>' +
'<label class="italic"><input type="checkbox" class="italic" />' + Common._e("Text in italic") + '</label>' + '<label class="italic"><input type="checkbox" class="italic" />' + Common._e("Text in italic") + '</label>' +
'<label class="underline"><input type="checkbox" class="underline" />' + Common._e("Underlined text") + '</label>' + '<label class="underline"><input type="checkbox" class="underline" />' + Common._e("Underlined text") + '</label>' +
'<a href="#" class="color" style="background-color: #b10808; clear: both;" data-color="b10808"></a>' + '<a href="#" class="color" style="background-color: #b10808; clear: both;" data-color="b10808"></a>' +
'<a href="#" class="color" style="background-color: #e5860c;" data-color="e5860c"></a>' + '<a href="#" class="color" style="background-color: #e5860c;" data-color="e5860c"></a>' +
'<a href="#" class="color" style="background-color: #f0f30e;" data-color="f0f30e"></a>' + '<a href="#" class="color" style="background-color: #f0f30e;" data-color="f0f30e"></a>' +
'<a href="#" class="color" style="background-color: #009a04;" data-color="009a04"></a>' + '<a href="#" class="color" style="background-color: #009a04;" data-color="009a04"></a>' +
'<a href="#" class="color" style="background-color: #0ba9a0;" data-color="0ba9a0"></a>' + '<a href="#" class="color" style="background-color: #0ba9a0;" data-color="0ba9a0"></a>' +
'<a href="#" class="color" style="background-color: #04228f;" data-color="04228f"></a>' + '<a href="#" class="color" style="background-color: #04228f;" data-color="04228f"></a>' +
'<a href="#" class="color" style="background-color: #9d0ab7;" data-color="9d0ab7"></a>' + '<a href="#" class="color" style="background-color: #9d0ab7;" data-color="9d0ab7"></a>' +
'<div class="color-picker">' + '<div class="color-picker">' +
'<a href="#" class="color-more talk-images"></a>' + '<a href="#" class="color-more talk-images"></a>' +
'<div class="color-hex">' + '<div class="color-hex">' +
'<span class="hex-begin">#</span>' + '<span class="hex-begin">#</span>' +
'<input class="hex-value" type="text" maxlength="6" placeholder="e1e1e1" />' + '<input class="hex-value" type="text" maxlength="6" placeholder="e1e1e1" />' +
'</div>' + '</div>' +
'</div>'; '</div>';
break; break;
// File send // File send
case 'file': case 'file':
title = Common._e("Send a file"); title = Common._e("Send a file");
content = '<p style="margin-bottom: 8px;">' + Common._e("Once uploaded, your friend will be prompted to download the file you sent.") + '</p>'; content = '<p style="margin-bottom: 8px;">' + Common._e("Once uploaded, your friend will be prompted to download the file you sent.") + '</p>';
content += '<form id="oob-upload" action="./server/send.php" method="post" enctype="multipart/form-data">' + Interface.generateFileShare() + '</form>'; content += '<form id="oob-upload" action="./server/send.php" method="post" enctype="multipart/form-data">' + Interface.generateFileShare() + '</form>';
break; break;
// Chat log // Chat log
case 'save': case 'save':
title = Common._e("Save chat"); title = Common._e("Save chat");
content = '<p style="margin-bottom: 8px;">' + Common._e("Click on the following link to get the chat log, and wait. Then click again to get the file.") + '</p>'; content = '<p style="margin-bottom: 8px;">' + Common._e("Click on the following link to get the chat log, and wait. Then click again to get the file.") + '</p>';
// Possible to generate any log? // Possible to generate any log?
if($(path + ' .one-line').size()) if($(path + ' .one-line').size())
content += '<a href="#" class="tooltip-actionlog">' + Common._e("Generate file!") + '</a>'; content += '<a href="#" class="tooltip-actionlog">' + Common._e("Generate file!") + '</a>';
else else
content += '<span class="tooltip-nolog">' + Common._e("This chat is empty!") + '</span>'; content += '<span class="tooltip-nolog">' + Common._e("This chat is empty!") + '</span>';
break; break;
} }
// Generates general tooltip HTML code // Generates general tooltip HTML code
var html = var html =
'<div class="tooltip bubble-' + type + '">' + '<div class="tooltip bubble-' + type + '">' +
'<div class="tooltip-subitem">' + '<div class="tooltip-subitem">' +
'<p class="tooltip-top">' + title + '</p>' + '<p class="tooltip-top">' + title + '</p>' +
content + content +
'</div>' + '</div>' +
'<div class="tooltip-subarrow talk-images"></div>' + '<div class="tooltip-subarrow talk-images"></div>' +
'</div>'; '</div>';
// Append the HTML code // Append the HTML code
$(path_tooltip).append(html); $(path_tooltip).append(html);
// Special events // Special events
switch(type) { switch(type) {
// Smileys // Smileys
@ -188,9 +189,9 @@ var Tooltip = (function () {
$(path_tooltip + ' a.emoticon').click(function() { $(path_tooltip + ' a.emoticon').click(function() {
return Interface.insertSmiley($(this).attr('data-smiley'), hash); return Interface.insertSmiley($(this).attr('data-smiley'), hash);
}); });
break; break;
// Style // Style
case 'style': case 'style':
// Paths to items // Paths to items
@ -207,198 +208,219 @@ var Tooltip = (function () {
var color = bubble_style + ' div.color-picker'; var color = bubble_style + ' div.color-picker';
var color_more = color + ' a.color-more'; var color_more = color + ' a.color-more';
var color_hex = color + ' div.color-hex'; var color_hex = color + ' div.color-hex';
// 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());
$(message_area).attr('data-font', this_sel.attr('data-value'));
} }
// A font is defined
else {
$(font_current).attr('data-font', $(this).attr('data-font'))
.attr('data-value', $(this).attr('data-value'))
.text($(font_list).find('a[data-value="' + $(this).attr('data-value') + '"]').text());
$(message_area).attr('data-font', $(this).attr('data-value'));
}
return false; return false;
}); });
// 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;
}); });
// 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;
}); });
// Click event on color picker // Click event on color picker
$(color_more).click(function() { $(color_more).click(function() {
var this_sel = $(this);
// The clicked color is yet selected // The clicked color is yet selected
if($(color_hex).is(':visible')) if($(color_hex).is(':visible')) {
$(this).parent().removeClass('opened'); this_sel.parent().removeClass('opened');
} else {
else { this_sel.parent().addClass('opened');
$(this).parent().addClass('opened');
// Focus // Focus
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
$(color_hex).find('input').focus(); $(color_hex).find('input').focus();
}); });
} }
return false; return false;
}); });
// Click event on color hex // Click event on color hex
$(color_hex).click(function() { $(color_hex).click(function() {
return false; return false;
}); });
// 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')) {
$(color_more).click(); $(color_more).click();
// Focus again on the message textarea // Focus again on the message textarea
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
$(message_area).focus(); $(message_area).focus();
}); });
} }
return false; return false;
} }
// Reset current color // Reset current color
$(message_area).removeAttr('data-color'); $(message_area).removeAttr('data-color');
$(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
$(style + ', ' + colors + ', ' + font_select + ', ' + fontsize_select).click(function() { $(style + ', ' + colors + ', ' + font_select + ', ' + fontsize_select).click(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() {
$(message_area).focus(); $(message_area).focus();
}); });
}); });
// Load current style // Load current style
self.loadStyleSelector(hash); self.loadStyleSelector(hash);
break; break;
// File send // File send
case 'file': case 'file':
// File upload vars // File upload vars
@ -407,34 +429,41 @@ var Tooltip = (function () {
beforeSubmit: OOB.waitUpload, beforeSubmit: OOB.waitUpload,
success: OOB.handleUpload success: OOB.handleUpload
}; };
// 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');
// Add a cancel button // Add a cancel button
$(this).after('<input type="reset" value="' + Common._e("Cancel") + '" />'); $(this).after('<input type="reset" value="' + Common._e("Cancel") + '" />');
// Cancel button click event // Cancel button click event
$(path_tooltip + ' #oob-upload input[type="reset"]').click(function() { $(path_tooltip + ' #oob-upload input[type="reset"]').click(function() {
// Remove the bubble // Remove the bubble
@ -442,24 +471,24 @@ var Tooltip = (function () {
self.destroy(hash, 'file'); self.destroy(hash, 'file');
}); });
}); });
break; break;
// Chat log // Chat log
case 'save': case 'save':
// Chat log generation click event // Chat log generation click event
$(path_tooltip + ' .tooltip-actionlog').click(function() { $(path_tooltip + ' .tooltip-actionlog').click(function() {
// Replace it with a waiting notice // Replace it with a waiting notice
$(this).replaceWith('<span class="tooltip-waitlog">' + Common._e("Please wait...") + '</span>'); $(this).replaceWith('<span class="tooltip-waitlog">' + Common._e("Please wait...") + '</span>');
Interface.generateChatLog(xid, hash); Interface.generateChatLog(xid, hash);
return false; return false;
}); });
break; break;
} }
return true; return true;
} catch(e) { } catch(e) {
Console.error('Tooltip.create', e); Console.error('Tooltip.create', e);
@ -524,7 +553,7 @@ var Tooltip = (function () {
self.hover(xid, hash, 'style'); self.hover(xid, hash, 'style');
self.hover(xid, hash, 'file'); self.hover(xid, hash, 'file');
self.hover(xid, hash, 'save'); self.hover(xid, hash, 'save');
// Click events // Click events
$('#' + hash + ' a.chat-tools-content, #' + hash + ' .chat-tools-content a').click(function() { $('#' + hash + ' a.chat-tools-content, #' + hash + ' .chat-tools-content a').click(function() {
return false; return false;
@ -553,33 +582,37 @@ var Tooltip = (function () {
var font_select = $(bubble_style + ' div.font-list').find('a[data-value="' + font + '"]'); var font_select = $(bubble_style + ' div.font-list').find('a[data-value="' + font + '"]');
var fontsize = message_area.attr('data-fontsize'); var fontsize = message_area.attr('data-fontsize');
var color = message_area.attr('data-color'); var color = message_area.attr('data-color');
// Apply message font // Apply message font
if(font) { if(font) {
$(bubble_style + ' a.font-current').attr('data-value', font) $(bubble_style + ' a.font-current').attr('data-value', font)
.attr('data-font', font_select.attr('data-font')) .attr('data-font', font_select.attr('data-font'))
.text(font_select.text()); .text(font_select.text());
} }
// Apply message font-size // Apply message font-size
if(fontsize) { if(fontsize) {
$(bubble_style + ' a.fontsize-current').attr('data-value', fontsize) $(bubble_style + ' a.fontsize-current').attr('data-value', fontsize)
.text(fontsize); .text(fontsize);
} }
// 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

@ -31,91 +31,91 @@ var UserInfos = (function () {
try { try {
// Can show shortcuts? // Can show shortcuts?
var shortcuts = ''; var shortcuts = '';
if(xid != Common.getXID()) { if(xid != Common.getXID()) {
shortcuts = '<div class="shortcuts">' + shortcuts = '<div class="shortcuts">' +
'<a href="#" class="message talk-images" title="' + Common._e("Send him/her a message") + '" onclick="UserInfos.close(); return Inbox.composeMessage(\'' + Utils.encodeOnclick(xid) + '\');"></a>' + '<a href="#" class="message talk-images" title="' + Common._e("Send him/her a message") + '" onclick="UserInfos.close(); return Inbox.composeMessage(\'' + Utils.encodeOnclick(xid) + '\');"></a>' +
'<a href="#" class="chat talk-images" title="' + Common._e("Start a chat with him/her") + '" onclick="UserInfos.close(); return Chat.checkCreate(\'' + Utils.encodeOnclick(xid) + '\', \'chat\');"></a>' + '<a href="#" class="chat talk-images" title="' + Common._e("Start a chat with him/her") + '" onclick="UserInfos.close(); return Chat.checkCreate(\'' + Utils.encodeOnclick(xid) + '\', \'chat\');"></a>' +
'<a href="#" class="command talk-images" title="' + Common._e("Command") + '" onclick="UserInfos.close(); return AdHoc.retrieve(\'' + Utils.encodeOnclick(xid) + '\');"></a>' + '<a href="#" class="command talk-images" title="' + Common._e("Command") + '" onclick="UserInfos.close(); return AdHoc.retrieve(\'' + Utils.encodeOnclick(xid) + '\');"></a>' +
'</div>'; '</div>';
} }
// Popup HTML content // Popup HTML content
var html = var html =
'<div class="top">' + Common._e("User profile") + '</div>' + '<div class="top">' + Common._e("User profile") + '</div>' +
'<div class="tab">' + '<div class="tab">' +
'<a href="#" class="tab-active" data-key="1">' + Common._e("General") + '</a>' + '<a href="#" class="tab-active" data-key="1">' + Common._e("General") + '</a>' +
'<a href="#" data-key="2">' + Common._e("Advanced") + '</a>' + '<a href="#" data-key="2">' + Common._e("Advanced") + '</a>' +
'<a href="#" data-key="3">' + Common._e("Comments") + '</a>' + '<a href="#" data-key="3">' + Common._e("Comments") + '</a>' +
'</div>' + '</div>' +
'<div class="content">' + '<div class="content">' +
'<div class="lap-active one-lap info1">' + '<div class="lap-active one-lap info1">' +
'<div class="main-infos">' + '<div class="main-infos">' +
'<div class="avatar-container">' + '<div class="avatar-container">' +
'<img class="avatar" src="' + './images/others/default-avatar.png' + '" alt="" />' + '<img class="avatar" src="' + './images/others/default-avatar.png' + '" alt="" />' +
'</div>' + '</div>' +
'<h1 id="BUDDY-FN" class="reset-info">' + Common._e("unknown") + '</h1>' + '<h1 id="BUDDY-FN" class="reset-info">' + Common._e("unknown") + '</h1>' +
'<h2 class="buddy-xid" class="reset-info">' + Common._e("unknown") + '</h2>' + '<h2 class="buddy-xid" class="reset-info">' + Common._e("unknown") + '</h2>' +
'<h3 class="buddy-last" class="reset-info">' + Common._e("unknown") + '</h3>' + '<h3 class="buddy-last" class="reset-info">' + Common._e("unknown") + '</h3>' +
shortcuts + shortcuts +
'</div>' + '</div>' +
'<div class="block-infos">' + '<div class="block-infos">' +
'<div class="one-line"><b class="line-label">' + Common._e("Date of birth") + '</b><span id="BUDDY-BDAY" class="reset-info">' + Common._e("unknown") + '</span></div>' + '<div class="one-line"><b class="line-label">' + Common._e("Date of birth") + '</b><span id="BUDDY-BDAY" class="reset-info">' + Common._e("unknown") + '</span></div>' +
'<div class="one-line"><b class="line-label">' + Common._e("E-mail") + '</b><span id="BUDDY-EMAIL-USERID" class="reset-info">' + Common._e("unknown") + '</span></div>' + '<div class="one-line"><b class="line-label">' + Common._e("E-mail") + '</b><span id="BUDDY-EMAIL-USERID" class="reset-info">' + Common._e("unknown") + '</span></div>' +
'<div class="one-line"><b class="line-label">' + Common._e("Phone") + '</b><span id="BUDDY-TEL-NUMBER" class="reset-info">' + Common._e("unknown") + '</span></div>' + '<div class="one-line"><b class="line-label">' + Common._e("Phone") + '</b><span id="BUDDY-TEL-NUMBER" class="reset-info">' + Common._e("unknown") + '</span></div>' +
'<div class="one-line"><b class="line-label">' + Common._e("Website") + '</b><span id="BUDDY-URL" class="reset-info">' + Common._e("unknown") + '</span></div>' + '<div class="one-line"><b class="line-label">' + Common._e("Website") + '</b><span id="BUDDY-URL" class="reset-info">' + Common._e("unknown") + '</span></div>' +
'</div>' + '</div>' +
'<div class="block-infos">' + '<div class="block-infos">' +
'<div class="one-line"><b class="line-label">' + Common._e("Client") + '</b><span id="BUDDY-CLIENT" class="reset-info">' + Common._e("unknown") + '</span></div>' + '<div class="one-line"><b class="line-label">' + Common._e("Client") + '</b><span id="BUDDY-CLIENT" class="reset-info">' + Common._e("unknown") + '</span></div>' +
'<div class="one-line"><b class="line-label">' + Common._e("System") + '</b><span id="BUDDY-SYSTEM" class="reset-info">' + Common._e("unknown") + '</span></div>' + '<div class="one-line"><b class="line-label">' + Common._e("System") + '</b><span id="BUDDY-SYSTEM" class="reset-info">' + Common._e("unknown") + '</span></div>' +
'<div class="one-line"><b class="line-label">' + Common._e("Local time") + '</b><span id="BUDDY-TIME" class="reset-info">' + Common._e("unknown") + '</span></div>' + '<div class="one-line"><b class="line-label">' + Common._e("Local time") + '</b><span id="BUDDY-TIME" class="reset-info">' + Common._e("unknown") + '</span></div>' +
'</div>' + '</div>' +
'</div>' + '</div>' +
'<div class="one-lap info2">' + '<div class="one-lap info2">' +
'<div class="block-infos">' + '<div class="block-infos">' +
'<div class="one-line"><b class="line-label">' + Common._e("Street") + '</b><span id="BUDDY-ADR-STREET" class="reset-info">' + Common._e("unknown") + '</span></div>' + '<div class="one-line"><b class="line-label">' + Common._e("Street") + '</b><span id="BUDDY-ADR-STREET" class="reset-info">' + Common._e("unknown") + '</span></div>' +
'<div class="one-line"><b class="line-label">' + Common._e("City") + '</b><span id="BUDDY-ADR-LOCALITY" class="reset-info">' + Common._e("unknown") + '</span></div>' + '<div class="one-line"><b class="line-label">' + Common._e("City") + '</b><span id="BUDDY-ADR-LOCALITY" class="reset-info">' + Common._e("unknown") + '</span></div>' +
'<div class="one-line"><b class="line-label">' + Common._e("Postal code") + '</b><span id="BUDDY-ADR-PCODE" class="reset-info">' + Common._e("unknown") + '</span></div>' + '<div class="one-line"><b class="line-label">' + Common._e("Postal code") + '</b><span id="BUDDY-ADR-PCODE" class="reset-info">' + Common._e("unknown") + '</span></div>' +
'<div class="one-line"><b class="line-label">' + Common._e("Country") + '</b><span id="BUDDY-ADR-CTRY" class="reset-info">' + Common._e("unknown") + '</span></div>' + '<div class="one-line"><b class="line-label">' + Common._e("Country") + '</b><span id="BUDDY-ADR-CTRY" class="reset-info">' + Common._e("unknown") + '</span></div>' +
'</div>' + '</div>' +
'<div class="block-infos">' + '<div class="block-infos">' +
'<div class="one-line"><b class="line-label">' + Common._e("Biography") + '</b><span id="BUDDY-DESC" class="reset-info">' + Common._e("unknown") + '</span></div>' + '<div class="one-line"><b class="line-label">' + Common._e("Biography") + '</b><span id="BUDDY-DESC" class="reset-info">' + Common._e("unknown") + '</span></div>' +
'</div>' + '</div>' +
'</div>' + '</div>' +
'<div class="one-lap info3">' + '<div class="one-lap info3">' +
'<textarea class="rosternotes" rows="8" cols="60"></textarea>' + '<textarea class="rosternotes" rows="8" cols="60"></textarea>' +
'</div>' + '</div>' +
'</div>' + '</div>' +
'<div class="bottom">' + '<div class="bottom">' +
'<div class="wait wait-medium"></div>' + '<div class="wait wait-medium"></div>' +
'<a href="#" class="finish">' + Common._e("Close") + '</a>' + '<a href="#" class="finish">' + Common._e("Close") + '</a>' +
'</div>'; '</div>';
// Create the popup // Create the popup
Popup.create('userinfos', html); Popup.create('userinfos', html);
// Associate the events // Associate the events
UserInfos.instance(); UserInfos.instance();
// We retrieve the user's vcard // We retrieve the user's vcard
self.retrieve(xid); self.retrieve(xid);
} catch(e) { } catch(e) {
@ -137,7 +137,7 @@ var UserInfos = (function () {
try { try {
// Send the buddy comments // Send the buddy comments
self.sendBuddyComments(); self.sendBuddyComments();
// Destroy the popup // Destroy the popup
Popup.destroy('userinfos'); Popup.destroy('userinfos');
} catch(e) { } catch(e) {
@ -160,38 +160,38 @@ var UserInfos = (function () {
try { try {
// We setup the waiting indicator // We setup the waiting indicator
markers = 'vcard last'; markers = 'vcard last';
// We put the user's XID // We put the user's XID
$('#userinfos .buddy-xid').text(xid); $('#userinfos .buddy-xid').text(xid);
// We get the vCard // We get the vCard
vCard.get(xid, 'buddy'); vCard.get(xid, 'buddy');
// Get the highest resource for this XID // Get the highest resource for this XID
var cXID = Presence.highestPriority(xid); var cXID = Presence.highestPriority(xid);
var pXID = xid; var pXID = xid;
// If the user is logged in // If the user is logged in
if(cXID) { if(cXID) {
// Change the XID // Change the XID
pXID = cXID; pXID = cXID;
// We request the user's system infos // We request the user's system infos
self.query(cXID, 'version'); self.query(cXID, 'version');
// We request the user's local time // We request the user's local time
self.query(cXID, 'time'); self.query(cXID, 'time');
// Add these to the markers // Add these to the markers
markers += ' version time'; markers += ' version time';
} }
// We request the user's last activity // We request the user's last activity
self.query(pXID, 'last'); self.query(pXID, 'last');
// Add the markers // Add the markers
$('#userinfos .content').addClass(markers); $('#userinfos .content').addClass(markers);
// We request all the user's comments // We request all the user's comments
self.displayBuddyComments(xid); self.displayBuddyComments(xid);
} catch(e) { } catch(e) {
@ -214,26 +214,26 @@ var UserInfos = (function () {
// Generate a session ID // Generate a session ID
var id = genID(); var id = genID();
$('#userinfos').attr('data-' + mode, id); $('#userinfos').attr('data-' + mode, id);
// New IQ // New IQ
var iq = new JSJaCIQ(); var iq = new JSJaCIQ();
iq.setID(id); iq.setID(id);
iq.setType('get'); iq.setType('get');
iq.setTo(xid); iq.setTo(xid);
// Last activity query // Last activity query
if(mode == 'last') { if(mode == 'last') {
iq.setQuery(NS_LAST); iq.setQuery(NS_LAST);
con.send(iq, self.lastActivityUserInfos); con.send(iq, self.lastActivityUserInfos);
} }
// Time query // Time query
else if(mode == 'time') { else if(mode == 'time') {
iq.appendNode('time', {'xmlns': NS_URN_TIME}); iq.appendNode('time', {'xmlns': NS_URN_TIME});
con.send(iq, self.localTime); con.send(iq, self.localTime);
} }
// Version query // Version query
else if(mode == 'version') { else if(mode == 'version') {
iq.setQuery(NS_VERSION); iq.setQuery(NS_VERSION);
@ -273,7 +273,7 @@ var UserInfos = (function () {
try { try {
var value = DataStore.getDB(Connection.desktop_hash, 'rosternotes', xid); var value = DataStore.getDB(Connection.desktop_hash, 'rosternotes', xid);
if(value) { if(value) {
$('#userinfos .rosternotes').val(value); $('#userinfos .rosternotes').val(value);
} }
@ -296,26 +296,28 @@ var UserInfos = (function () {
// Extract the request ID // Extract the request ID
var id = iq.getID(); var id = iq.getID();
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
var from = Common.fullXID(Common.getStanzaFrom(iq)); var from = Common.fullXID(Common.getStanzaFrom(iq));
var seconds = $(iq.getNode()).find('query').attr('seconds'); var seconds = $(iq.getNode()).find('query').attr('seconds');
// Any seconds? // Any seconds?
if(seconds !== undefined) { if(seconds !== undefined) {
// Initialize the parsing // Initialize the parsing
var last; var last;
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 {
// Parse the date // Parse the date
@ -323,23 +325,25 @@ var UserInfos = (function () {
var time_now = date_now.getTime(); var time_now = date_now.getTime();
var date_last = new Date(date_now - (seconds * 1000)); var date_last = new Date(date_now - (seconds * 1000));
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);
} }
Console.log('Last activity received: ' + from); Console.log('Last activity received: ' + from);
} }
$('#userinfos .content').removeClass('last'); $('#userinfos .content').removeClass('last');
self.wait(); self.wait();
} catch(e) { } catch(e) {
@ -361,11 +365,12 @@ var UserInfos = (function () {
// Extract the request ID // Extract the request ID
var id = iq.getID(); var id = iq.getID();
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')) {
// Get the values // Get the values
@ -373,20 +378,24 @@ var UserInfos = (function () {
var name = $(xml).find('name').text(); var name = $(xml).find('name').text();
var version = $(xml).find('version').text(); var version = $(xml).find('version').text();
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)));
} }
$('#userinfos .content').removeClass('version'); $('#userinfos .content').removeClass('version');
self.wait(); self.wait();
} catch(e) { } catch(e) {
@ -408,33 +417,35 @@ var UserInfos = (function () {
// Extract the request ID // Extract the request ID
var id = iq.getID(); var id = iq.getID();
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
var xml = iq.getNode(); var xml = iq.getNode();
var tzo = $(xml).find('tzo').text(); var tzo = $(xml).find('tzo').text();
var utc = $(xml).find('utc').text(); var utc = $(xml).find('utc').text();
// 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);
// Then display it // Then display it
$(path + ' #BUDDY-TIME').text(local_string); $(path + ' #BUDDY-TIME').text(local_string);
} }
Console.log('Local time received: ' + Common.fullXID(Common.getStanzaFrom(iq))); Console.log('Local time received: ' + Common.fullXID(Common.getStanzaFrom(iq)));
} }
$('#userinfos .content').removeClass('time'); $('#userinfos .content').removeClass('time');
self.wait(); self.wait();
} catch(e) { } catch(e) {
@ -453,9 +464,10 @@ 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);
} }
@ -474,41 +486,43 @@ var UserInfos = (function () {
// Update the current value // Update the current value
var value = $('#userinfos .rosternotes').val(); var value = $('#userinfos .rosternotes').val();
var xid = $('#userinfos .buddy-xid').text(); var xid = $('#userinfos .buddy-xid').text();
// 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);
// Send the new buddy storage values // Send the new buddy storage values
var iq = new JSJaCIQ(); var iq = new JSJaCIQ();
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_ROSTERNOTES})); var storage = query.appendChild(iq.buildNode('storage', {'xmlns': NS_ROSTERNOTES}));
// We regenerate the XML // We regenerate the XML
var db_regex = new RegExp(('^' + Connection.desktop_hash + '_') + 'rosternotes' + ('_(.+)')); var db_regex = new RegExp(('^' + Connection.desktop_hash + '_') + 'rosternotes' + ('_(.+)'));
for(var i = 0; i < DataStore.storageDB.length; i++) { for(var i = 0; i < DataStore.storageDB.length; i++) {
// Get the pointer values // Get the pointer values
var current = DataStore.storageDB.key(i); var current = DataStore.storageDB.key(i);
// If the pointer is on a stored rosternote // If the pointer is on a stored rosternote
if(current.match(db_regex)) { if(current.match(db_regex)) {
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);
return false; return false;
} catch(e) { } catch(e) {
Console.error('UserInfos.sendBuddyComments', e); Console.error('UserInfos.sendBuddyComments', e);
@ -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 {
@ -558,11 +577,11 @@ var UserInfos = (function () {
$('#' + hash + ' .top .name .bc-name').text(nick); $('#' + hash + ' .top .name .bc-name').text(nick);
$('#page-switch .' + hash + ' .name').text(nick); $('#page-switch .' + hash + ' .name').text(nick);
} }
// Get the buddy PEP informations // Get the buddy PEP informations
PEP.displayAll(xid); PEP.displayAll(xid);
} }
// Display the buddy presence // Display the buddy presence
Presence.funnel(xid, hash); Presence.funnel(xid, hash);
} catch(e) { } catch(e) {
@ -582,16 +601,19 @@ 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);
}); });
$('#userinfos .bottom .finish').click(function() { $('#userinfos .bottom .finish').click(function() {
return self.close(); return self.close();
}); });

View file

@ -52,9 +52,10 @@ 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) {
Console.error('Utils.generateURL', e); Console.error('Utils.generateURL', e);
@ -76,7 +77,7 @@ var Utils = (function () {
if(value == condition) { if(value == condition) {
return ' disabled=""'; return ' disabled=""';
} }
return ''; return '';
} catch(e) { } catch(e) {
Console.error('Utils.disableInput', e); Console.error('Utils.disableInput', e);
@ -99,7 +100,7 @@ var Utils = (function () {
if(string.length > limit) { if(string.length > limit) {
string = string.substr(0, limit) + '...'; string = string.substr(0, limit) + '...';
} }
return string; return string;
} catch(e) { } catch(e) {
Console.error('Utils.truncate', e); Console.error('Utils.truncate', e);
@ -215,31 +216,37 @@ var Utils = (function () {
// Get browser name & version // Get browser name & version
var browser_name = BrowserDetect.browser; var browser_name = BrowserDetect.browser;
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) {
Console.error('Utils.isObsolete', e); Console.error('Utils.isObsolete', e);
@ -341,7 +348,7 @@ var Utils = (function () {
} catch(e) { } catch(e) {
Console.error('Utils.quoteMyNick', e); Console.error('Utils.quoteMyNick', e);
} }
}; };
@ -355,7 +362,7 @@ var Utils = (function () {
try { try {
var cat; var cat;
switch(ext) { switch(ext) {
// Images // Images
case 'jpg': case 'jpg':
@ -371,9 +378,9 @@ var Utils = (function () {
case 'psb': case 'psb':
case 'xcf': case 'xcf':
cat = 'image'; cat = 'image';
break; break;
// Videos // Videos
case 'ogv': case 'ogv':
case 'ogg': case 'ogg':
@ -395,9 +402,9 @@ var Utils = (function () {
case '3gp': case '3gp':
case 'avc': case 'avc':
cat = 'video'; cat = 'video';
break; break;
// Sounds // Sounds
case 'oga': case 'oga':
case 'mka': case 'mka':
@ -422,9 +429,9 @@ var Utils = (function () {
case 'snd': case 'snd':
case 'voc': case 'voc':
cat = 'audio'; cat = 'audio';
break; break;
// Documents // Documents
case 'pdf': case 'pdf':
case 'odt': case 'odt':
@ -463,9 +470,9 @@ var Utils = (function () {
case 'dhtml': case 'dhtml':
case 'mshtml': case 'mshtml':
cat = 'document'; cat = 'document';
break; break;
// Packages // Packages
case 'tgz': case 'tgz':
case 'gz': case 'gz':
@ -490,16 +497,16 @@ var Utils = (function () {
case 'arj': case 'arj':
case 'msi': case 'msi':
cat = 'package'; cat = 'package';
break; break;
// Others // Others
default: default:
cat = 'other'; cat = 'other';
break; break;
} }
return cat; return cat;
} catch(e) { } catch(e) {
Console.error('Utils.fileCategory', e); Console.error('Utils.fileCategory', e);
@ -517,7 +524,7 @@ var Utils = (function () {
try { try {
navigator.registerProtocolHandler('xmpp', JAPPIX_LOCATION + '?x=%s', SERVICE_NAME); navigator.registerProtocolHandler('xmpp', JAPPIX_LOCATION + '?x=%s', SERVICE_NAME);
return true; return true;
} catch(e) { } catch(e) {
Console.error('Utils.xmppLinksHandler', e); Console.error('Utils.xmppLinksHandler', 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
@ -595,26 +629,27 @@ var Utils = (function () {
try { try {
var array = []; var array = [];
// Any string to convert? // Any string to convert?
if(string) { if(string) {
// More than one item // More than one item
if(string.match(/,/gi)) { if(string.match(/,/gi)) {
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
array.push(string); array.push(string);
} }
return array; return array;
} catch(e) { } catch(e) {
Console.error('Utils.stringToArray', e); Console.error('Utils.stringToArray', e);
@ -634,20 +669,21 @@ 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;
for(var i = 0; i < array.length; i++) { for(var i = 0; i < array.length; i++) {
if(array[i] == value) { if(array[i] == value) {
index = i; index = i;
break; break;
} }
} }
return index; return index;
} catch(e) { } catch(e) {
Console.error('Utils.indexArrayValue', e); Console.error('Utils.indexArrayValue', e);

View file

@ -30,122 +30,122 @@ var vCard = (function () {
try { try {
// Popup HTML content // Popup HTML content
var html = var html =
'<div class="top">' + Common._e("Your profile") + '</div>' + '<div class="top">' + Common._e("Your profile") + '</div>' +
'<div class="tab">' + '<div class="tab">' +
'<a href="#" class="tab-active" data-key="1">' + Common._e("Identity") + '</a>' + '<a href="#" class="tab-active" data-key="1">' + Common._e("Identity") + '</a>' +
'<a href="#" data-key="2">' + Common._e("Profile image") + '</a>' + '<a href="#" data-key="2">' + Common._e("Profile image") + '</a>' +
'<a href="#" data-key="3">' + Common._e("Others") + '</a>' + '<a href="#" data-key="3">' + Common._e("Others") + '</a>' +
'</div>' + '</div>' +
'<div class="content">' + '<div class="content">' +
'<div id="lap1" class="lap-active one-lap forms">' + '<div id="lap1" class="lap-active one-lap forms">' +
'<fieldset>' + '<fieldset>' +
'<legend>' + Common._e("Personal") + '</legend>' + '<legend>' + Common._e("Personal") + '</legend>' +
'<label for="USER-FN">' + Common._e("Complete name") + '</label>' + '<label for="USER-FN">' + Common._e("Complete name") + '</label>' +
'<input type="text" id="USER-FN" data-vcard4="fn-text" class="vcard-item" placeholder="John Locke" />' + '<input type="text" id="USER-FN" data-vcard4="fn-text" class="vcard-item" placeholder="John Locke" />' +
'<label for="USER-NICKNAME">' + Common._e("Nickname") + '</label>' + '<label for="USER-NICKNAME">' + Common._e("Nickname") + '</label>' +
'<input type="text" id="USER-NICKNAME" data-vcard4="nickname-text" class="vcard-item" placeholder="Jo" />' + '<input type="text" id="USER-NICKNAME" data-vcard4="nickname-text" class="vcard-item" placeholder="Jo" />' +
'<label for="USER-N-GIVEN">' + Common._e("First name") + '</label>' + '<label for="USER-N-GIVEN">' + Common._e("First name") + '</label>' +
'<input type="text" id="USER-N-GIVEN" data-vcard4="n-given" class="vcard-item" placeholder="John" />' + '<input type="text" id="USER-N-GIVEN" data-vcard4="n-given" class="vcard-item" placeholder="John" />' +
'<label for="USER-N-FAMILY">' + Common._e("Last name") + '</label>' + '<label for="USER-N-FAMILY">' + Common._e("Last name") + '</label>' +
'<input type="text" id="USER-N-FAMILY" data-vcard4="n-surname" class="vcard-item" placeholder="Locke" />' + '<input type="text" id="USER-N-FAMILY" data-vcard4="n-surname" class="vcard-item" placeholder="Locke" />' +
'<label for="USER-BDAY">' + Common._e("Date of birth") + '</label>' + '<label for="USER-BDAY">' + Common._e("Date of birth") + '</label>' +
'<input type="text" id="USER-BDAY" data-vcard4="bday-date" class="vcard-item" pattern="^[0-9]{2}-[0-9]{2}-[0-9]{4}$" placeholder="16-02-1974" />' + '<input type="text" id="USER-BDAY" data-vcard4="bday-date" class="vcard-item" pattern="^[0-9]{2}-[0-9]{2}-[0-9]{4}$" placeholder="16-02-1974" />' +
'</fieldset>' + '</fieldset>' +
'<fieldset>' + '<fieldset>' +
'<legend>' + Common._e("Contact") + '</legend>' + '<legend>' + Common._e("Contact") + '</legend>' +
'<label for="USER-EMAIL-USERID">' + Common._e("E-mail") + '</label>' + '<label for="USER-EMAIL-USERID">' + Common._e("E-mail") + '</label>' +
'<input type="text" id="USER-EMAIL-USERID" data-vcard4="email-text" class="vcard-item" placeholder="john@locke.fam" />' + '<input type="text" id="USER-EMAIL-USERID" data-vcard4="email-text" class="vcard-item" placeholder="john@locke.fam" />' +
'<label for="USER-TEL-NUMBER">' + Common._e("Phone") + '</label>' + '<label for="USER-TEL-NUMBER">' + Common._e("Phone") + '</label>' +
'<input type="text" id="USER-TEL-NUMBER" data-vcard4="tel-uri" class="vcard-item" placeholder="John" placeholder="+1-292-321-0812" />' + '<input type="text" id="USER-TEL-NUMBER" data-vcard4="tel-uri" class="vcard-item" placeholder="John" placeholder="+1-292-321-0812" />' +
'<label for="USER-URL">' + Common._e("Website") + '</label>' + '<label for="USER-URL">' + Common._e("Website") + '</label>' +
'<input type="text" id="USER-URL" data-vcard4="url-uri" class="vcard-item" placeholder="john.locke.fam" />' + '<input type="text" id="USER-URL" data-vcard4="url-uri" class="vcard-item" placeholder="john.locke.fam" />' +
'</fieldset>' + '</fieldset>' +
'</div>' + '</div>' +
'<div id="lap2" class="one-lap forms">' + '<div id="lap2" class="one-lap forms">' +
'<fieldset>' + '<fieldset>' +
'<legend>' + Common._e("New") + '</legend>' + '<legend>' + Common._e("New") + '</legend>' +
'<input type="hidden" id="USER-PHOTO-TYPE" class="vcard-item" />' + '<input type="hidden" id="USER-PHOTO-TYPE" class="vcard-item" />' +
'<input type="hidden" id="USER-PHOTO-BINVAL" class="vcard-item" />' + '<input type="hidden" id="USER-PHOTO-BINVAL" class="vcard-item" />' +
'<form id="vcard-avatar" action="./server/avatar-upload.php" method="post" enctype="multipart/form-data">' + '<form id="vcard-avatar" action="./server/avatar-upload.php" method="post" enctype="multipart/form-data">' +
Interface.generateFileShare() + Interface.generateFileShare() +
'</form>' + '</form>' +
'</fieldset>' + '</fieldset>' +
'<fieldset>' + '<fieldset>' +
'<legend>' + Common._e("Current") + '</legend>' + '<legend>' + Common._e("Current") + '</legend>' +
'<div class="avatar-container"></div>' + '<div class="avatar-container"></div>' +
'<a href="#" class="one-button avatar-delete talk-images">' + Common._e("Delete") + '</a>' + '<a href="#" class="one-button avatar-delete talk-images">' + Common._e("Delete") + '</a>' +
'<div class="no-avatar">' + Common._e("What a pity! You have no profile image defined in your identity card!") + '</div>' + '<div class="no-avatar">' + Common._e("What a pity! You have no profile image defined in your identity card!") + '</div>' +
'</fieldset>' + '</fieldset>' +
'<div class="avatar-wait avatar-info">' + Common._e("Please wait while your avatar is uploaded...") + '</div>' + '<div class="avatar-wait avatar-info">' + Common._e("Please wait while your avatar is uploaded...") + '</div>' +
'<div class="avatar-ok avatar-info">' + Common._e("Here it is! A new beautiful profile image!") + '</div>' + '<div class="avatar-ok avatar-info">' + Common._e("Here it is! A new beautiful profile image!") + '</div>' +
'<div class="avatar-error avatar-info">' + Common._e("The image file is not supported or has a bad size.") + '</div>' + '<div class="avatar-error avatar-info">' + Common._e("The image file is not supported or has a bad size.") + '</div>' +
'</div>' + '</div>' +
'<div id="lap3" class="one-lap forms">' + '<div id="lap3" class="one-lap forms">' +
'<fieldset>' + '<fieldset>' +
'<legend>' + Common._e("Address") + '</legend>' + '<legend>' + Common._e("Address") + '</legend>' +
'<label for="USER-ADR-STREET">' + Common._e("Street") + '</label>' + '<label for="USER-ADR-STREET">' + Common._e("Street") + '</label>' +
'<input type="text" id="USER-ADR-STREET" data-vcard4="adr-street" class="vcard-item" placeholder="Manhattan" />' + '<input type="text" id="USER-ADR-STREET" data-vcard4="adr-street" class="vcard-item" placeholder="Manhattan" />' +
'<label for="USER-ADR-LOCALITY">' + Common._e("City") + '</label>' + '<label for="USER-ADR-LOCALITY">' + Common._e("City") + '</label>' +
'<input type="text" id="USER-ADR-LOCALITY" data-vcard4="adr-locality" class="vcard-item" placeholder="New-York" />' + '<input type="text" id="USER-ADR-LOCALITY" data-vcard4="adr-locality" class="vcard-item" placeholder="New-York" />' +
'<label for="USER-ADR-PCODE">' + Common._e("Postal code") + '</label>' + '<label for="USER-ADR-PCODE">' + Common._e("Postal code") + '</label>' +
'<input type="text" id="USER-ADR-PCODE" data-vcard4="adr-code" class="vcard-item" placeholder="10002" />' + '<input type="text" id="USER-ADR-PCODE" data-vcard4="adr-code" class="vcard-item" placeholder="10002" />' +
'<label for="USER-ADR-CTRY">' + Common._e("Country") + '</label>' + '<label for="USER-ADR-CTRY">' + Common._e("Country") + '</label>' +
'<input type="text" id="USER-ADR-CTRY" data-vcard4="adr-country" class="vcard-item" placeholder="USA" />' + '<input type="text" id="USER-ADR-CTRY" data-vcard4="adr-country" class="vcard-item" placeholder="USA" />' +
'</fieldset>' + '</fieldset>' +
'<fieldset>' + '<fieldset>' +
'<legend>' + Common._e("Biography") + '</legend>' + '<legend>' + Common._e("Biography") + '</legend>' +
'<textarea id="USER-DESC" data-vcard4="note-text" rows="8" cols="60" class="vcard-item"></textarea>' + '<textarea id="USER-DESC" data-vcard4="note-text" rows="8" cols="60" class="vcard-item"></textarea>' +
'</fieldset>' + '</fieldset>' +
'</div>' + '</div>' +
'<div class="infos">' + '<div class="infos">' +
'<p class="infos-title">' + Common._e("Important notice") + '</p>' + '<p class="infos-title">' + Common._e("Important notice") + '</p>' +
'<p>' + Common._e("Be careful with the information you store into your profile, because it might be accessible by everyone (even someone you don't want to).") + '</p>' + '<p>' + Common._e("Be careful with the information you store into your profile, because it might be accessible by everyone (even someone you don't want to).") + '</p>' +
'<p>' + Common._e("Not everything is private on XMPP; this is one of those things, your public profile (vCard).") + '</p>' + '<p>' + Common._e("Not everything is private on XMPP; this is one of those things, your public profile (vCard).") + '</p>' +
'<p>' + Common.printf(Common._e("It is strongly recommended to upload a profile image (%s maximum), like a picture of yourself, because that makes you easily recognizable by your friends."), JAPPIX_MAX_UPLOAD) + '</p>' + '<p>' + Common.printf(Common._e("It is strongly recommended to upload a profile image (%s maximum), like a picture of yourself, because that makes you easily recognizable by your friends."), JAPPIX_MAX_UPLOAD) + '</p>' +
'<p><b><a href="https://me.jappix.com/new" target="_blank">' + Common._e("Enable my public profile") + ' »</a></b></p>' + '<p><b><a href="https://me.jappix.com/new" target="_blank">' + Common._e("Enable my public profile") + ' »</a></b></p>' +
'</div>' + '</div>' +
'</div>' + '</div>' +
'<div class="bottom">' + '<div class="bottom">' +
'<div class="wait wait-medium"></div>' + '<div class="wait wait-medium"></div>' +
'<a href="#" class="finish save disabled">' + Common._e("Save") + '</a>' + '<a href="#" class="finish save disabled">' + Common._e("Save") + '</a>' +
'<a href="#" class="finish cancel">' + Common._e("Cancel") + '</a>' + '<a href="#" class="finish cancel">' + Common._e("Cancel") + '</a>' +
'</div>'; '</div>';
// Create the popup // Create the popup
Popup.create('vcard', html); Popup.create('vcard', html);
// Associate the events // Associate the events
self.instance(); self.instance();
// We get the VCard informations // We get the VCard informations
self.get(Common.getXID(), 'user'); self.get(Common.getXID(), 'user');
} catch(e) { } catch(e) {
@ -167,12 +167,12 @@ var vCard = (function () {
try { try {
// Destroy the popup // Destroy the popup
Popup.destroy('vcard'); Popup.destroy('vcard');
// Create the welcome end popup? // Create the welcome end popup?
if(Welcome.is_done) { if(Welcome.is_done) {
// Open popup // Open popup
Me.open(); Me.open();
// Unavoidable popup // Unavoidable popup
$('#me').addClass('unavoidable'); $('#me').addClass('unavoidable');
} }
@ -217,7 +217,7 @@ var vCard = (function () {
try { try {
// Reset the avatar info // Reset the avatar info
$('#vcard .avatar-info').hide().stopTime(); $('#vcard .avatar-info').hide().stopTime();
// Show the wait info // Show the wait info
$('#vcard .avatar-wait').show(); $('#vcard .avatar-wait').show();
} catch(e) { } catch(e) {
@ -238,53 +238,53 @@ var vCard = (function () {
try { try {
// Data selector // Data selector
var dData = $(responseXML).find('jappix'); var dData = $(responseXML).find('jappix');
// Not current upload session? // Not current upload session?
if(parseInt(dData.attr('id')) != parseInt($('#vcard-avatar input[name="id"]').val())) { if(parseInt(dData.attr('id')) != parseInt($('#vcard-avatar input[name="id"]').val())) {
return; return;
} }
// Reset the avatar info // Reset the avatar info
$('#vcard .avatar-info').hide().stopTime(); $('#vcard .avatar-info').hide().stopTime();
// Process the returned data // Process the returned data
if(!dData.find('error').size()) { if(!dData.find('error').size()) {
// Read the values // Read the values
var aType = dData.find('type').text(); var aType = dData.find('type').text();
var aBinval = dData.find('binval').text(); var aBinval = dData.find('binval').text();
// We remove everything that isn't useful right here // We remove everything that isn't useful right here
$('#vcard .no-avatar').hide(); $('#vcard .no-avatar').hide();
$('#vcard .avatar').remove(); $('#vcard .avatar').remove();
// We display the delete button // We display the delete button
$('#vcard .avatar-delete').show(); $('#vcard .avatar-delete').show();
// We tell the user it's okay // We tell the user it's okay
$('#vcard .avatar-ok').show(); $('#vcard .avatar-ok').show();
// Timer // Timer
$('#vcard .avatar-info').oneTime('10s', function() { $('#vcard .avatar-info').oneTime('10s', function() {
$(this).hide(); $(this).hide();
}); });
// We put the base64 values in a hidden input to be sent // We put the base64 values in a hidden input to be sent
$('#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>');
} }
// Any error? // Any error?
else { else {
$('#vcard .avatar-error').show(); $('#vcard .avatar-error').show();
// Timer // Timer
$('#vcard .avatar-info').oneTime('10s', function() { $('#vcard .avatar-info').oneTime('10s', function() {
$(this).hide(); $(this).hide();
}); });
Console.error('Error while uploading the avatar', dData.find('error').text()); Console.error('Error while uploading the avatar', dData.find('error').text());
} }
} catch(e) { } catch(e) {
@ -306,10 +306,10 @@ var vCard = (function () {
$('#vcard .avatar-info').stopTime(); $('#vcard .avatar-info').stopTime();
$('#vcard .avatar-info, #vcard .avatar-wait, #vcard .avatar-error, #vcard .avatar-ok, #vcard .avatar-delete').hide(); $('#vcard .avatar-info, #vcard .avatar-wait, #vcard .avatar-error, #vcard .avatar-ok, #vcard .avatar-delete').hide();
$('#vcard .avatar').remove(); $('#vcard .avatar').remove();
// We reset the input value // We reset the input value
$('#USER-PHOTO-TYPE, #USER-PHOTO-BINVAL').val(''); $('#USER-PHOTO-TYPE, #USER-PHOTO-BINVAL').val('');
// We show the avatar-uploading request // We show the avatar-uploading request
$('#vcard .no-avatar').show(); $('#vcard .no-avatar').show();
} catch(e) { } catch(e) {
@ -333,7 +333,7 @@ var vCard = (function () {
try { try {
// Generate the new ID // Generate the new ID
id = 'USER-' + id; id = 'USER-' + id;
// Can append the content // Can append the content
if((type == 'user') && !Common.exists('#vcard #' + id)) { if((type == 'user') && !Common.exists('#vcard #' + id)) {
$('#vcard .content').append('<input id="' + id + '" class="vcard-item" type="hidden" />'); $('#vcard .content').append('<input id="' + id + '" class="vcard-item" type="hidden" />');
@ -357,32 +357,30 @@ var vCard = (function () {
try { try {
// Generate a special ID // Generate a special ID
var id = genID(); var id = genID();
// New IQ // New IQ
var iq = new JSJaCIQ(); var iq = new JSJaCIQ();
iq.setID(id); iq.setID(id);
iq.setType('get'); iq.setType('get');
iq.appendNode('vCard', {'xmlns': NS_VCARD}); iq.appendNode('vCard', {'xmlns': NS_VCARD});
// Send the IQ to the good user // Send the IQ to the good user
if(type == 'user') { if(type == 'user') {
// Show the wait icon // Show the wait icon
$('#vcard .wait').show(); $('#vcard .wait').show();
// Apply the session ID // Apply the session ID
$('#vcard').attr('data-vcard', id); $('#vcard').attr('data-vcard', id);
// 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();
// Apply the session ID // Apply the session ID
$('#userinfos').attr('data-vcard', id); $('#userinfos').attr('data-vcard', id);
// Send the IQ // Send the IQ
iq.setTo(to); iq.setTo(to);
con.send(iq, self.handleBuddy); con.send(iq, self.handleBuddy);
@ -446,7 +444,7 @@ var vCard = (function () {
// Define some paths // Define some paths
var path_vcard = '#vcard[data-vcard="' + iqID + '"]'; var path_vcard = '#vcard[data-vcard="' + iqID + '"]';
var path_userInfos = '#userinfos[data-vcard="' + iqID + '"]'; var path_userInfos = '#userinfos[data-vcard="' + iqID + '"]';
// End if the session does not exist // End if the session does not exist
if(((type == 'user') && !Common.exists(path_vcard)) || ((type == 'buddy') && !Common.exists(path_userInfos))) { if(((type == 'user') && !Common.exists(path_vcard)) || ((type == 'buddy') && !Common.exists(path_userInfos))) {
return; return;
@ -454,80 +452,85 @@ var vCard = (function () {
// We retrieve main values // We retrieve main values
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();
// Not yet added? // Not yet added?
if(!Utils.existArrayValue(values_yet, currentID)) { if(!Utils.existArrayValue(values_yet, currentID)) {
// Create an input if it does not exist // Create an input if it does not exist
self.createInput(values_yet, type); self.createInput(values_yet, type);
// 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') {
$(path_vcard + ' #USER-' + currentID).val(currentText); $(path_vcard + ' #USER-' + currentID).val(currentText);
} }
// Avoid duplicating the value // Avoid duplicating the value
values_yet.push(currentID); values_yet.push(currentID);
} }
}); });
} }
// Node without any parent // Node without any parent
else { else {
// Get the node values // Get the node values
var currentText = $(this).text(); var currentText = $(this).text();
// Not yet added? // Not yet added?
if(!Utils.existArrayValue(values_yet, tokenname)) { if(!Utils.existArrayValue(values_yet, tokenname)) {
// Create an input if it does not exist // Create an input if it does not exist
self.createInput(tokenname, type); self.createInput(tokenname, type);
// Userinfos viewer popup // Userinfos viewer popup
if((type == 'buddy') && currentText) { if((type == 'buddy') && currentText) {
// 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>';
} }
// Description modification // Description modification
else if(tokenname == 'DESC') { else if(tokenname == 'DESC') {
currentText = Filter.message(currentText, Name.getBuddy(iqFrom).htmlEnc(), true); currentText = Filter.message(currentText, Name.getBuddy(iqFrom).htmlEnc(), true);
} }
// Other stuffs // Other stuffs
else { else {
currentText = currentText.htmlEnc(); currentText = currentText.htmlEnc();
} }
$(path_userInfos + ' #BUDDY-' + tokenname).html(currentText); $(path_userInfos + ' #BUDDY-' + tokenname).html(currentText);
} }
// 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);
} }
@ -538,27 +541,25 @@ var vCard = (function () {
if(type == 'buddy') { if(type == 'buddy') {
// Get the avatar XML // Get the avatar XML
var xml = DataStore.getPersistent('global', 'avatar', iqFrom); var xml = DataStore.getPersistent('global', 'avatar', iqFrom);
// If there were no stored avatar previously // If there were no stored avatar previously
if($(Common.XMLFromString(xml)).find('type').text() == 'none') { if($(Common.XMLFromString(xml)).find('type').text() == 'none') {
xml = xml.replace(/<forced>false<\/forced>/gi, '<forced>true</forced>'); xml = xml.replace(/<forced>false<\/forced>/gi, '<forced>true</forced>');
DataStore.setPersistent(Common.getXID(), 'avatar', iqFrom, xml); DataStore.setPersistent(Common.getXID(), 'avatar', iqFrom, xml);
} }
// Handle the user avatar // Handle the user avatar
Avatar.handle(iq); Avatar.handle(iq);
} }
// The avatar values targets // The avatar values targets
var aBinval, aType, aContainer; var aBinval, aType, aContainer;
if(type == 'user') { if(type == 'user') {
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';
@ -570,18 +571,20 @@ var vCard = (function () {
if(!aType) { if(!aType) {
aType = 'image/png'; aType = 'image/png';
} }
if(type == 'user') { if(type == 'user') {
// We move all the things that we don't need in that case // We move all the things that we don't need in that case
$(path_vcard + ' .no-avatar').hide(); $(path_vcard + ' .no-avatar').hide();
$(path_vcard + ' .avatar-delete').show(); $(path_vcard + ' .avatar-delete').show();
$(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') {
$(aContainer).replaceWith('<div class="avatar-container"><img class="avatar" src="' + './images/others/default-avatar.png' + '" alt="" /></div>'); $(aContainer).replaceWith('<div class="avatar-container"><img class="avatar" src="' + './images/others/default-avatar.png' + '" alt="" /></div>');
} }
@ -593,7 +596,7 @@ var vCard = (function () {
} else { } else {
UserInfos.vCard(); UserInfos.vCard();
} }
Console.log('vCard received: ' + iqFrom); Console.log('vCard received: ' + iqFrom);
} catch(e) { } catch(e) {
Console.error('vCard.handle', e); Console.error('vCard.handle', e);
@ -613,18 +616,18 @@ var vCard = (function () {
// Send both vcard-temp + vCard4 // Send both vcard-temp + vCard4
self._sendLegacy(); self._sendLegacy();
self._sendForward(); self._sendForward();
// Send the user nickname & avatar over PEP // Send the user nickname & avatar over PEP
if(Features.enabledPEP()) { if(Features.enabledPEP()) {
self._sendPubsub(); self._sendPubsub();
} }
// Close the vCard stuffs // Close the vCard stuffs
self.close(); self.close();
// Get our new avatar // Get our new avatar
Avatar.get(Common.getXID(), 'force', 'true', 'forget'); Avatar.get(Common.getXID(), 'force', 'true', 'forget');
Console.log('vCard sent.'); Console.log('vCard sent.');
} catch(e) { } catch(e) {
Console.error('vCard.send', e); Console.error('vCard.send', e);
@ -668,11 +671,12 @@ 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(
Common.explodeThis('-', item_id, 1), Common.explodeThis('-', item_id, 1),
@ -723,13 +727,13 @@ var vCard = (function () {
try { try {
var iq = new JSJaCIQ(); var iq = new JSJaCIQ();
iq.setType('set'); iq.setType('set');
var vCard = iq.appendNode('vCard', { var vCard = iq.appendNode('vCard', {
'xmlns': NS_VCARD 'xmlns': NS_VCARD
}); });
self._generateTree(NS_VCARD, iq, vCard); self._generateTree(NS_VCARD, iq, vCard);
con.send(iq); con.send(iq);
} catch(e) { } catch(e) {
Console.error('vCard._sendLegacy', e); Console.error('vCard._sendLegacy', e);
@ -748,7 +752,7 @@ var vCard = (function () {
try { try {
var iq = new JSJaCIQ(); var iq = new JSJaCIQ();
iq.setType('set'); iq.setType('set');
// Build Pubsub headers // Build Pubsub headers
var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB}); var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB});
@ -766,9 +770,9 @@ var vCard = (function () {
var vcard = item.appendChild(iq.buildNode('vcard', { var vcard = item.appendChild(iq.buildNode('vcard', {
'xmlns': NS_IETF_VCARD4 'xmlns': NS_IETF_VCARD4
})); }));
self._generateTree(NS_IETF_VCARD4, iq, vcard); self._generateTree(NS_IETF_VCARD4, iq, vcard);
con.send(iq); con.send(iq);
// Make it publicly-viewable // Make it publicly-viewable
@ -791,7 +795,7 @@ var vCard = (function () {
// Generate some values // Generate some values
var photo_bin = $('#USER-PHOTO-BINVAL').val(); var photo_bin = $('#USER-PHOTO-BINVAL').val();
var photo_data = Base64.decode(photo_bin) || ''; var photo_data = Base64.decode(photo_bin) || '';
// Data to be sent // Data to be sent
var send_data = {}; var send_data = {};
send_data[NS_NICK] = $('#USER-NICKNAME').val(); send_data[NS_NICK] = $('#USER-NICKNAME').val();
@ -801,12 +805,12 @@ var vCard = (function () {
'id': (hex_sha1(photo_data) || ''), 'id': (hex_sha1(photo_data) || ''),
'bytes': (photo_data.length || '') 'bytes': (photo_data.length || '')
}; };
// Generate the XML // Generate the XML
$.each(send_data, function(namespace, data) { $.each(send_data, function(namespace, data) {
var iq = new JSJaCIQ(); var iq = new JSJaCIQ();
iq.setType('set'); iq.setType('set');
var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB}); var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB});
var publish = pubsub.appendChild(iq.buildNode('publish', {'node': namespace, 'xmlns': NS_PUBSUB})); var publish = pubsub.appendChild(iq.buildNode('publish', {'node': namespace, 'xmlns': NS_PUBSUB}));
@ -815,26 +819,26 @@ var vCard = (function () {
if(namespace === NS_NICK) { if(namespace === NS_NICK) {
item = publish.appendChild(iq.buildNode('item', {'xmlns': NS_PUBSUB})); item = publish.appendChild(iq.buildNode('item', {'xmlns': NS_PUBSUB}));
// Nickname element // Nickname element
item.appendChild(iq.buildNode('nick', {'xmlns': NS_NICK}, data)); item.appendChild(iq.buildNode('nick', {'xmlns': NS_NICK}, data));
} else if(namespace === NS_URN_ADATA || namespace === NS_URN_AMETA) { } else if(namespace === NS_URN_ADATA || namespace === NS_URN_AMETA) {
item = publish.appendChild(iq.buildNode('item', {'xmlns': NS_PUBSUB})); item = publish.appendChild(iq.buildNode('item', {'xmlns': NS_PUBSUB}));
// Apply the SHA-1 hash // Apply the SHA-1 hash
if(send_data[NS_URN_AMETA].id) { if(send_data[NS_URN_AMETA].id) {
item.setAttribute('id', send_data[NS_URN_AMETA].id); item.setAttribute('id', send_data[NS_URN_AMETA].id);
} }
// Append XML nodes depending on namespace // Append XML nodes depending on namespace
if(namespace === NS_URN_ADATA) { if(namespace === NS_URN_ADATA) {
item.appendChild(iq.buildNode('data', {'xmlns': NS_URN_ADATA}, data)); item.appendChild(iq.buildNode('data', {'xmlns': NS_URN_ADATA}, data));
} else if(namespace === NS_URN_AMETA) { } else if(namespace === NS_URN_AMETA) {
var metadata = item.appendChild(iq.buildNode('metadata', {'xmlns': NS_URN_AMETA})); var metadata = item.appendChild(iq.buildNode('metadata', {'xmlns': NS_URN_AMETA}));
if(data) { if(data) {
var meta_info = metadata.appendChild(iq.buildNode('info', {'xmlns': NS_URN_AMETA})); var meta_info = metadata.appendChild(iq.buildNode('info', {'xmlns': NS_URN_AMETA}));
if(data.type) if(data.type)
meta_info.setAttribute('type', data.type); meta_info.setAttribute('type', data.type);
if(data.id) if(data.id)
@ -870,62 +874,77 @@ var vCard = (function () {
$(document).oneTime(10, function() { $(document).oneTime(10, function() {
$('#vcard input:first').focus(); $('#vcard input:first').focus();
}); });
// 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);
}); });
$('#vcard .avatar-delete').click(function() { $('#vcard .avatar-delete').click(function() {
return self.deleteAvatar(); return self.deleteAvatar();
}); });
$('#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;
}); });
// Avatar upload vars // Avatar upload vars
var avatar_options = { var avatar_options = {
dataType: 'xml', dataType: 'xml',
beforeSubmit: self.waitAvatarUpload, beforeSubmit: self.waitAvatarUpload,
success: self.handleAvatarUpload success: self.handleAvatarUpload
}; };
// 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;
}); });
// Placeholders // Placeholders
$('#vcard-avatar input[type="text"]').placeholder(); $('#vcard-avatar input[type="text"]').placeholder();
} catch(e) { } catch(e) {

View file

@ -23,7 +23,7 @@ var Welcome = (function () {
/* Variables */ /* Variables */
self.is_done = false; self.is_done = false;
/** /**
* Opens the welcome tools * Opens the welcome tools
* @public * @public
@ -34,125 +34,125 @@ var Welcome = (function () {
try { try {
// Share message // Share message
var share_msg = Common.printf(Common._e("Using Jappix, an open social platform. I am %s!"), Common.getXID()); var share_msg = Common.printf(Common._e("Using Jappix, an open social platform. I am %s!"), Common.getXID());
// Popup HTML content // Popup HTML content
var html = var html =
'<div class="top">' + Common._e("Welcome!") + '</div>' + '<div class="top">' + Common._e("Welcome!") + '</div>' +
'<div class="tab">' + '<div class="tab">' +
'<a href="#" class="tab-active" data-step="1">' + Common._e("Options") + '</a>' + '<a href="#" class="tab-active" data-step="1">' + Common._e("Options") + '</a>' +
'<a href="#" class="tab-missing" data-step="2">' + Common._e("Friends") + '</a>' + '<a href="#" class="tab-missing" data-step="2">' + Common._e("Friends") + '</a>' +
'<a href="#" class="tab-missing" data-step="3">' + Common._e("Share") + '</a>' + '<a href="#" class="tab-missing" data-step="3">' + Common._e("Share") + '</a>' +
'</div>' + '</div>' +
'<div class="content">' + '<div class="content">' +
'<div class="lap-active one-lap welcome1">' + '<div class="lap-active one-lap welcome1">' +
'<div class="infos">' + '<div class="infos">' +
'<p class="infos-title">' + Common._e("Welcome on Jappix, your own social cloud!") + '</p>' + '<p class="infos-title">' + Common._e("Welcome on Jappix, your own social cloud!") + '</p>' +
'<p>' + Common._e("Before you start using it, you will have to change some settings, search for friends and complete your profile.") + '</p>' + '<p>' + Common._e("Before you start using it, you will have to change some settings, search for friends and complete your profile.") + '</p>' +
'</div>' + '</div>' +
'<a href="#" class="box enabled" title="' + Common._e("Click to disable") + '">' + '<a href="#" class="box enabled" title="' + Common._e("Click to disable") + '">' +
'<span class="option">' + Common._e("Sounds") + '</span>' + '<span class="option">' + Common._e("Sounds") + '</span>' +
'<span class="description">' + Common._e("Enable notification sounds") + '</span>' + '<span class="description">' + Common._e("Enable notification sounds") + '</span>' +
'<span class="image sound talk-images"></span>' + '<span class="image sound talk-images"></span>' +
'<span class="tick talk-images"></span>' + '<span class="tick talk-images"></span>' +
'</a>' + '</a>' +
'<a href="#" class="box enabled pep-hidable" title="' + Common._e("Click to disable") + '">' + '<a href="#" class="box enabled pep-hidable" title="' + Common._e("Click to disable") + '">' +
'<span class="option">' + Common._e("Geolocation") + '</span>' + '<span class="option">' + Common._e("Geolocation") + '</span>' +
'<span class="description">' + Common._e("Share your position on the globe") + '</span>' + '<span class="description">' + Common._e("Share your position on the globe") + '</span>' +
'<span class="image geolocation talk-images"></span>' + '<span class="image geolocation talk-images"></span>' +
'<span class="tick talk-images"></span>' + '<span class="tick talk-images"></span>' +
'</a>' + '</a>' +
'<a href="#" class="box xmpplinks-hidable" title="' + Common._e("Click to enable") + '">' + '<a href="#" class="box xmpplinks-hidable" title="' + Common._e("Click to enable") + '">' +
'<span class="option">' + Common._e("XMPP links") + '</span>' + '<span class="option">' + Common._e("XMPP links") + '</span>' +
'<span class="description">' + Common._e("Open XMPP links with Jappix") + '</span>' + '<span class="description">' + Common._e("Open XMPP links with Jappix") + '</span>' +
'<span class="image xmpp talk-images"></span>' + '<span class="image xmpp talk-images"></span>' +
'<span class="tick talk-images"></span>' + '<span class="tick talk-images"></span>' +
'</a>' + '</a>' +
'<a href="#" class="box mam-hidable pref" title="' + Common._e("Click to enable") + '">' + '<a href="#" class="box mam-hidable pref" title="' + Common._e("Click to enable") + '">' +
'<span class="option">' + Common._e("Message archiving") + '</span>' + '<span class="option">' + Common._e("Message archiving") + '</span>' +
'<span class="description">' + Common._e("Store a history of your chats") + '</span>' + '<span class="description">' + Common._e("Store a history of your chats") + '</span>' +
'<span class="image mam talk-images"></span>' + '<span class="image mam talk-images"></span>' +
'<span class="tick talk-images"></span>' + '<span class="tick talk-images"></span>' +
'</a>' + '</a>' +
'<a href="#" class="box" title="' + Common._e("Click to enable") + '">' + '<a href="#" class="box" title="' + Common._e("Click to enable") + '">' +
'<span class="option">' + Common._e("Offline friends") + '</span>' + '<span class="option">' + Common._e("Offline friends") + '</span>' +
'<span class="description">' + Common._e("Don\'t hide offline friends") + '</span>' + '<span class="description">' + Common._e("Don\'t hide offline friends") + '</span>' +
'<span class="image offline talk-images"></span>' + '<span class="image offline talk-images"></span>' +
'<span class="tick talk-images"></span>' + '<span class="tick talk-images"></span>' +
'</a>' + '</a>' +
'</div>' + '</div>' +
'<div class="one-lap welcome2">' + '<div class="one-lap welcome2">' +
'<div class="infos">' + '<div class="infos">' +
'<p class="infos-title">' + Common._e("Friends") + '</p>' + '<p class="infos-title">' + Common._e("Friends") + '</p>' +
'<p>' + Common._e("Use this tool to find your friends on the server you are using right now, or add them later.") + '</p>' + '<p>' + Common._e("Use this tool to find your friends on the server you are using right now, or add them later.") + '</p>' +
'</div>' + '</div>' +
'<div class="results welcome-results"></div>' + '<div class="results welcome-results"></div>' +
'</div>' + '</div>' +
'<div class="one-lap welcome3">' + '<div class="one-lap welcome3">' +
'<div class="infos">' + '<div class="infos">' +
'<p class="infos-title">' + Common._e("Share") + '</p>' + '<p class="infos-title">' + Common._e("Share") + '</p>' +
'<p>' + Common._e("Good job! Now, you can share Jappix with your friends!") + '</p>' + '<p>' + Common._e("Good job! Now, you can share Jappix with your friends!") + '</p>' +
'<p>' + Common._e("When you will press the save button, the profile editor will be opened. Happy socializing!") + '</p>' + '<p>' + Common._e("When you will press the save button, the profile editor will be opened. Happy socializing!") + '</p>' +
'</div>' + '</div>' +
'<a class="box share first" href="http://www.facebook.com/sharer/sharer.php?u=' + Common.encodeQuotes(Utils.generateURL(JAPPIX_LOCATION)) + '" target="_blank">' + '<a class="box share first" href="http://www.facebook.com/sharer/sharer.php?u=' + Common.encodeQuotes(Utils.generateURL(JAPPIX_LOCATION)) + '" target="_blank">' +
'<span class="logo facebook welcome-images"></span>' + '<span class="logo facebook welcome-images"></span>' +
'<span class="name">Facebook</span>' + '<span class="name">Facebook</span>' +
'<span class="description">' + Common.printf(Common._e("Share Jappix on %s"), 'Facebook') + '</span>' + '<span class="description">' + Common.printf(Common._e("Share Jappix on %s"), 'Facebook') + '</span>' +
'<span class="go talk-images"></span>' + '<span class="go talk-images"></span>' +
'</a>' + '</a>' +
'<a class="box share" href="http://twitter.com/intent/tweet?text=' + Common.encodeQuotes(share_msg) + '&amp;url=' + Common.encodeQuotes(Utils.generateURL(JAPPIX_LOCATION)) + '" target="_blank">' + '<a class="box share" href="http://twitter.com/intent/tweet?text=' + Common.encodeQuotes(share_msg) + '&amp;url=' + Common.encodeQuotes(Utils.generateURL(JAPPIX_LOCATION)) + '" target="_blank">' +
'<span class="logo twitter welcome-images"></span>' + '<span class="logo twitter welcome-images"></span>' +
'<span class="name">Twitter</span>' + '<span class="name">Twitter</span>' +
'<span class="description">' + Common.printf(Common._e("Share Jappix on %s"), 'Twitter') + '</span>' + '<span class="description">' + Common.printf(Common._e("Share Jappix on %s"), 'Twitter') + '</span>' +
'<span class="go talk-images"></span>' + '<span class="go talk-images"></span>' +
'</a>' + '</a>' +
'<a class="box share" href="https://plus.google.com/share?url=' + Common.encodeQuotes(Utils.generateURL(JAPPIX_LOCATION)) + '" target="_blank">' + '<a class="box share" href="https://plus.google.com/share?url=' + Common.encodeQuotes(Utils.generateURL(JAPPIX_LOCATION)) + '" target="_blank">' +
'<span class="logo plus welcome-images"></span>' + '<span class="logo plus welcome-images"></span>' +
'<span class="name">Google+</span>' + '<span class="name">Google+</span>' +
'<span class="description">' + Common.printf(Common._e("Share Jappix on %s"), 'Google+') + '</span>' + '<span class="description">' + Common.printf(Common._e("Share Jappix on %s"), 'Google+') + '</span>' +
'<span class="go talk-images"></span>' + '<span class="go talk-images"></span>' +
'</a>' + '</a>' +
'<a class="box share" href="https://waaave.com/spot/jappix/" target="_blank">' + '<a class="box share" href="https://waaave.com/spot/jappix/" target="_blank">' +
'<span class="logo waaave welcome-images"></span>' + '<span class="logo waaave welcome-images"></span>' +
'<span class="name">Waaave</span>' + '<span class="name">Waaave</span>' +
'<span class="description">' + Common.printf(Common._e("Follow Jappix topic on %s"), 'Waaave') + '</span>' + '<span class="description">' + Common.printf(Common._e("Follow Jappix topic on %s"), 'Waaave') + '</span>' +
'<span class="go talk-images"></span>' + '<span class="go talk-images"></span>' +
'</a>' + '</a>' +
'</div>' + '</div>' +
'</div>' + '</div>' +
'<div class="bottom">' + '<div class="bottom">' +
'<div class="wait wait-medium"></div>' + '<div class="wait wait-medium"></div>' +
'<a href="#" class="finish next">' + Common._e("Next") + ' »</a>' + '<a href="#" class="finish next">' + Common._e("Next") + ' »</a>' +
'<a href="#" class="finish save">' + Common._e("Save") + '</a>' + '<a href="#" class="finish save">' + Common._e("Save") + '</a>' +
'</div>'; '</div>';
// Create the popup // Create the popup
Popup.create('welcome', html); Popup.create('welcome', html);
// Unavoidable popup // Unavoidable popup
$('#welcome').addClass('unavoidable'); $('#welcome').addClass('unavoidable');
// Apply the features // Apply the features
Features.apply('welcome'); Features.apply('welcome');
// Associate the events // Associate the events
self.instance(); self.instance();
Console.log('Welcome assistant opened.'); Console.log('Welcome assistant opened.');
} catch(e) { } catch(e) {
Console.error('Welcome.open', e); Console.error('Welcome.open', e);
@ -194,19 +194,20 @@ var Welcome = (function () {
var content = welcome + '.content .'; var content = welcome + '.content .';
var tab = welcome + '.tab '; var tab = welcome + '.tab ';
var wait = $(welcome + '.wait'); var wait = $(welcome + '.wait');
$(content + 'one-lap').hide(); $(content + 'one-lap').hide();
$(content + 'welcome' + id).show(); $(content + 'welcome' + id).show();
$(tab + 'a').removeClass('tab-active'); $(tab + 'a').removeClass('tab-active');
$(tab + 'a[data-step="' + id + '"]').addClass('tab-active').removeClass('tab-missing'); $(tab + 'a[data-step="' + id + '"]').addClass('tab-active').removeClass('tab-missing');
// 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();
} }
// If this is ID 2: vJUD search // If this is ID 2: vJUD search
if(id == 2) { if(id == 2) {
wait.show(); wait.show();
@ -235,26 +236,26 @@ var Welcome = (function () {
// Sends the options // Sends the options
var iq = new JSJaCIQ(); var iq = new JSJaCIQ();
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_OPTIONS})); var storage = query.appendChild(iq.buildNode('storage', {'xmlns': NS_OPTIONS}));
// Value array // Value array
var tags = ['sounds', 'geolocation', '', '', 'roster-showall']; var tags = ['sounds', 'geolocation', '', '', 'roster-showall'];
// Build the XML with the array // Build the XML with the array
for(var i in array) { for(var i in array) {
var value = array[i]; var value = array[i];
var tag = tags[i]; var tag = tags[i];
if((i != 2) && (i != 3) && tag && value) { if((i != 2) && (i != 3) && tag && value) {
storage.appendChild(iq.buildNode('option', {'type': tag, 'xmlns': NS_OPTIONS}, value)); storage.appendChild(iq.buildNode('option', {'type': tag, 'xmlns': NS_OPTIONS}, value));
DataStore.setDB(Connection.desktop_hash, 'options', tag, value); DataStore.setDB(Connection.desktop_hash, 'options', tag, value);
} }
} }
con.send(iq); con.send(iq);
// If geolocation is enabled // If geolocation is enabled
if(array[1] == '1') { if(array[1] == '1') {
PEP.geolocate(); PEP.geolocate();
@ -276,24 +277,27 @@ var Welcome = (function () {
try { try {
// Get the new options // Get the new options
var array = []; var array = [];
$('#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()) {
// If archiving is enabled // If archiving is enabled
@ -301,19 +305,19 @@ var Welcome = (function () {
MAM.setConfig('roster'); MAM.setConfig('roster');
} }
} }
// Send the new options // Send the new options
self.send(array); self.send(array);
// Close the welcome tool // Close the welcome tool
self.close(); self.close();
// Open the profile editor // Open the profile editor
vCard.open(); vCard.open();
// Unavoidable popup // Unavoidable popup
$('#vcard').addClass('unavoidable'); $('#vcard').addClass('unavoidable');
self.is_done = true; self.is_done = true;
} catch(e) { } catch(e) {
Console.error('Welcome.save', e); Console.error('Welcome.save', e);
@ -335,10 +339,11 @@ var Welcome = (function () {
// Check the next step to go to // Check the next step to go to
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);
} catch(e) { } catch(e) {
@ -360,27 +365,37 @@ 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;
}); });
} catch(e) { } catch(e) {

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