Merge pull request #11 from mbugeia/master
Update to Jappix 1.1.2 and some improvement
8
README.markdown
Normal file
|
@ -0,0 +1,8 @@
|
|||
Jappix for Yunohost
|
||||
============
|
||||
|
||||
[Yunohost project](https://yunohost.org/)
|
||||
|
||||
Official website: <https://jappix.org/>
|
||||
|
||||
Jappix v1.1.2
|
|
@ -1,12 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<jappix xmlns="jappix:conf:main">
|
||||
<name>YunoJappix</name>
|
||||
<name>CHANGENAME</name>
|
||||
<desc>a free social network</desc>
|
||||
<owner_name></owner_name>
|
||||
<owner_website></owner_website>
|
||||
<legal></legal>
|
||||
<language>CHANGELANG</language>
|
||||
<resource>YunoJappix</resource>
|
||||
<resource>CHANGENAME</resource>
|
||||
<lock>on</lock>
|
||||
<anonymous>off</anonymous>
|
||||
<http_auth>on</http_auth>
|
||||
|
@ -18,6 +18,7 @@
|
|||
<https_storage>off</https_storage>
|
||||
<https_force>off</https_force>
|
||||
<compression>off</compression>
|
||||
<caching>on</caching>
|
||||
<analytics_track>off</analytics_track>
|
||||
<analytics_url></analytics_url>
|
||||
<analytics_id></analytics_id>
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
"en": "A free social network",
|
||||
"fr": "Un réseau social libre"
|
||||
},
|
||||
"licence": "AGPL v3",
|
||||
"developer": {
|
||||
"name": "titoko",
|
||||
"email": "titoko@titoko.fr",
|
||||
|
@ -16,27 +17,38 @@
|
|||
{
|
||||
"name": "domain",
|
||||
"ask": {
|
||||
"en": "Choose a domain for Jappix"
|
||||
"en": "Choose a domain for Jappix",
|
||||
"fr": "Choisissez un domaine pour Jappix"
|
||||
},
|
||||
"example": "domain.org"
|
||||
},
|
||||
{
|
||||
"name": "path",
|
||||
"ask": {
|
||||
"en": "Choose a path for Jappix"
|
||||
"en": "Choose a path for Jappix",
|
||||
"fr": "Choisissez un chemin pour Jappix"
|
||||
},
|
||||
"example": "/jappix",
|
||||
"default": "/jappix"
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"ask": {
|
||||
"en": "Choose a name for Jappix",
|
||||
"fr": "Choisissez un nom pour Jappix"
|
||||
},
|
||||
"example": "YunoJappix",
|
||||
"default": "YunoJappix"
|
||||
},
|
||||
{
|
||||
"name": "language",
|
||||
"ask": {
|
||||
"en": "Choose the language of the Jappix",
|
||||
"fr": "Choissisez la langue du Jappix"
|
||||
},
|
||||
"example": "en",
|
||||
"default": "en"
|
||||
}
|
||||
"en": "Choose the language of the Jappix",
|
||||
"fr": "Choissisez la langue du Jappix"
|
||||
},
|
||||
"choices" : ["en", "fr", "es"],
|
||||
"default" : "en"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
15
scripts/backup
Normal 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
|
|
@ -3,7 +3,8 @@
|
|||
# Retrieve arguments
|
||||
domain=$1
|
||||
path=$2
|
||||
language=$3
|
||||
name=$3
|
||||
language=$4
|
||||
|
||||
# Check domain/path availability
|
||||
sudo yunohost app checkurl $domain$path -a jappix
|
||||
|
@ -15,10 +16,10 @@ fi
|
|||
path=${path%/}
|
||||
|
||||
# Copy files to the right place
|
||||
final_path=/var/www/jappix
|
||||
sudo mkdir -p $final_path
|
||||
sudo cp -r ../source/* $final_path
|
||||
sudo cp ../conf/*.xml $final_path/store/conf/
|
||||
final_path=/var/www/jappix
|
||||
sudo mkdir -p $final_path
|
||||
sudo cp -r ../source/* $final_path
|
||||
sudo cp ../conf/*.xml $final_path/store/conf/
|
||||
|
||||
# Set permissions to jappix directory
|
||||
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
|
||||
|
||||
if [ -z "$path" ]; then
|
||||
path="/"
|
||||
path="/"
|
||||
fi
|
||||
|
||||
sudo ls $final_path/i18n/$language > /dev/null 2>&1
|
||||
|
@ -36,6 +37,7 @@ then
|
|||
language="en"
|
||||
fi
|
||||
|
||||
sudo yunohost app setting jappix name -v $name
|
||||
sudo yunohost app setting jappix language -v $language
|
||||
|
||||
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@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@CHANGENAME@$name@g" $final_path/store/conf/main.xml
|
||||
sudo sed -i "s@DOMAINTOCHANGE@$domain@g" $final_path/store/conf/hosts.xml
|
||||
|
||||
# Reload Nginx and regenerate SSOwat conf
|
||||
|
|
|
@ -3,3 +3,6 @@ domain=$(sudo yunohost app setting jappix domain)
|
|||
|
||||
sudo rm -rf /var/www/jappix
|
||||
sudo rm -f /etc/nginx/conf.d/$domain.d/jappix.conf
|
||||
|
||||
sudo service nginx reload
|
||||
sudo yunohost app ssowatconf
|
||||
|
|
16
scripts/restore
Normal 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
|
|
@ -3,8 +3,13 @@
|
|||
# Retrieve arguments
|
||||
domain=$(sudo yunohost app setting jappix domain)
|
||||
path=$(sudo yunohost app setting jappix path)
|
||||
name=$(sudo yunohost app setting jappix name)
|
||||
language=$(sudo yunohost app setting jappix language)
|
||||
|
||||
if [[ "$name" = "" ]];
|
||||
then
|
||||
name="YunoJappix"
|
||||
fi
|
||||
if [[ "$language" = "" ]];
|
||||
then
|
||||
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@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@CHANGENAME@$name@g" $final_path/store/conf/main.xml
|
||||
sudo sed -i "s@DOMAINTOCHANGE@$domain@g" $final_path/store/conf/hosts.xml
|
||||
|
||||
# Reload Nginx and regenerate SSOwat conf
|
||||
|
|
|
@ -4,6 +4,71 @@ Jappix Changelog
|
|||
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)
|
||||
------------------------
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
# XMPP Extensions
|
||||
# XMPP Extensions (Standardized)
|
||||
|
||||
* XEP-0045: Multi-User Chat *v1.25*
|
||||
* XEP-0004: Data Forms *v2.9*
|
||||
* XEP-0012: Last Activity *v2.0*
|
||||
* XEP-0016: Privacy Lists *v1.6*
|
||||
* XEP-0030: Service Discovery *v2.4*
|
||||
* XEP-0045: Multi-User Chat *v1.25*
|
||||
* XEP-0049: Private XML Storage *v1.2*
|
||||
* XEP-0050: Ad-Hoc Commands *v1.2*
|
||||
* XEP-0054: vcard-temp *v1.2*
|
||||
* XEP-0055: Jabber Search *v1.3*
|
||||
* XEP-0060: Publish-Subscribe *v1.13*
|
||||
* XEP-0124: Bidirectional-streams Over Synchronous HTTP (BOSH) *v1.10*
|
||||
* XEP-0115: Entity Capabilities *v1.5*
|
||||
* XEP-0066: Out of Band Data *v1.5*
|
||||
* XEP-0071: XHTML-IM *v1.5*
|
||||
* XEP-0072: SOAP Over XMPP *v1.0*
|
||||
* XEP-0077: In-Band Registration *v2.4*
|
||||
* XEP-0080: User Location *v1.7*
|
||||
* XEP-0084: User Avatar *v1.1*
|
||||
* XEP-0085: Chat State Notifications *v2.1*
|
||||
* XEP-0092: Software Version *v1.1*
|
||||
* XEP-0107: User Mood *v1.2*
|
||||
* XEP-0108: User Activity *v1.3*
|
||||
* XEP-0115: Entity Capabilities *v1.5*
|
||||
* XEP-0118: User Tune *v1.2*
|
||||
* XEP-0080: User Location *v1.7*
|
||||
* XEP-0172: User Nickname *v1.1*
|
||||
* XEP-0084: User Avatar *v1.1*
|
||||
* XEP-0277: Microblogging over XMPP *v0.6*
|
||||
* XEP-xxxx: Notification Inbox *v0.1*
|
||||
* Alternate URL: http://xmpp.org/extensions/inbox/notification-inbox.html
|
||||
* XEP-0203: Delayed Delivery *v2.0*
|
||||
* XEP-0124: Bidirectional-streams Over Synchronous HTTP (BOSH) *v1.10*
|
||||
* XEP-0144: Roster Item Exchange *v1.0*
|
||||
* XEP-0072: SOAP Over XMPP *v1.0*
|
||||
* XEP-0085: Chat State Notifications *v2.1*
|
||||
* XEP-0071: XHTML-IM *v1.5*
|
||||
* XEP-0313: Message Archive Management *v0.3*
|
||||
* Alternate URL: https://demo.frenchtouch.pro/valerian.saliou/xmpp/extensions/xep-0313.html
|
||||
* XEP-0012: Last Activity *v2.0*
|
||||
* XEP-0049: Private XML Storage *v1.2*
|
||||
* XEP-0077: In-Band Registration *v2.4*
|
||||
* XEP-0055: Jabber Search *v1.3*
|
||||
* XEP-0050: Ad-Hoc Commands *v1.2*
|
||||
* XEP-0092: Software Version *v1.1*
|
||||
* XEP-0004: Data Forms *v2.9*
|
||||
* XEP-0054: vcard-temp *v1.2*
|
||||
* XEP-0202: Entity Time *v2.0*
|
||||
* XEP-0199: XMPP Ping *v2.0*
|
||||
* XEP-0184: Message Delivery Receipts *v1.2*
|
||||
* XEP-0016: Privacy Lists *v1.6*
|
||||
* XEP-0066: Out of Band Data *v1.5*
|
||||
* XEP-0280: Message Carbons *v0.9*
|
||||
* XEP-0292: vCard4 Over XMPP *v0.10*
|
||||
* XEP-0152: Reachability Addresses *v1.0*
|
||||
* XEP-0166: Jingle *v1.1*
|
||||
* XEP-0167: Jingle RTP Sessions *v1.1*
|
||||
* XEP-0172: User Nickname *v1.1*
|
||||
* XEP-0176: Jingle ICE-UDP Transport Method *v1.0*
|
||||
* XEP-0177: Jingle Raw UDP Transport Method *v1.1*
|
||||
* XEP-0184: Message Delivery Receipts *v1.2*
|
||||
* XEP-0199: XMPP Ping *v2.0*
|
||||
* XEP-0202: Entity Time *v2.0*
|
||||
* XEP-0203: Delayed Delivery *v2.0*
|
||||
* XEP-0224: Attention *v1.0*
|
||||
* XEP-0215: External Service Discovery *v0.5*
|
||||
* XEP-0249: Direct MUC Invitations *v1.2*
|
||||
* XEP-0262: Use of ZRTP in Jingle RTP Sessions *v1.0*
|
||||
* XEP-0266: Codecs for Jingle Audio *v1.0*
|
||||
* XEP-0269: Jingle Early Media *v0.1*
|
||||
* XEP-0277: Microblogging over XMPP *v0.6*
|
||||
* XEP-0278: Jingle Relay Nodes *v0.2*
|
||||
* XEP-0280: Message Carbons *v0.9*
|
||||
* XEP-0292: vCard4 Over XMPP *v0.10*
|
||||
* XEP-0293: Jingle RTP Feedback Negotiation *v0.1*
|
||||
* XEP-0294: Jingle RTP Header Extensions Negotiation *v0.1*
|
||||
* XEP-0299: Codecs for Jingle Video *v0.1*
|
||||
* XEP-0308: Last Message Correction *v1.0*
|
||||
* XEP-0319: Last User Interaction in Presence *v0.2*
|
||||
* XEP-0320: Use of DTLS-SRTP in Jingle Sessions *v0.2*
|
||||
* XEP-0333: Chat Markers *v0.2*
|
||||
* XEP-0334: Message Processing Hints *v0.1*
|
||||
* XEP-0338: Jingle Grouping Framework *v0.1*
|
||||
* XEP-0339: Source-Specific Media Attributes in Jingle *v0.1*
|
||||
* 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
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
||||
[](https://ci.frenchtouch.pro/projects/7?ref=master)
|
||||
[](https://ci.hakuma.holdings/projects/7?ref=master)
|
||||
|
||||
|
||||
License
|
||||
|
@ -32,9 +32,9 @@ Start translating on https://www.transifex.com/projects/p/jappix/ (new translato
|
|||
Links
|
||||
-----
|
||||
|
||||
* Jappix project website: http://jappix.org/
|
||||
* Jappix project website: https://jappix.org/
|
||||
* Jappix project dev panel: https://github.com/jappix/jappix
|
||||
* Jappix nodes list: http://jappix.net/
|
||||
* Jappix nodes list: https://jappix.net/
|
||||
* Jappix main service: https://jappix.com/
|
||||
* Jappix commercial support: https://jappix.pro/
|
||||
|
||||
|
@ -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:
|
||||
|
||||
* 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
|
||||
|
|
|
@ -1 +1 @@
|
|||
One [1.0.3]
|
||||
Primo [1.1.2]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<jappix xmlns="jappix:file:get">
|
||||
<css>fonts.css~main.css~images.css~board.css~home.css~others.css~tools.css~roster.css~myinfos.css~pageengine.css~channel.css~pageswitch.css~smileys.css~popup.css~vcard.css~options.css~favorites.css~discovery.css~directory.css~adhoc.css~privacy.css~inbox.css~mucadmin.css~integratebox.css~userinfos.css~search.css~welcome.css~me.css~rosterx.css~jingle.css</css>
|
||||
<js>origin.js~jxhr.js~datejs.js~jquery.js~jquery.ui.js~jquery.json.js~jquery.form.js~jquery.timers.js~jquery.placeholder.js~jquery.textrange.js~base64.js~jsjac.js~jsjac.jingle.js~system.js~constants.js~datastore.js~browser-detect.js~home.js~talk.js~popup.js~audio.js~board.js~bubble.js~chat.js~groupchat.js~smileys.js~oob.js~avatar.js~mucadmin.js~connection.js~dataform.js~discovery.js~directory.js~adhoc.js~privacy.js~errors.js~name.js~favorites.js~features.js~interface.js~xmpplinks.js~iq.js~message.js~chatstate.js~receipts.js~tooltip.js~filter.js~links.js~inbox.js~microblog.js~music.js~notification.js~httpreply.js~options.js~integratebox.js~pubsub.js~pep.js~presence.js~roster.js~jingle.js~storage.js~console.js~common.js~utilities.js~date.js~caps.js~vcard.js~userinfos.js~search.js~autocompletion.js~welcome.js~me.js~rosterx.js~mam.js~carbons.js</js>
|
||||
<css>fonts.css~main.css~images.css~board.css~home.css~others.css~tools.css~roster.css~myinfos.css~pageengine.css~channel.css~pageswitch.css~smileys.css~popup.css~vcard.css~options.css~favorites.css~discovery.css~directory.css~adhoc.css~privacy.css~inbox.css~mucadmin.css~integratebox.css~userinfos.css~search.css~welcome.css~me.css~rosterx.css~call.css~jingle.css~muji.css</css>
|
||||
<js>origin.js~jxhr.js~datejs.js~jquery.js~jquery.ui.js~jquery.json.js~jquery.form.js~jquery.timers.js~jquery.placeholder.js~jquery.textrange.js~jquery.scrollto.js~base64.js~jsjac.js~jsjac.jingle.js~system.js~constants.js~datastore.js~browser-detect.js~home.js~talk.js~popup.js~audio.js~board.js~bubble.js~chat.js~groupchat.js~smileys.js~oob.js~avatar.js~mucadmin.js~connection.js~dataform.js~discovery.js~directory.js~adhoc.js~privacy.js~errors.js~name.js~favorites.js~features.js~interface.js~xmpplinks.js~iq.js~message.js~chatstate.js~receipts.js~tooltip.js~filter.js~links.js~inbox.js~microblog.js~music.js~notification.js~httpreply.js~options.js~integratebox.js~pubsub.js~pep.js~presence.js~roster.js~call.js~jingle.js~muji.js~storage.js~console.js~common.js~utilities.js~date.js~caps.js~vcard.js~userinfos.js~search.js~autocompletion.js~welcome.js~me.js~rosterx.js~mam.js~carbons.js~correction.js~markers.js~attention.js</js>
|
||||
</jappix>
|
||||
|
|
BIN
source/app/images/placeholders/jingle_audio_local.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
source/app/images/placeholders/jingle_audio_remote.png
Normal file
After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 1.1 KiB |
BIN
source/app/images/placeholders/jingle_video_remote.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
source/app/images/sprites/call.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 2 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.2 KiB |
|
@ -29,24 +29,24 @@ var AdHoc = (function () {
|
|||
|
||||
try {
|
||||
// Popup HTML content
|
||||
var html =
|
||||
'<div class="top">' + Common._e("Commands") + '</div>' +
|
||||
|
||||
'<div class="content">' +
|
||||
'<div class="adhoc-head"></div>' +
|
||||
|
||||
'<div class="results adhoc-results"></div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="bottom">' +
|
||||
'<div class="wait wait-medium"></div>' +
|
||||
|
||||
'<a href="#" class="finish">' + Common._e("Close") + '</a>' +
|
||||
var html =
|
||||
'<div class="top">' + Common._e("Commands") + '</div>' +
|
||||
|
||||
'<div class="content">' +
|
||||
'<div class="adhoc-head"></div>' +
|
||||
|
||||
'<div class="results adhoc-results"></div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="bottom">' +
|
||||
'<div class="wait wait-medium"></div>' +
|
||||
|
||||
'<a href="#" class="finish">' + Common._e("Close") + '</a>' +
|
||||
'</div>';
|
||||
|
||||
|
||||
// Create the popup
|
||||
Popup.create('adhoc', html);
|
||||
|
||||
|
||||
// Associate the events
|
||||
self.launch();
|
||||
} catch(e) {
|
||||
|
@ -88,16 +88,16 @@ var AdHoc = (function () {
|
|||
try {
|
||||
// Open the popup
|
||||
self.open();
|
||||
|
||||
|
||||
// Add a XID marker
|
||||
$('#adhoc .adhoc-head').html('<b>' + Name.getBuddy(xid).htmlEnc() + '</b> (' + xid.htmlEnc() + ')');
|
||||
|
||||
|
||||
// Get the highest entity resource
|
||||
var highest = Presence.highestPriority(xid);
|
||||
|
||||
|
||||
if(highest)
|
||||
xid = highest;
|
||||
|
||||
|
||||
// Start a new adhoc command
|
||||
DataForm.go(xid, 'command', '', '', 'adhoc');
|
||||
} catch(e) {
|
||||
|
@ -120,10 +120,10 @@ var AdHoc = (function () {
|
|||
try {
|
||||
// Open the popup
|
||||
self.open();
|
||||
|
||||
|
||||
// Add a XID marker
|
||||
$('#adhoc .adhoc-head').html('<b>' + server.htmlEnc() + '</b>');
|
||||
|
||||
|
||||
// Start a new adhoc command
|
||||
DataForm.go(server, 'command', '', '', 'adhoc');
|
||||
} catch(e) {
|
||||
|
@ -142,9 +142,7 @@ var AdHoc = (function () {
|
|||
|
||||
try {
|
||||
// Click event
|
||||
$('#adhoc .bottom .finish').click(
|
||||
self.close()
|
||||
);
|
||||
$('#adhoc .bottom .finish').click(self.close);
|
||||
} catch(e) {
|
||||
Console.error('AdHoc.launch', e);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,28 @@ var Anonymous = (function () {
|
|||
var self = {};
|
||||
|
||||
|
||||
/**
|
||||
* Registers connection handlers
|
||||
* @private
|
||||
* @param {object} con
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._registerHandlers = function(con) {
|
||||
|
||||
try {
|
||||
con.registerHandler('message', Message.handle);
|
||||
con.registerHandler('presence', Presence.handle);
|
||||
con.registerHandler('iq', IQ.handle);
|
||||
con.registerHandler('onconnect', self.connected);
|
||||
con.registerHandler('onerror', Errors.handle);
|
||||
con.registerHandler('ondisconnect', self.disconnected);
|
||||
} catch(e) {
|
||||
Console.error('Anonymous._registerHandlers', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Connected to an anonymous session
|
||||
* @public
|
||||
|
@ -29,40 +51,40 @@ var Anonymous = (function () {
|
|||
|
||||
try {
|
||||
Console.info('Jappix (anonymous) is now connected.');
|
||||
|
||||
|
||||
// Connected marker
|
||||
Connection.connected = true;
|
||||
Connection.current_session = true;
|
||||
Connection.reconnect_try = 0;
|
||||
Connection.reconnect_timer = 0;
|
||||
|
||||
|
||||
// Not resumed?
|
||||
if(!Connection.resume) {
|
||||
// Create the app
|
||||
Talk.create();
|
||||
|
||||
|
||||
// Send our first presence
|
||||
Presence.sendFirst('');
|
||||
|
||||
|
||||
// Set last activity stamp
|
||||
DateUtils.last_activity = DateUtils.getTimeStamp();
|
||||
|
||||
|
||||
// Create the new groupchat
|
||||
Chat.checkCreate(Common.generateXID(ANONYMOUS_ROOM, 'groupchat'), 'groupchat');
|
||||
|
||||
|
||||
// Remove some nasty elements for the anonymous mode
|
||||
$('.tools-mucadmin, .tools-add').remove();
|
||||
}
|
||||
|
||||
|
||||
// Resumed
|
||||
else {
|
||||
// Send again our presence
|
||||
Presence.sendActions();
|
||||
|
||||
|
||||
// Change the title
|
||||
Interface.updateTitle();
|
||||
}
|
||||
|
||||
|
||||
// Remove the waiting icon
|
||||
Interface.removeGeneralWait();
|
||||
} catch(e) {
|
||||
|
@ -107,21 +129,16 @@ var Anonymous = (function () {
|
|||
|
||||
// Check BOSH origin
|
||||
BOSH_SAME_ORIGIN = Origin.isSame(httpbase);
|
||||
|
||||
|
||||
// We create the new http-binding connection
|
||||
con = new JSJaCHttpBindingConnection({
|
||||
httpbase: httpbase
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// And we handle everything that happen
|
||||
con.registerHandler('message', Message.handle);
|
||||
con.registerHandler('presence', Presence.handle);
|
||||
con.registerHandler('iq', IQ.handle);
|
||||
con.registerHandler('onconnect', self.connected);
|
||||
con.registerHandler('onerror', Errors.handle);
|
||||
con.registerHandler('ondisconnect', self.disconnected);
|
||||
|
||||
self._registerHandlers(con);
|
||||
|
||||
// We set the anonymous connection parameters
|
||||
oArgs = {};
|
||||
oArgs.domain = server;
|
||||
|
@ -129,10 +146,10 @@ var Anonymous = (function () {
|
|||
oArgs.resource = JAPPIX_RESOURCE + ' Anonymous (' + (new Date()).getTime() + ')';
|
||||
oArgs.secure = true;
|
||||
oArgs.xmllang = XML_LANG;
|
||||
|
||||
|
||||
// We connect !
|
||||
con.connect(oArgs);
|
||||
|
||||
|
||||
// Change the page title
|
||||
Interface.title('wait');
|
||||
} catch(e) {
|
||||
|
@ -140,7 +157,7 @@ var Anonymous = (function () {
|
|||
|
||||
// Reset Jappix
|
||||
self.disconnected();
|
||||
|
||||
|
||||
// Open an unknown error
|
||||
Board.openThisError(2);
|
||||
} finally {
|
||||
|
@ -160,16 +177,19 @@ var Anonymous = (function () {
|
|||
try {
|
||||
$(document).ready(function() {
|
||||
Console.info('Anonymous mode detected, connecting...');
|
||||
|
||||
|
||||
// We add the login wait div
|
||||
Interface.showGeneralWait();
|
||||
|
||||
|
||||
// Get the vars
|
||||
if(XMPPLinks.links_var.r)
|
||||
if(XMPPLinks.links_var.r) {
|
||||
ANONYMOUS_ROOM = XMPPLinks.links_var.r;
|
||||
if(XMPPLinks.links_var.n)
|
||||
}
|
||||
|
||||
if(XMPPLinks.links_var.n) {
|
||||
ANONYMOUS_NICK = XMPPLinks.links_var.n;
|
||||
|
||||
}
|
||||
|
||||
// Fire the login action
|
||||
self.login(HOST_ANONYMOUS);
|
||||
});
|
||||
|
|
216
source/app/javascripts/attention.js
Normal file
|
@ -0,0 +1,216 @@
|
|||
/*
|
||||
|
||||
Jappix - An open social platform
|
||||
Implementation of XEP-0224: Attention
|
||||
|
||||
-------------------------------------------------
|
||||
|
||||
License: AGPL
|
||||
Author: Valérian Saliou
|
||||
|
||||
*/
|
||||
|
||||
// Bundle
|
||||
var Attention = (function () {
|
||||
|
||||
/**
|
||||
* Alias of this
|
||||
* @private
|
||||
*/
|
||||
var self = {};
|
||||
|
||||
|
||||
/**
|
||||
* Displays attention message
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @param {string} body
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._display = function(xid, body, mode) {
|
||||
|
||||
try {
|
||||
var name = Name.getBuddy(xid).htmlEnc();
|
||||
var hash = hex_md5(xid);
|
||||
|
||||
// Compute some variables
|
||||
var message = Common._e(Common.printf("You requested %s's attention to the conversation", name));
|
||||
|
||||
if(mode == 'him') {
|
||||
message = Common._e(Common.printf("%s requested your attention to the conversation", name));
|
||||
}
|
||||
|
||||
if(body) {
|
||||
message += ' (' + body + ')';
|
||||
}
|
||||
|
||||
// Display notification
|
||||
Message.display(
|
||||
'chat',
|
||||
xid,
|
||||
hash,
|
||||
name,
|
||||
message,
|
||||
DateUtils.getCompleteTime(),
|
||||
DateUtils.getTimeStamp(),
|
||||
'system-message',
|
||||
true,
|
||||
undefined,
|
||||
mode
|
||||
);
|
||||
|
||||
// Add a marker to displayed message
|
||||
$('#' + hash + ' .content .one-line.system-message:last').addClass('attention-notice');
|
||||
} catch(e) {
|
||||
Console.error('Attention._display', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sends attention stanza
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @param {string} body
|
||||
* @return {object}
|
||||
*/
|
||||
self._stanza = function(xid, body) {
|
||||
|
||||
try {
|
||||
var message = new JSJaCMessage();
|
||||
message.setType('headline');
|
||||
message.setTo(xid);
|
||||
|
||||
if(body) {
|
||||
message.setBody(body);
|
||||
}
|
||||
|
||||
// Attention node
|
||||
message.appendNode('attention', {
|
||||
'xmlns': NS_URN_ATTENTION
|
||||
});
|
||||
|
||||
con.send(message);
|
||||
|
||||
return message;
|
||||
} catch(e) {
|
||||
Console.error('Attention._stanza', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether last attention message exists or not
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @return {boolean}
|
||||
*/
|
||||
self._lastExists = function(xid, mode) {
|
||||
|
||||
var last_exists = false;
|
||||
|
||||
try {
|
||||
var line_sel = $('#' + hex_md5(xid) + ' .content .one-line[data-mode="' + mode + '"]:last');
|
||||
last_exists = line_sel.is('.system-message.attention-notice') ? true : false;
|
||||
} catch(e) {
|
||||
Console.error('Attention._lastExists', e);
|
||||
} finally {
|
||||
return last_exists;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return whether entity supports attention notifications
|
||||
* @public
|
||||
* @param {string} xid
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.hasSupport = function(xid) {
|
||||
|
||||
var has_support = false;
|
||||
|
||||
try {
|
||||
has_support = true ? $('#' + hex_md5(xid)).attr('data-attention') == 'true' : false;
|
||||
} catch(e) {
|
||||
Console.error('Attention.hasSupport', e);
|
||||
} finally {
|
||||
return has_support;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Send an attention message
|
||||
* @public
|
||||
* @param {string} xid
|
||||
* @param {string} body
|
||||
* @return {undefined}
|
||||
*/
|
||||
self.send = function(xid, body) {
|
||||
|
||||
try {
|
||||
var mode = 'me';
|
||||
|
||||
// Don't send attention message twice
|
||||
if(self._lastExists(xid, mode) === false) {
|
||||
// Send message stanza
|
||||
self._stanza(xid, body);
|
||||
|
||||
// Display attention notification
|
||||
self._display(xid, body, mode);
|
||||
} else {
|
||||
Console.debug('Attention.send', 'Not sending attention message to: ' + xid + ' because already sent.');
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Attention.send', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Receive an attention notification
|
||||
* @public
|
||||
* @param {string} xid
|
||||
* @return {undefined}
|
||||
*/
|
||||
self.receive = function(xid, body) {
|
||||
|
||||
try {
|
||||
var mode = 'him';
|
||||
var hash = hex_md5(xid);
|
||||
|
||||
// Don't receive attention message twice
|
||||
if((self._lastExists(xid, mode) === false) && Common.exists('#' + hash)) {
|
||||
// Display attention notification
|
||||
self._display(xid, body, mode);
|
||||
|
||||
// Show a notification
|
||||
Interface.messageNotify(hash, 'personal');
|
||||
Audio.play('catch-attention');
|
||||
|
||||
Board.quick(
|
||||
xid,
|
||||
'chat',
|
||||
Common._e("Attention to conversation requested."),
|
||||
Name.getBuddy(xid)
|
||||
);
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Attention.receive', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return class scope
|
||||
*/
|
||||
return self;
|
||||
|
||||
})();
|
|
@ -29,7 +29,7 @@ var Audio = (function () {
|
|||
* @private
|
||||
* @return {boolean}
|
||||
*/
|
||||
self._is_supported = function() {
|
||||
self._isSupported = function() {
|
||||
|
||||
is_supported = true;
|
||||
|
||||
|
@ -38,7 +38,7 @@ var Audio = (function () {
|
|||
is_supported = false;
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Audio._is_supported', e);
|
||||
Console.error('Audio._isSupported', e);
|
||||
} finally {
|
||||
return is_supported;
|
||||
}
|
||||
|
@ -46,6 +46,57 @@ var Audio = (function () {
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* Append audio DOM code
|
||||
* @private
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._appendDOM = function() {
|
||||
|
||||
try {
|
||||
// If the audio elements aren't yet in the DOM
|
||||
if(!Common.exists('#audio')) {
|
||||
$('body').append(
|
||||
'<div id="audio">' +
|
||||
'<audio id="new-chat" preload="auto" data-duration="2">' +
|
||||
'<source src="' + './sounds/new-chat.mp3' + '" />' +
|
||||
'<source src="' + './sounds/new-chat.oga' + '" />' +
|
||||
'</audio>' +
|
||||
|
||||
'<audio id="receive-message" preload="auto" data-duration="2">' +
|
||||
'<source src="' + './sounds/receive-message.mp3' + '" />' +
|
||||
'<source src="' + './sounds/receive-message.oga' + '" />' +
|
||||
'</audio>' +
|
||||
|
||||
'<audio id="notification" preload="auto" data-duration="2">' +
|
||||
'<source src="' + './sounds/notification.mp3' + '" />' +
|
||||
'<source src="' + './sounds/notification.oga' + '" />' +
|
||||
'</audio>' +
|
||||
|
||||
'<audio id="catch-attention" preload="auto" data-duration="3">' +
|
||||
'<source src="' + './sounds/catch-attention.mp3' + '" />' +
|
||||
'<source src="' + './sounds/catch-attention.oga' + '" />' +
|
||||
'</audio>' +
|
||||
|
||||
'<audio id="incoming-call" preload="auto" data-duration="7">' +
|
||||
'<source src="' + './sounds/incoming-call.mp3' + '" />' +
|
||||
'<source src="' + './sounds/incoming-call.oga' + '" />' +
|
||||
'</audio>' +
|
||||
|
||||
'<audio id="outgoing-call" preload="auto" data-duration="30">' +
|
||||
'<source src="' + './sounds/outgoing-call.mp3' + '" />' +
|
||||
'<source src="' + './sounds/outgoing-call.oga' + '" />' +
|
||||
'</audio>' +
|
||||
'</div>'
|
||||
);
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Audio._appendDOM', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Plays the given sound ID
|
||||
* @public
|
||||
|
@ -58,44 +109,14 @@ var Audio = (function () {
|
|||
repeat = (typeof repeat === 'boolean') ? repeat : false;
|
||||
|
||||
// Not supported?
|
||||
if(!self._is_supported()) {
|
||||
if(!self._isSupported()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// If the sounds are enabled
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'sounds') === '1') {
|
||||
// If the audio elements aren't yet in the DOM
|
||||
if(!Common.exists('#audio')) {
|
||||
$('body').append(
|
||||
'<div id="audio">' +
|
||||
'<audio id="new-chat" preload="auto" data-duration="2">' +
|
||||
'<source src="' + './sounds/new-chat.mp3' + '" />' +
|
||||
'<source src="' + './sounds/new-chat.oga' + '" />' +
|
||||
'</audio>' +
|
||||
|
||||
'<audio id="receive-message" preload="auto" data-duration="2">' +
|
||||
'<source src="' + './sounds/receive-message.mp3' + '" />' +
|
||||
'<source src="' + './sounds/receive-message.oga' + '" />' +
|
||||
'</audio>' +
|
||||
|
||||
'<audio id="notification" preload="auto" data-duration="2">' +
|
||||
'<source src="' + './sounds/notification.mp3' + '" />' +
|
||||
'<source src="' + './sounds/notification.oga' + '" />' +
|
||||
'</audio>' +
|
||||
|
||||
'<audio id="incoming-call" preload="auto" data-duration="7">' +
|
||||
'<source src="' + './sounds/incoming-call.mp3' + '" />' +
|
||||
'<source src="' + './sounds/incoming-call.oga' + '" />' +
|
||||
'</audio>' +
|
||||
|
||||
'<audio id="outgoing-call" preload="auto" data-duration="30">' +
|
||||
'<source src="' + './sounds/outgoing-call.mp3' + '" />' +
|
||||
'<source src="' + './sounds/outgoing-call.oga' + '" />' +
|
||||
'</audio>' +
|
||||
'</div>'
|
||||
);
|
||||
}
|
||||
|
||||
self._appendDOM();
|
||||
|
||||
// We play the target sound
|
||||
var audio_raw_sel = $('#audio audio').filter('#' + name);
|
||||
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);
|
||||
|
||||
self._timeout_stop = false;
|
||||
|
||||
|
||||
audio_raw_sel.oneTime((duration + 's'), function() {
|
||||
if(!self._timeout_stop) {
|
||||
self.play(name, repeat);
|
||||
|
@ -146,10 +167,10 @@ var Audio = (function () {
|
|||
|
||||
try {
|
||||
// Not supported?
|
||||
if(!self._is_supported()) {
|
||||
if(!self._isSupported()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
self._timeout_stop = true;
|
||||
|
||||
// Check the audio container exists before doing anything...
|
||||
|
@ -159,7 +180,7 @@ var Audio = (function () {
|
|||
|
||||
if(audio_parent_sel.size()) {
|
||||
audio_raw_sel.stopTime();
|
||||
|
||||
|
||||
if(audio_sel) {
|
||||
if(!audio_sel.paused) {
|
||||
audio_sel.pause();
|
||||
|
|
|
@ -32,14 +32,17 @@ var Autocompletion = (function () {
|
|||
|
||||
try {
|
||||
// Put the two strings into lower case
|
||||
var sA = a[0].toLowerCase();
|
||||
var sB = b[0].toLowerCase();
|
||||
|
||||
var sort_a = a[0].toLowerCase();
|
||||
var sort_b = b[0].toLowerCase();
|
||||
|
||||
// Process the sort
|
||||
if(sA > sB)
|
||||
if(sort_a > sort_b) {
|
||||
return 1;
|
||||
if(sA < sB)
|
||||
}
|
||||
|
||||
if(sort_a < sort_b) {
|
||||
return -1;
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Autocompletion.caseInsensitiveSort', e);
|
||||
}
|
||||
|
@ -49,40 +52,51 @@ var Autocompletion = (function () {
|
|||
|
||||
/**
|
||||
* Split a query into its subqueries ready to be used in autocompletion
|
||||
* The function return an array containing two others : the first with subqueries
|
||||
* and the second with remaining parts
|
||||
* For example, if query is "A B C", the subqueries are ["C", "B C", "A B C"] and
|
||||
* the remaining parts are ["A B ", "A ", ""]
|
||||
* @public
|
||||
* @param {string} query
|
||||
* @return {Array}
|
||||
* @return {object}
|
||||
*/
|
||||
self.getSubQueries = function(query) {
|
||||
|
||||
var subqueries = [];
|
||||
var remnants = [];
|
||||
var result = [];
|
||||
|
||||
var queryLastCharPos = query.length - 1;
|
||||
var spaceCounter = 0;
|
||||
for (var i=queryLastCharPos; i>=0; i--) {
|
||||
// Search from the end of the query
|
||||
var iChar = query.charAt(i);
|
||||
if (spaceCounter === 0 && iChar.search(/\s/) === 0) {
|
||||
// the first "local" space was found
|
||||
// add the subquery and its remnant to results
|
||||
subqueries.push(query.slice(i+1));
|
||||
remnants.push(query.slice(0, i+1));
|
||||
spaceCounter++;
|
||||
} else {
|
||||
spaceCounter = 0;
|
||||
try {
|
||||
var subqueries = [];
|
||||
var remnants = [];
|
||||
|
||||
var query_last_char_pos = query.length - 1;
|
||||
var space_counter = 0;
|
||||
var cur_char;
|
||||
|
||||
for(var i = query_last_char_pos; i >= 0; i--) {
|
||||
// Search from the end of the query
|
||||
cur_char = query.charAt(i);
|
||||
|
||||
if(space_counter === 0 && cur_char.search(/\s/) === 0) {
|
||||
// The first "local" space was found
|
||||
// Add the subquery and its remnant to results
|
||||
subqueries.push(query.slice(i+1));
|
||||
remnants.push(query.slice(0, i+1));
|
||||
|
||||
space_counter++;
|
||||
} else {
|
||||
space_counter = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (spaceCounter === 0) {
|
||||
// If the first char of the query is not a space, add the full query to results
|
||||
subqueries.push(query);
|
||||
remnants.push("");
|
||||
|
||||
if(space_counter === 0) {
|
||||
// If the first char of the query is not a space, add the full query to results
|
||||
subqueries.push(query);
|
||||
remnants.push('');
|
||||
}
|
||||
|
||||
result = [subqueries, remnants];
|
||||
} catch(e) {
|
||||
Console.error('Autocompletion.getSubQueries', e);
|
||||
} finally {
|
||||
return result;
|
||||
}
|
||||
|
||||
return [subqueries, remnants];
|
||||
};
|
||||
|
||||
|
||||
|
@ -102,25 +116,37 @@ var Autocompletion = (function () {
|
|||
try {
|
||||
// Replace forbidden characters in regex
|
||||
query = Common.escapeRegex(query);
|
||||
|
||||
// Build an array of regex to use
|
||||
var queryRegExp = [];
|
||||
for (i = 0; i<query.length; i++) {
|
||||
if (query[i] !== null) {
|
||||
queryRegExp.push(new RegExp('(^)' + query[i], 'gi'));
|
||||
var query_reg_exp = [];
|
||||
|
||||
for(i = 0; i < query.length; i++) {
|
||||
if(query[i] !== null) {
|
||||
query_reg_exp.push(
|
||||
new RegExp('(^)' + query[i], 'gi')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Search in the roster
|
||||
var nick, regex;
|
||||
|
||||
$('#' + id + ' .user').each(function() {
|
||||
var nick = $(this).find('.name').text();
|
||||
for (i = 0; i<queryRegExp.length; i++) {
|
||||
var regex = queryRegExp[i];
|
||||
nick = $(this).find('.name').text();
|
||||
|
||||
for(i = 0; i < query_reg_exp.length; i++) {
|
||||
regex = query_reg_exp[i];
|
||||
|
||||
if(nick.match(regex)) {
|
||||
results.push([nick, i]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Sort the array
|
||||
results = results.sort(self.caseInsensitiveSort);
|
||||
results = results.sort(
|
||||
self.caseInsensitiveSort
|
||||
);
|
||||
} catch(e) {
|
||||
Console.error('Autocompletion.process', e);
|
||||
} finally {
|
||||
|
@ -139,7 +165,8 @@ var Autocompletion = (function () {
|
|||
self.reset = function(hash) {
|
||||
|
||||
try {
|
||||
$('#' + hash + ' .message-area').removeAttr('data-autocompletion-pointer').removeAttr('data-autocompletion-query');
|
||||
$('#' + hash + ' .message-area').removeAttr('data-autocompletion-pointer')
|
||||
.removeAttr('data-autocompletion-query');
|
||||
} catch(e) {
|
||||
Console.error('Autocompletion.reset', e);
|
||||
}
|
||||
|
@ -157,59 +184,62 @@ var Autocompletion = (function () {
|
|||
|
||||
try {
|
||||
// Initialize
|
||||
var vSelector = $('#' + hash + ' .message-area');
|
||||
var value = vSelector.val();
|
||||
var message_area_sel = $('#' + hash + ' .message-area');
|
||||
var value = message_area_sel.val();
|
||||
|
||||
if(!value) {
|
||||
self.reset(hash);
|
||||
}
|
||||
|
||||
var query = vSelector.attr('data-autocompletion-query');
|
||||
|
||||
var query = message_area_sel.attr('data-autocompletion-query');
|
||||
|
||||
if(query === undefined) {
|
||||
// The autocompletion has not been yet launched
|
||||
query = self.getSubQueries(value);
|
||||
vSelector.attr('data-autocompletion-query', JSON.stringify(query));
|
||||
message_area_sel.attr('data-autocompletion-query', JSON.stringify(query));
|
||||
} else {
|
||||
// The autocompletion has already stored a query
|
||||
query = JSON.parse(query);
|
||||
}
|
||||
|
||||
|
||||
// Get the pointer
|
||||
var pointer = vSelector.attr('data-autocompletion-pointer');
|
||||
var i = 0;
|
||||
|
||||
if(pointer)
|
||||
i = parseInt(pointer);
|
||||
|
||||
var pointer = message_area_sel.attr('data-autocompletion-pointer');
|
||||
var i = pointer ? parseInt(pointer, 10) : 0;
|
||||
|
||||
// We get the nickname
|
||||
var nickResult = self.process(query[0], hash)[i];
|
||||
var nick_result = self.process(query[0], hash)[i];
|
||||
var nick;
|
||||
if (nickResult !== undefined) {
|
||||
nick = nickResult[0];
|
||||
|
||||
if(nick_result !== undefined) {
|
||||
nick = nick_result[0];
|
||||
}
|
||||
|
||||
|
||||
// Shit, this is my nick!
|
||||
if((nick !== undefined) && (nick.toLowerCase() == Name.getMUCNick(hash).toLowerCase())) {
|
||||
// Increment
|
||||
i++;
|
||||
|
||||
|
||||
// Get the next nick
|
||||
nickResult = self.process(query[0], hash)[i];
|
||||
if (nickResult !== undefined) {
|
||||
nick = nickResult[0];
|
||||
nick_result = self.process(query[0], hash)[i];
|
||||
|
||||
if (nick_result !== undefined) {
|
||||
nick = nick_result[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// We quote the nick
|
||||
if((nickResult !== undefined) && (nick !== undefined)) {
|
||||
if((nick_result !== undefined) && (nick !== undefined)) {
|
||||
// Increment
|
||||
i++;
|
||||
var message = query[1][nickResult[1]];
|
||||
Utils.quoteMyNick(hash, nick, message);
|
||||
|
||||
|
||||
Utils.quoteMyNick(
|
||||
hash,
|
||||
nick,
|
||||
query[1][nick_result[1]]
|
||||
);
|
||||
|
||||
// Put a pointer
|
||||
vSelector.attr('data-autocompletion-pointer', i);
|
||||
message_area_sel.attr('data-autocompletion-pointer', i);
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Autocompletion.create', e);
|
||||
|
|
|
@ -39,30 +39,32 @@ var Avatar = (function () {
|
|||
|
||||
try {
|
||||
// No need to get the avatar, another process is yet running
|
||||
if(Utils.existArrayValue(self.pending, xid))
|
||||
if(Utils.existArrayValue(self.pending, xid)) {
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
// Initialize: XML data is in one SQL entry, because some browser are sloooow with SQL requests
|
||||
var xml = Common.XMLFromString(
|
||||
DataStore.getPersistent('global', 'avatar', xid)
|
||||
);
|
||||
var forced = false;
|
||||
|
||||
|
||||
// Retrieving forced?
|
||||
if($(xml).find('forced').text() == 'true')
|
||||
if($(xml).find('forced').text() == 'true') {
|
||||
forced = true;
|
||||
|
||||
}
|
||||
|
||||
// No avatar in presence
|
||||
if(!photo && !forced && enabled == 'true') {
|
||||
// Pending marker
|
||||
self.pending.push(xid);
|
||||
|
||||
|
||||
// Reset the avatar
|
||||
self.reset(xid, hex_md5(xid));
|
||||
|
||||
|
||||
Console.warn('No avatar for: ' + xid);
|
||||
}
|
||||
|
||||
|
||||
// Try to catch the avatar
|
||||
else {
|
||||
// Define some stuffs
|
||||
|
@ -72,38 +74,39 @@ var Avatar = (function () {
|
|||
var updated = false;
|
||||
|
||||
// Process the checksum of the avatar
|
||||
if(checksum == photo || photo == 'forget' || forced)
|
||||
if(checksum == photo || photo == 'forget' || forced) {
|
||||
updated = true;
|
||||
}
|
||||
|
||||
// If the avatar is yet stored and a new retrieving is not needed
|
||||
if(mode == 'cache' && type && binval && checksum && updated) {
|
||||
// Pending marker
|
||||
self.pending.push(xid);
|
||||
|
||||
|
||||
// Display the cache avatar
|
||||
self.display(xid, hex_md5(xid), type, binval);
|
||||
|
||||
|
||||
Console.info('Read avatar from cache: ' + xid);
|
||||
}
|
||||
|
||||
|
||||
// Else if the request has not yet been fired, we get it
|
||||
else if((!updated || mode == 'force' || photo == 'forget') && enabled != 'false') {
|
||||
// Pending marker
|
||||
self.pending.push(xid);
|
||||
|
||||
|
||||
// Get the latest avatar
|
||||
var iq = new JSJaCIQ();
|
||||
iq.setType('get');
|
||||
iq.setTo(xid);
|
||||
|
||||
|
||||
iq.appendNode('vCard', {'xmlns': NS_VCARD});
|
||||
|
||||
|
||||
con.send(iq, self.handle);
|
||||
|
||||
|
||||
Console.info('Get avatar from server: ' + xid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
} catch(e) {
|
||||
Console.error('Avatar.get', e);
|
||||
|
@ -124,90 +127,94 @@ var Avatar = (function () {
|
|||
// Extract the XML values
|
||||
var handleXML = iq.getNode();
|
||||
var handleFrom = Common.fullXID(Common.getStanzaFrom(iq));
|
||||
|
||||
|
||||
// Is this me? Remove the resource!
|
||||
if(Common.bareXID(handleFrom) == Common.getXID()) {
|
||||
handleFrom = Common.bareXID(handleFrom);
|
||||
}
|
||||
|
||||
|
||||
// Get some other values
|
||||
var hash = hex_md5(handleFrom);
|
||||
var find = $(handleXML).find('vCard');
|
||||
var aChecksum = 'none';
|
||||
var oChecksum = null;
|
||||
|
||||
|
||||
// Read our own checksum
|
||||
if(handleFrom == Common.getXID()) {
|
||||
oChecksum = DataStore.getDB(Connection.desktop_hash, 'checksum', 1);
|
||||
|
||||
|
||||
// Avoid the "null" value
|
||||
if(!oChecksum)
|
||||
if(!oChecksum) {
|
||||
oChecksum = '';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// vCard not empty?
|
||||
if(find.size()) {
|
||||
// We get our profile details
|
||||
if(handleFrom == Common.getXID()) {
|
||||
// Get the names
|
||||
var names = Name.generateBuddy(iq);
|
||||
|
||||
var phone_number = find.find('TEL:has(NUMBER):first NUMBER:first').text();
|
||||
|
||||
// Write the values to the database
|
||||
DataStore.setDB(Connection.desktop_hash, 'profile', 'name', names[0]);
|
||||
DataStore.setDB(Connection.desktop_hash, 'profile', 'nick', names[1]);
|
||||
DataStore.setDB(Connection.desktop_hash, 'profile', 'phone', phone_number);
|
||||
}
|
||||
|
||||
|
||||
// We get the avatar
|
||||
var aType = find.find('TYPE:first').text();
|
||||
var aBinval = find.find('BINVAL:first').text();
|
||||
|
||||
|
||||
// No binval?
|
||||
if(!aBinval) {
|
||||
aType = 'none';
|
||||
aBinval = 'none';
|
||||
}
|
||||
|
||||
|
||||
// Enough data
|
||||
else {
|
||||
// No type?
|
||||
if(!aType)
|
||||
if(!aType) {
|
||||
aType = 'image/png';
|
||||
|
||||
// Process the checksum
|
||||
else
|
||||
} else {
|
||||
aChecksum = hex_sha1(Base64.decode(aBinval));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// We display the user avatar
|
||||
self.display(handleFrom, hash, aType, aBinval);
|
||||
|
||||
|
||||
// Store the 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);
|
||||
}
|
||||
|
||||
|
||||
// vCard is empty
|
||||
else {
|
||||
self.reset(handleFrom);
|
||||
}
|
||||
|
||||
|
||||
// We got a new checksum for us?
|
||||
if(((oChecksum !== null) && (oChecksum != aChecksum)) || !Presence.first_sent) {
|
||||
// Define a proper checksum
|
||||
var pChecksum = aChecksum;
|
||||
|
||||
if(pChecksum == 'none')
|
||||
|
||||
if(pChecksum == 'none') {
|
||||
pChecksum = '';
|
||||
|
||||
}
|
||||
|
||||
// Update our temp. checksum
|
||||
DataStore.setDB(Connection.desktop_hash, 'checksum', 1, pChecksum);
|
||||
|
||||
|
||||
// Send the stanza
|
||||
if(!Presence.first_sent)
|
||||
if(!Presence.first_sent) {
|
||||
Storage.get(NS_OPTIONS);
|
||||
else if(DataStore.hasPersistent())
|
||||
} else if(DataStore.hasPersistent()) {
|
||||
Presence.sendActions(pChecksum);
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Avatar.handle', e);
|
||||
|
@ -228,7 +235,7 @@ var Avatar = (function () {
|
|||
try {
|
||||
// Store the empty avatar
|
||||
DataStore.setPersistent('global', 'avatar', xid, '<avatar><type>none</type><binval>none</binval><checksum>none</checksum><forced>false</forced></avatar>');
|
||||
|
||||
|
||||
// Display the empty avatar
|
||||
self.display(xid, hash, 'none', 'none');
|
||||
} catch(e) {
|
||||
|
@ -253,18 +260,19 @@ var Avatar = (function () {
|
|||
// Initialize the vars
|
||||
var container = hash + ' .avatar-container';
|
||||
var code = '<img class="avatar" src="';
|
||||
|
||||
|
||||
// If the avatar exists
|
||||
if((type != 'none') && (binval != 'none'))
|
||||
if((type != 'none') && (binval != 'none')) {
|
||||
code += 'data:' + type + ';base64,' + binval;
|
||||
else
|
||||
} else {
|
||||
code += './images/others/default-avatar.png';
|
||||
|
||||
}
|
||||
|
||||
code += '" alt="" />';
|
||||
|
||||
|
||||
// Replace with the new avatar (in the roster and in the chat)
|
||||
$('.' + container).html(code);
|
||||
|
||||
|
||||
// We can remove the pending marker
|
||||
Utils.removeArrayValue(self.pending, xid);
|
||||
} catch(e) {
|
||||
|
|
|
@ -17,12 +17,12 @@ var Base64 = (function () {
|
|||
var chr1, chr2, chr3;
|
||||
var enc1, enc2, enc3, enc4;
|
||||
var i = 0;
|
||||
|
||||
|
||||
do {
|
||||
chr1 = input.charCodeAt(i++);
|
||||
chr2 = input.charCodeAt(i++);
|
||||
chr3 = input.charCodeAt(i++);
|
||||
|
||||
|
||||
enc1 = chr1 >> 2;
|
||||
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
|
||||
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
|
||||
|
@ -33,14 +33,14 @@ var Base64 = (function () {
|
|||
} else if (isNaN(chr3)) {
|
||||
enc4 = 64;
|
||||
}
|
||||
|
||||
|
||||
output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) +
|
||||
keyStr.charAt(enc3) + keyStr.charAt(enc4);
|
||||
} while (i < input.length);
|
||||
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Decodes a base64 string.
|
||||
* @param {String} input The string to decode.
|
||||
|
@ -50,22 +50,22 @@ var Base64 = (function () {
|
|||
var chr1, chr2, chr3;
|
||||
var enc1, enc2, enc3, enc4;
|
||||
var i = 0;
|
||||
|
||||
|
||||
// remove all characters that are not A-Z, a-z, 0-9, +, /, or =
|
||||
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
|
||||
|
||||
|
||||
do {
|
||||
enc1 = keyStr.indexOf(input.charAt(i++));
|
||||
enc2 = keyStr.indexOf(input.charAt(i++));
|
||||
enc3 = keyStr.indexOf(input.charAt(i++));
|
||||
enc4 = keyStr.indexOf(input.charAt(i++));
|
||||
|
||||
|
||||
chr1 = (enc1 << 2) | (enc2 >> 4);
|
||||
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
|
||||
chr3 = ((enc3 & 3) << 6) | enc4;
|
||||
|
||||
|
||||
output = output + String.fromCharCode(chr1);
|
||||
|
||||
|
||||
if (enc3 != 64) {
|
||||
output = output + String.fromCharCode(chr2);
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ var Base64 = (function () {
|
|||
output = output + String.fromCharCode(chr3);
|
||||
}
|
||||
} while (i < input.length);
|
||||
|
||||
|
||||
return output;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -20,6 +20,137 @@ var Board = (function () {
|
|||
var self = {};
|
||||
|
||||
|
||||
/* Contants */
|
||||
self.NOTIFICATION = (window.Notification || window.mozNotification || window.webkitNotification);
|
||||
|
||||
|
||||
/**
|
||||
* Generate board info message
|
||||
* @private
|
||||
* @param {string} id
|
||||
* @return {string}
|
||||
*/
|
||||
self._generateBoardInfo = function(id) {
|
||||
|
||||
var text = null;
|
||||
|
||||
try {
|
||||
switch(id) {
|
||||
// Password change
|
||||
case 1:
|
||||
text = Common._e("Your password has been changed, now you can connect to your account with your new login data.");
|
||||
|
||||
break;
|
||||
|
||||
// Account deletion
|
||||
case 2:
|
||||
text = Common._e("Your XMPP account has been removed, bye!");
|
||||
|
||||
break;
|
||||
|
||||
// Account logout
|
||||
case 3:
|
||||
text = Common._e("You have been logged out of your XMPP account, have a nice day!");
|
||||
|
||||
break;
|
||||
|
||||
// Groupchat join
|
||||
case 4:
|
||||
text = Common._e("The room you tried to join doesn't seem to exist.");
|
||||
|
||||
break;
|
||||
|
||||
// Groupchat removal
|
||||
case 5:
|
||||
text = Common._e("The groupchat has been removed.");
|
||||
|
||||
break;
|
||||
|
||||
// Non-existant groupchat user
|
||||
case 6:
|
||||
text = Common._e("The user that you want to reach is not present in the room.");
|
||||
|
||||
break;
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Board._generateBoardInfo', e);
|
||||
} finally {
|
||||
return text;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Generate board error message
|
||||
* @private
|
||||
* @param {string} id
|
||||
* @return {string}
|
||||
*/
|
||||
self._generateBoardError = function(id) {
|
||||
|
||||
var text = null;
|
||||
|
||||
try {
|
||||
switch(id) {
|
||||
// Custom error
|
||||
case 1:
|
||||
text = '<b>' + Common._e("Error") + '</b> » <span></span>';
|
||||
|
||||
break;
|
||||
|
||||
// Network error
|
||||
case 2:
|
||||
text = Common._e("Jappix has been interrupted by a network issue, a bug or bad login (check that you entered the right credentials), sorry for the inconvenience.");
|
||||
|
||||
break;
|
||||
|
||||
// List retrieving error
|
||||
case 3:
|
||||
text = Common._e("The element list on this server could not be obtained!");
|
||||
|
||||
break;
|
||||
|
||||
// Attaching error
|
||||
case 4:
|
||||
text = Common.printf(Common._e("An error occured while uploading your file: maybe it is too big (%s maximum) or forbidden!"), JAPPIX_MAX_UPLOAD);
|
||||
|
||||
break;
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Board._generateBoardError', e);
|
||||
} finally {
|
||||
return text;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Attaches board events
|
||||
* @private
|
||||
* @param {object} board_sel
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._attachEvents = function(board_sel) {
|
||||
|
||||
try {
|
||||
board_sel.click(function() {
|
||||
self.closeThis(this);
|
||||
});
|
||||
|
||||
board_sel.oneTime('5s', function() {
|
||||
self.closeThis(this);
|
||||
});
|
||||
|
||||
board_sel.slideDown();
|
||||
} catch(e) {
|
||||
Console.error('Board._attachEvents', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a board panel
|
||||
* @public
|
||||
|
@ -32,97 +163,29 @@ var Board = (function () {
|
|||
try {
|
||||
// Text var
|
||||
var text = '';
|
||||
|
||||
|
||||
// Info
|
||||
if(type == 'info') {
|
||||
switch(id) {
|
||||
// Password change
|
||||
case 1:
|
||||
text = Common._e("Your password has been changed, now you can connect to your account with your new login data.");
|
||||
|
||||
break;
|
||||
|
||||
// Account deletion
|
||||
case 2:
|
||||
text = Common._e("Your XMPP account has been removed, bye!");
|
||||
|
||||
break;
|
||||
|
||||
// Account logout
|
||||
case 3:
|
||||
text = Common._e("You have been logged out of your XMPP account, have a nice day!");
|
||||
|
||||
break;
|
||||
|
||||
// Groupchat join
|
||||
case 4:
|
||||
text = Common._e("The room you tried to join doesn't seem to exist.");
|
||||
|
||||
break;
|
||||
|
||||
// Groupchat removal
|
||||
case 5:
|
||||
text = Common._e("The groupchat has been removed.");
|
||||
|
||||
break;
|
||||
|
||||
// Non-existant groupchat user
|
||||
case 6:
|
||||
text = Common._e("The user that you want to reach is not present in the room.");
|
||||
|
||||
break;
|
||||
}
|
||||
text = self._generateBoardInfo(id);
|
||||
} else {
|
||||
text = self._generateBoardError(id);
|
||||
}
|
||||
|
||||
// Error
|
||||
else {
|
||||
switch(id) {
|
||||
// Custom error
|
||||
case 1:
|
||||
text = '<b>' + Common._e("Error") + '</b> » <span></span>';
|
||||
|
||||
break;
|
||||
|
||||
// Network error
|
||||
case 2:
|
||||
text = Common._e("Jappix has been interrupted by a network issue, a bug or bad login (check that you entered the right credentials), sorry for the inconvenience.");
|
||||
|
||||
break;
|
||||
|
||||
// List retrieving error
|
||||
case 3:
|
||||
text = Common._e("The element list on this server could not be obtained!");
|
||||
|
||||
break;
|
||||
|
||||
// Attaching error
|
||||
case 4:
|
||||
text = Common.printf(Common._e("An error occured while uploading your file: maybe it is too big (%s maximum) or forbidden!"), JAPPIX_MAX_UPLOAD);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// No text?
|
||||
if(!text)
|
||||
if(!text) {
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
// Append the content
|
||||
$('#board').append('<div class="one-board ' + type + '" data-id="' + id + '">' + text + '</div>');
|
||||
|
||||
$('#board').append(
|
||||
'<div class="one-board ' + type + '" data-id="' + id + '">' + text + '</div>'
|
||||
);
|
||||
|
||||
// Events (click and auto-hide)
|
||||
$('#board .one-board.' + type + '[data-id="' + id + '"]')
|
||||
|
||||
.click(function() {
|
||||
self.closeThis(this);
|
||||
})
|
||||
|
||||
.oneTime('5s', function() {
|
||||
self.closeThis(this);
|
||||
})
|
||||
|
||||
.slideDown();
|
||||
|
||||
self._attachEvents(
|
||||
$('#board .one-board.' + type + '[data-id="' + id + '"]')
|
||||
);
|
||||
|
||||
return true;
|
||||
} catch(e) {
|
||||
Console.error('Board.create', e);
|
||||
|
@ -158,7 +221,7 @@ var Board = (function () {
|
|||
try {
|
||||
// In a first, we destroy other boards
|
||||
self.destroy();
|
||||
|
||||
|
||||
// Then we display the board
|
||||
self.create(type, id);
|
||||
} catch(e) {
|
||||
|
@ -235,99 +298,74 @@ var Board = (function () {
|
|||
|
||||
try {
|
||||
// Cannot process?
|
||||
if(Common.isFocused() || !content || !(window.webkitNotifications || window.Notification)) {
|
||||
if(Common.isFocused() || !content || !self.NOTIFICATION) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Default icon?
|
||||
if(!icon) {
|
||||
icon = './images/others/default-avatar.png';
|
||||
|
||||
|
||||
// Avatar icon?
|
||||
if(xid) {
|
||||
var avatar_xml = Common.XMLFromString(
|
||||
DataStore.getPersistent('global', 'avatar', xid)
|
||||
);
|
||||
|
||||
var avatar_type = $(avatar_xml).find('type').text() || 'image/png';
|
||||
var avatar_binval = $(avatar_xml).find('binval').text();
|
||||
|
||||
if(avatar_binval && avatar_type)
|
||||
|
||||
if(avatar_binval && avatar_type) {
|
||||
icon = 'data:' + avatar_type + ';base64,' + avatar_binval;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Default title?
|
||||
if(!title) {
|
||||
title = Common._e("New event!");
|
||||
}
|
||||
|
||||
// Click callback
|
||||
var cb_click_fn = function() {
|
||||
// Create notification
|
||||
var notification = new self.NOTIFICATION(title, {
|
||||
dir: 'auto',
|
||||
lang: '',
|
||||
body: content,
|
||||
tag: type,
|
||||
icon: icon
|
||||
});
|
||||
|
||||
// Click event
|
||||
notification.onclick = function() {
|
||||
// Click action?
|
||||
switch(type) {
|
||||
case 'chat':
|
||||
Interface.switchChan(hex_md5(xid));
|
||||
break;
|
||||
|
||||
|
||||
case 'groupchat':
|
||||
Interface.switchChan(hex_md5(Common.bareXID(xid)));
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Focus on msg-me
|
||||
window.focus();
|
||||
|
||||
|
||||
// Remove notification
|
||||
this.cancel();
|
||||
this.close();
|
||||
};
|
||||
|
||||
// Check for notification permission
|
||||
try {
|
||||
if(Notification.permission == 'granted' || Notification.permission === undefined) {
|
||||
var notification = new Notification(title, {
|
||||
dir: 'auto',
|
||||
lang: '',
|
||||
body: content,
|
||||
tag: type,
|
||||
icon: icon
|
||||
});
|
||||
|
||||
notification.onclick = cb_click_fn;
|
||||
// Show event
|
||||
notification.onshow = function() {
|
||||
setTimeout(function() {
|
||||
notification.close();
|
||||
}, 10000);
|
||||
};
|
||||
|
||||
setTimeout(function() {
|
||||
notification.close();
|
||||
}, 10000);
|
||||
|
||||
if(notification.permission == 'granted') {
|
||||
return notification;
|
||||
}
|
||||
}
|
||||
} catch(_e) {
|
||||
if(window.webkitNotifications.checkPermission() === 0) {
|
||||
// Create notification
|
||||
var notification = window.webkitNotifications.createNotification(icon, title, content);
|
||||
|
||||
// Auto-hide after a while
|
||||
notification.ondisplay = function(event) {
|
||||
setTimeout(function() {
|
||||
event.currentTarget.cancel();
|
||||
}, 10000);
|
||||
};
|
||||
|
||||
// Click event
|
||||
notification.onclick = cb_click_fn;
|
||||
|
||||
// Show notification
|
||||
notification.show();
|
||||
|
||||
return notification;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return notification;
|
||||
} catch(e) {
|
||||
Console.error('Board.quick', e);
|
||||
}
|
||||
|
@ -343,21 +381,7 @@ var Board = (function () {
|
|||
self.quickPermission = function() {
|
||||
|
||||
try {
|
||||
try {
|
||||
// W3C Notification API (still a draft!)
|
||||
if(Notification.permission !== 'granted') {
|
||||
// Ask for permission
|
||||
Notification.requestPermission();
|
||||
}
|
||||
} catch (_e) {
|
||||
// WebKit Notification API (fallback)
|
||||
if(!window.webkitNotifications || (window.webkitNotifications.checkPermission() === 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ask for permission
|
||||
window.webkitNotifications.requestPermission();
|
||||
}
|
||||
self.NOTIFICATION.requestPermission();
|
||||
} catch(e) {
|
||||
Console.error('Board.quickPermission', e);
|
||||
}
|
||||
|
@ -376,8 +400,9 @@ var Board = (function () {
|
|||
// Fires quickPermission() on document click
|
||||
$(document).click(function() {
|
||||
// Ask for permission to use quick boards
|
||||
if((typeof con != 'undefined') && con.connected())
|
||||
if((typeof con != 'undefined') && con.connected()) {
|
||||
self.quickPermission();
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Board.launch', e);
|
||||
|
|
|
@ -6,12 +6,12 @@
|
|||
var BrowserDetect = {
|
||||
init: function () {
|
||||
this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
|
||||
this.version = this.searchVersion(navigator.userAgent)
|
||||
|| this.searchVersion(navigator.appVersion)
|
||||
|| "an unknown version";
|
||||
this.version = this.searchVersion(navigator.userAgent) ||
|
||||
this.searchVersion(navigator.appVersion) ||
|
||||
"an unknown version";
|
||||
this.OS = this.searchString(this.dataOS) || "an unknown OS";
|
||||
},
|
||||
|
||||
|
||||
searchString: function (data) {
|
||||
for (var i=0;i<data.length;i++) {
|
||||
var dataString = data[i].string;
|
||||
|
@ -25,13 +25,13 @@ var BrowserDetect = {
|
|||
return data[i].identity;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
searchVersion: function (dataString) {
|
||||
var index = dataString.indexOf(this.versionSearchString);
|
||||
if (index == -1) return;
|
||||
return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
|
||||
},
|
||||
|
||||
|
||||
dataBrowser: [
|
||||
{
|
||||
string: navigator.userAgent,
|
||||
|
@ -97,7 +97,7 @@ var BrowserDetect = {
|
|||
versionSearch: "Mozilla"
|
||||
}
|
||||
],
|
||||
|
||||
|
||||
dataOS : [
|
||||
{
|
||||
string: navigator.platform,
|
||||
|
|
|
@ -31,6 +31,7 @@ var Bubble = (function () {
|
|||
// Destroy all the elements
|
||||
$('.bubble.hidable:visible').hide();
|
||||
$('.bubble.removable').remove();
|
||||
|
||||
$('body').off('click');
|
||||
} catch(e) {
|
||||
Console.error('Bubble.close', e);
|
||||
|
@ -53,33 +54,36 @@ var Bubble = (function () {
|
|||
// Hidable bubbles special things
|
||||
if($(selector).is('.hidable')) {
|
||||
// This bubble is yet displayed? So abort!
|
||||
if($(selector).is(':visible'))
|
||||
if($(selector).is(':visible')) {
|
||||
return self.close();
|
||||
|
||||
}
|
||||
|
||||
// Close all the bubbles
|
||||
self.close();
|
||||
|
||||
|
||||
// Show the requested bubble
|
||||
$(selector).show();
|
||||
}
|
||||
|
||||
|
||||
// Removable bubbles special things
|
||||
else {
|
||||
// This bubble is yet added? So abort!
|
||||
if(Common.exists(selector))
|
||||
if(Common.exists(selector)) {
|
||||
return self.close();
|
||||
|
||||
}
|
||||
|
||||
// Close all the bubbles
|
||||
self.close();
|
||||
}
|
||||
|
||||
|
||||
// Creates a new click event to close the bubble
|
||||
$('body').on('click', function(evt) {
|
||||
var target = evt.target;
|
||||
|
||||
|
||||
// If this is a click away from a bubble
|
||||
if(!$(target).parents('.ibubble').size())
|
||||
if(!$(target).parents('.ibubble').size()) {
|
||||
self.close();
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Bubble.show', e);
|
||||
|
|
1095
source/app/javascripts/call.js
Normal file
|
@ -20,6 +20,444 @@ var Caps = (function () {
|
|||
var self = {};
|
||||
|
||||
|
||||
/* Constants */
|
||||
self.disco_infos = {
|
||||
'identity': {
|
||||
'category': 'client',
|
||||
'type': 'web',
|
||||
'name': 'Jappix'
|
||||
},
|
||||
|
||||
'items': [
|
||||
NS_MUC,
|
||||
NS_MUC_USER,
|
||||
NS_MUC_ADMIN,
|
||||
NS_MUC_OWNER,
|
||||
NS_MUC_CONFIG,
|
||||
NS_DISCO_INFO,
|
||||
NS_DISCO_ITEMS,
|
||||
NS_PUBSUB_RI,
|
||||
NS_BOSH,
|
||||
NS_CAPS,
|
||||
NS_MOOD,
|
||||
NS_ACTIVITY,
|
||||
NS_TUNE,
|
||||
NS_GEOLOC,
|
||||
NS_NICK,
|
||||
NS_URN_MBLOG,
|
||||
NS_URN_INBOX,
|
||||
NS_MOOD + NS_NOTIFY,
|
||||
NS_ACTIVITY + NS_NOTIFY,
|
||||
NS_TUNE + NS_NOTIFY,
|
||||
NS_GEOLOC + NS_NOTIFY,
|
||||
NS_URN_MBLOG + NS_NOTIFY,
|
||||
NS_URN_INBOX + NS_NOTIFY,
|
||||
NS_URN_DELAY,
|
||||
NS_ROSTER,
|
||||
NS_ROSTERX,
|
||||
NS_HTTP_AUTH,
|
||||
NS_CHATSTATES,
|
||||
NS_XHTML_IM,
|
||||
NS_URN_MAM,
|
||||
NS_IPV6,
|
||||
NS_LAST,
|
||||
NS_PRIVATE,
|
||||
NS_REGISTER,
|
||||
NS_SEARCH,
|
||||
NS_COMMANDS,
|
||||
NS_VERSION,
|
||||
NS_XDATA,
|
||||
NS_VCARD,
|
||||
NS_IETF_VCARD4,
|
||||
NS_URN_ADATA,
|
||||
NS_URN_AMETA,
|
||||
NS_URN_TIME,
|
||||
NS_URN_PING,
|
||||
NS_URN_RECEIPTS,
|
||||
NS_PRIVACY,
|
||||
NS_IQOOB,
|
||||
NS_XOOB,
|
||||
NS_URN_CARBONS,
|
||||
NS_URN_CORRECT,
|
||||
NS_URN_MARKERS,
|
||||
NS_URN_IDLE,
|
||||
NS_URN_ATTENTION,
|
||||
NS_URN_REACH,
|
||||
NS_URN_HINTS
|
||||
]
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Parse identities from disco infos query response
|
||||
* @private
|
||||
* @param {object} query
|
||||
* @return {object}
|
||||
*/
|
||||
self._parseDiscoIdentities = function(query) {
|
||||
|
||||
var identities = [];
|
||||
|
||||
try {
|
||||
var cur_category, cur_type, cur_lang, cur_name;
|
||||
|
||||
$(query).find('identity').each(function() {
|
||||
cur_category = $(this).attr('category') || '';
|
||||
cur_type = $(this).attr('type') || '';
|
||||
cur_lang = $(this).attr('xml:lang') || '';
|
||||
cur_name = $(this).attr('name') || '';
|
||||
|
||||
identities.push(cur_category + '/' + cur_type + '/' + cur_lang + '/' + cur_name);
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Caps._parseDiscoIdentities', e);
|
||||
} finally {
|
||||
return identities;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Parse features from disco infos query response
|
||||
* @private
|
||||
* @param {object} query
|
||||
* @return {object}
|
||||
*/
|
||||
self._parseDiscoFeatures = function(query) {
|
||||
|
||||
var features = [];
|
||||
|
||||
try {
|
||||
var cur_var;
|
||||
|
||||
$(query).find('feature').each(function() {
|
||||
cur_var = $(this).attr('var');
|
||||
|
||||
// Add the current value to the array
|
||||
if(cur_var) {
|
||||
features.push(cur_var);
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Caps._parseDiscoFatures', e);
|
||||
} finally {
|
||||
return features;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Parse data form from disco infos query response
|
||||
* @private
|
||||
* @param {object} query
|
||||
* @return {object}
|
||||
*/
|
||||
self._parseDiscoDataForms = function(query) {
|
||||
|
||||
var data_forms = [];
|
||||
|
||||
try {
|
||||
var cur_string, cur_sort_var,
|
||||
cur_text, cur_var, cur_sort_val;
|
||||
|
||||
$(query).find('x[xmlns="' + NS_XDATA + '"]').each(function() {
|
||||
// Initialize some stuffs
|
||||
cur_string = '';
|
||||
cur_sort_var = [];
|
||||
|
||||
// Add the form type field
|
||||
$(this).find('field[var="FORM_TYPE"] value').each(function() {
|
||||
cur_text = $(this).text();
|
||||
|
||||
if(cur_text) {
|
||||
cur_string += cur_text + '<';
|
||||
}
|
||||
});
|
||||
|
||||
// Add the var attributes into an array
|
||||
$(this).find('field:not([var="FORM_TYPE"])').each(function() {
|
||||
cur_var = $(this).attr('var');
|
||||
|
||||
if(cur_var) {
|
||||
cur_sort_var.push(cur_var);
|
||||
}
|
||||
});
|
||||
|
||||
// Sort the var attributes
|
||||
cur_sort_var = cur_sort_var.sort();
|
||||
|
||||
// Loop this sorted var attributes
|
||||
$.each(cur_sort_var, function(i) {
|
||||
// Initialize the value sorting
|
||||
cur_sort_val = [];
|
||||
|
||||
// Append it to the string
|
||||
cur_string += cur_sort_var[i] + '<';
|
||||
|
||||
// Add each value to the array
|
||||
$(this).find('field[var=' + cur_sort_var[i] + '] value').each(function() {
|
||||
cur_sort_val.push($(this).text());
|
||||
});
|
||||
|
||||
// Sort the values
|
||||
cur_sort_val = cur_sort_val.sort();
|
||||
|
||||
// Append the values to the string
|
||||
for(var j in cur_sort_val) {
|
||||
cur_string += cur_sort_val[j] + '<';
|
||||
}
|
||||
});
|
||||
|
||||
// Any string?
|
||||
if(cur_string) {
|
||||
// Remove the undesired double '<' from the string
|
||||
if(cur_string.match(/(.+)(<)+$/)) {
|
||||
cur_string = cur_string.substring(0, cur_string.length - 1);
|
||||
}
|
||||
|
||||
// Add the current string to the array
|
||||
data_forms.push(cur_string);
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Caps._parseDiscoDataForms', e);
|
||||
} finally {
|
||||
return data_forms;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply XHTML-IM features from disco infos
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @param {object} features
|
||||
* @param {object} style_sel
|
||||
* @param {object} message_area_sel
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._applyDiscoXHTMLIM = function(xid, features, style_sel, message_area_sel) {
|
||||
|
||||
try {
|
||||
// Apply
|
||||
if(NS_XHTML_IM in features) {
|
||||
style_sel.show();
|
||||
} else {
|
||||
// Remove the tooltip elements
|
||||
style_sel.hide();
|
||||
style_sel.find('.bubble-style').remove();
|
||||
|
||||
// Reset the markers
|
||||
message_area_sel.removeAttr('style')
|
||||
.removeAttr('data-font')
|
||||
.removeAttr('data-fontsize')
|
||||
.removeAttr('data-color')
|
||||
.removeAttr('data-bold')
|
||||
.removeAttr('data-italic')
|
||||
.removeAttr('data-underline');
|
||||
}
|
||||
|
||||
} catch(e) {
|
||||
Console.error('Caps._applyDiscoXHTMLIM', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply Jingle features from disco infos
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @param {object} path_sel
|
||||
* @param {object} roster_sel
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._applyDiscoJingle = function(xid, path_sel, roster_sel) {
|
||||
|
||||
try {
|
||||
// Selectors
|
||||
var roster_jingle_sel = roster_sel.find('.buddy-infos .call-jingle');
|
||||
var jingle_audio = path_sel.find('.tools-jingle-audio');
|
||||
var roster_jingle_audio = roster_jingle_sel.find('a.audio');
|
||||
var jingle_video = path_sel.find('.tools-jingle-video');
|
||||
var roster_jingle_video = roster_jingle_sel.find('a.video');
|
||||
var roster_jingle_separator = roster_jingle_sel.find('span.separator');
|
||||
|
||||
// Apply
|
||||
var jingle_local_supported = JSJAC_JINGLE_AVAILABLE;
|
||||
var jingle_audio_xid = self.getFeatureResource(xid, NS_JINGLE_APPS_RTP_AUDIO);
|
||||
var jingle_video_xid = self.getFeatureResource(xid, NS_JINGLE_APPS_RTP_VIDEO);
|
||||
|
||||
if(jingle_audio_xid && jingle_local_supported) {
|
||||
jingle_audio.show();
|
||||
roster_jingle_audio.show();
|
||||
} else {
|
||||
jingle_audio.hide();
|
||||
roster_jingle_audio.hide();
|
||||
}
|
||||
|
||||
if(jingle_video_xid && jingle_local_supported) {
|
||||
jingle_video.show();
|
||||
roster_jingle_video.show();
|
||||
} else {
|
||||
jingle_video.hide();
|
||||
roster_jingle_video.hide();
|
||||
}
|
||||
|
||||
if(jingle_audio_xid && jingle_video_xid && jingle_local_supported) {
|
||||
roster_jingle_separator.show();
|
||||
} else {
|
||||
roster_jingle_separator.hide();
|
||||
}
|
||||
|
||||
if((jingle_audio_xid || jingle_video_xid) && jingle_local_supported) {
|
||||
roster_jingle_sel.show();
|
||||
} else {
|
||||
roster_jingle_sel.hide();
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Caps._applyDiscoJingle', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply Out of Band Data features from disco infos
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @param {object} features
|
||||
* @param {object} file_sel
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._applyDiscoOOB = function(xid, features, file_sel) {
|
||||
|
||||
try {
|
||||
// Apply
|
||||
var iq_oob_xid = self.getFeatureResource(xid, NS_IQOOB);
|
||||
|
||||
if(iq_oob_xid || NS_XOOB in features) {
|
||||
file_sel.show();
|
||||
|
||||
// Set a marker
|
||||
file_sel.attr(
|
||||
'data-oob',
|
||||
iq_oob_xid ? 'iq' : 'x'
|
||||
);
|
||||
} else {
|
||||
// Remove the tooltip elements
|
||||
file_sel.hide();
|
||||
file_sel.find('.bubble-style').remove();
|
||||
|
||||
// Reset the marker
|
||||
file_sel.removeAttr('data-oob');
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Caps._applyDiscoOOB', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply Receipts features from disco infos
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @param {object} features
|
||||
* @param {object} message_area_sel
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._applyDiscoReceipts = function(xid, features, message_area_sel) {
|
||||
|
||||
try {
|
||||
// Apply
|
||||
if(NS_URN_RECEIPTS in features) {
|
||||
message_area_sel.attr('data-receipts', 'true');
|
||||
} else {
|
||||
message_area_sel.removeAttr('data-receipts');
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Caps._applyDiscoReceipts', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply Last Message Correction features from disco infos
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @param {object} features
|
||||
* @param {object} path_sel
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._applyDiscoCorrection = function(xid, features, path_sel) {
|
||||
|
||||
try {
|
||||
// Apply
|
||||
if(NS_URN_CORRECT in features) {
|
||||
path_sel.attr('data-correction', 'true');
|
||||
} else {
|
||||
path_sel.removeAttr('data-correction');
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Caps._applyDiscoCorrection', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply Chat Markers features from disco infos
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @param {object} features
|
||||
* @param {object} path_sel
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._applyDiscoMarkers = function(xid, features, path_sel) {
|
||||
|
||||
try {
|
||||
// Apply
|
||||
if(NS_URN_MARKERS in features) {
|
||||
path_sel.attr('data-markers', 'true');
|
||||
} else {
|
||||
path_sel.removeAttr('data-markers');
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Caps._applyDiscoMarkers', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply Attention features from disco infos
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @param {object} features
|
||||
* @param {object} path_sel
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._applyDiscoAttention = function(xid, features, path_sel) {
|
||||
|
||||
try {
|
||||
// Apply
|
||||
if(NS_URN_ATTENTION in features) {
|
||||
path_sel.attr('data-attention', 'true');
|
||||
} else {
|
||||
path_sel.removeAttr('data-attention');
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Caps._applyDiscoAttention', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Reads a stored Caps
|
||||
* @public
|
||||
|
@ -47,62 +485,12 @@ var Caps = (function () {
|
|||
self.myDiscoInfos = function() {
|
||||
|
||||
try {
|
||||
var disco_base = [
|
||||
NS_MUC,
|
||||
NS_MUC_USER,
|
||||
NS_MUC_ADMIN,
|
||||
NS_MUC_OWNER,
|
||||
NS_MUC_CONFIG,
|
||||
NS_DISCO_INFO,
|
||||
NS_DISCO_ITEMS,
|
||||
NS_PUBSUB_RI,
|
||||
NS_BOSH,
|
||||
NS_CAPS,
|
||||
NS_MOOD,
|
||||
NS_ACTIVITY,
|
||||
NS_TUNE,
|
||||
NS_GEOLOC,
|
||||
NS_NICK,
|
||||
NS_URN_MBLOG,
|
||||
NS_URN_INBOX,
|
||||
NS_MOOD + NS_NOTIFY,
|
||||
NS_ACTIVITY + NS_NOTIFY,
|
||||
NS_TUNE + NS_NOTIFY,
|
||||
NS_GEOLOC + NS_NOTIFY,
|
||||
NS_URN_MBLOG + NS_NOTIFY,
|
||||
NS_URN_INBOX + NS_NOTIFY,
|
||||
NS_URN_DELAY,
|
||||
NS_ROSTER,
|
||||
NS_ROSTERX,
|
||||
NS_HTTP_AUTH,
|
||||
NS_CHATSTATES,
|
||||
NS_XHTML_IM,
|
||||
NS_URN_MAM,
|
||||
NS_IPV6,
|
||||
NS_LAST,
|
||||
NS_PRIVATE,
|
||||
NS_REGISTER,
|
||||
NS_SEARCH,
|
||||
NS_COMMANDS,
|
||||
NS_VERSION,
|
||||
NS_XDATA,
|
||||
NS_VCARD,
|
||||
NS_IETF_VCARD4,
|
||||
NS_URN_ADATA,
|
||||
NS_URN_AMETA,
|
||||
NS_URN_TIME,
|
||||
NS_URN_PING,
|
||||
NS_URN_RECEIPTS,
|
||||
NS_PRIVACY,
|
||||
NS_IQOOB,
|
||||
NS_XOOB,
|
||||
NS_URN_CARBONS
|
||||
];
|
||||
var disco_base = self.disco_infos.items;
|
||||
|
||||
var disco_jingle = JSJaCJingle_disco();
|
||||
var disco_jingle = JSJaCJingle.disco();
|
||||
var disco_all = disco_base.concat(disco_jingle);
|
||||
|
||||
return disco_all;
|
||||
|
||||
return Utils.uniqueArrayValues(disco_all);
|
||||
} catch(e) {
|
||||
Console.error('Caps.myDiscoInfos', e);
|
||||
}
|
||||
|
@ -123,35 +511,35 @@ var Caps = (function () {
|
|||
// No CAPS
|
||||
if(!caps) {
|
||||
Console.warn('No CAPS: ' + to);
|
||||
|
||||
|
||||
self.displayDiscoInfos(to, '');
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Get the stored disco infos
|
||||
var xml = self.read(caps);
|
||||
|
||||
|
||||
// Yet stored
|
||||
if(xml) {
|
||||
Console.info('CAPS from cache: ' + to);
|
||||
|
||||
|
||||
self.displayDiscoInfos(to, xml);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Console.info('CAPS from the network: ' + to);
|
||||
|
||||
|
||||
// Not stored: get the disco#infos
|
||||
var iq = new JSJaCIQ();
|
||||
|
||||
|
||||
iq.setTo(to);
|
||||
iq.setType('get');
|
||||
iq.setQuery(NS_DISCO_INFO);
|
||||
|
||||
|
||||
con.send(iq, self.handleDiscoInfos);
|
||||
|
||||
|
||||
return true;
|
||||
} catch(e) {
|
||||
Console.error('Caps.getDiscoInfos', e);
|
||||
|
@ -169,123 +557,37 @@ var Caps = (function () {
|
|||
self.handleDiscoInfos = function(iq) {
|
||||
|
||||
try {
|
||||
if(!iq || (iq.getType() == 'error'))
|
||||
if(!iq || (iq.getType() == 'error')) {
|
||||
return;
|
||||
|
||||
// IQ received, get some values
|
||||
}
|
||||
|
||||
var from = Common.fullXID(Common.getStanzaFrom(iq));
|
||||
var query = iq.getQuery();
|
||||
|
||||
// Generate the CAPS-processing values
|
||||
var identities = [];
|
||||
var features = [];
|
||||
var data_forms = [];
|
||||
|
||||
// Identity values
|
||||
$(query).find('identity').each(function() {
|
||||
var pCategory = $(this).attr('category');
|
||||
var pType = $(this).attr('type');
|
||||
var pLang = $(this).attr('xml:lang');
|
||||
var pName = $(this).attr('name');
|
||||
|
||||
if(!pCategory)
|
||||
pCategory = '';
|
||||
if(!pType)
|
||||
pType = '';
|
||||
if(!pLang)
|
||||
pLang = '';
|
||||
if(!pName)
|
||||
pName = '';
|
||||
|
||||
identities.push(pCategory + '/' + pType + '/' + pLang + '/' + pName);
|
||||
});
|
||||
|
||||
// Feature values
|
||||
$(query).find('feature').each(function() {
|
||||
var pVar = $(this).attr('var');
|
||||
|
||||
// Add the current value to the array
|
||||
if(pVar)
|
||||
features.push(pVar);
|
||||
});
|
||||
|
||||
// Data-form values
|
||||
$(query).find('x[xmlns="' + NS_XDATA + '"]').each(function() {
|
||||
// Initialize some stuffs
|
||||
var pString = '';
|
||||
var sortVar = [];
|
||||
|
||||
// Add the form type field
|
||||
$(this).find('field[var="FORM_TYPE"] value').each(function() {
|
||||
var cText = $(this).text();
|
||||
|
||||
if(cText)
|
||||
pString += cText + '<';
|
||||
});
|
||||
|
||||
// Add the var attributes into an array
|
||||
$(this).find('field:not([var="FORM_TYPE"])').each(function() {
|
||||
var cVar = $(this).attr('var');
|
||||
|
||||
if(cVar)
|
||||
sortVar.push(cVar);
|
||||
});
|
||||
|
||||
// Sort the var attributes
|
||||
sortVar = sortVar.sort();
|
||||
|
||||
// Loop this sorted var attributes
|
||||
$.each(sortVar, function(i) {
|
||||
// Initialize the value sorting
|
||||
var sortVal = [];
|
||||
|
||||
// Append it to the string
|
||||
pString += sortVar[i] + '<';
|
||||
|
||||
// Add each value to the array
|
||||
$(this).find('field[var=' + sortVar[i] + '] value').each(function() {
|
||||
sortVal.push($(this).text());
|
||||
});
|
||||
|
||||
// Sort the values
|
||||
sortVal = sortVal.sort();
|
||||
|
||||
// Append the values to the string
|
||||
for(var j in sortVal) {
|
||||
pString += sortVal[j] + '<';
|
||||
}
|
||||
});
|
||||
|
||||
// Any string?
|
||||
if(pString) {
|
||||
// Remove the undesired double '<' from the string
|
||||
if(pString.match(/(.+)(<)+$/))
|
||||
pString = pString.substring(0, pString.length - 1);
|
||||
|
||||
// Add the current string to the array
|
||||
data_forms.push(pString);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Parse values
|
||||
var identities = self._parseDiscoIdentities(query);
|
||||
var features = self._parseDiscoFeatures(query);
|
||||
var data_forms = self._parseDiscoDataForms(query);
|
||||
|
||||
// Process the CAPS
|
||||
var caps = self.process(identities, features, data_forms);
|
||||
|
||||
|
||||
// Get the XML string
|
||||
var xml = Common.xmlToString(query);
|
||||
|
||||
|
||||
// Store the disco infos
|
||||
DataStore.setPersistent('global', 'caps', caps, xml);
|
||||
|
||||
|
||||
// This is our server
|
||||
if(from == Utils.getServer()) {
|
||||
// Handle the features
|
||||
Features.handle(xml);
|
||||
|
||||
|
||||
Console.info('Got our server CAPS');
|
||||
} else {
|
||||
// Display the disco infos
|
||||
self.displayDiscoInfos(from, xml);
|
||||
|
||||
|
||||
Console.info('Got CAPS: ' + from);
|
||||
}
|
||||
} catch(e) {
|
||||
|
@ -307,11 +609,12 @@ var Caps = (function () {
|
|||
try {
|
||||
// Generate the chat path
|
||||
var xid = Common.bareXID(from);
|
||||
|
||||
|
||||
// This comes from a private groupchat chat?
|
||||
if(Utils.isPrivate(xid))
|
||||
if(Utils.isPrivate(xid)) {
|
||||
xid = from;
|
||||
|
||||
}
|
||||
|
||||
hash = hex_md5(xid);
|
||||
|
||||
// Display the supported features
|
||||
|
@ -324,98 +627,22 @@ var Caps = (function () {
|
|||
features[current] = 1;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Paths
|
||||
var path = $('#' + hash);
|
||||
var roster_path = $('#roster .buddy.' + hash);
|
||||
var roster_jingle_path = roster_path.find('.buddy-infos .call-jingle');
|
||||
var path_sel = $('#' + hash);
|
||||
var roster_sel = $('#roster .buddy.' + hash);
|
||||
var message_area_sel = path_sel.find('.message-area');
|
||||
var style_sel = path_sel.find('.chat-tools-style');
|
||||
var file_sel = path_sel.find('.chat-tools-file');
|
||||
|
||||
var message_area = path.find('.message-area');
|
||||
var style = path.find('.chat-tools-style');
|
||||
var jingle_audio = path.find('.tools-jingle-audio');
|
||||
var roster_jingle_audio = roster_jingle_path.find('a.audio');
|
||||
var jingle_video = path.find('.tools-jingle-video');
|
||||
var roster_jingle_video = roster_jingle_path.find('a.video');
|
||||
var roster_jingle_separator = roster_jingle_path.find('span.separator');
|
||||
var file = path.find('.chat-tools-file');
|
||||
|
||||
// Apply xHTML-IM
|
||||
if(NS_XHTML_IM in features) {
|
||||
style.show();
|
||||
} else {
|
||||
// Remove the tooltip elements
|
||||
style.hide();
|
||||
style.find('.bubble-style').remove();
|
||||
|
||||
// Reset the markers
|
||||
message_area.removeAttr('style')
|
||||
.removeAttr('data-font')
|
||||
.removeAttr('data-fontsize')
|
||||
.removeAttr('data-color')
|
||||
.removeAttr('data-bold')
|
||||
.removeAttr('data-italic')
|
||||
.removeAttr('data-underline');
|
||||
}
|
||||
|
||||
// Apply Jingle
|
||||
var jingle_local_supported = JSJAC_JINGLE_AVAILABLE;
|
||||
var jingle_audio_xid = self.getFeatureResource(xid, NS_JINGLE_APPS_RTP_AUDIO);
|
||||
var jingle_video_xid = self.getFeatureResource(xid, NS_JINGLE_APPS_RTP_VIDEO);
|
||||
|
||||
if(jingle_audio_xid && jingle_local_supported) {
|
||||
jingle_audio.show();
|
||||
roster_jingle_audio.show();
|
||||
} else {
|
||||
jingle_audio.hide();
|
||||
roster_jingle_audio.hide();
|
||||
}
|
||||
|
||||
if(jingle_video_xid && jingle_local_supported) {
|
||||
jingle_video.show();
|
||||
roster_jingle_video.show();
|
||||
} else {
|
||||
jingle_video.hide();
|
||||
roster_jingle_video.hide();
|
||||
}
|
||||
|
||||
if(jingle_audio_xid && jingle_video_xid && jingle_local_supported) {
|
||||
roster_jingle_separator.show();
|
||||
} else {
|
||||
roster_jingle_separator.hide();
|
||||
}
|
||||
|
||||
if((jingle_audio_xid || jingle_video_xid) && jingle_local_supported) {
|
||||
roster_jingle_path.show();
|
||||
} else {
|
||||
roster_jingle_path.hide();
|
||||
}
|
||||
|
||||
// Apply Out of Band Data
|
||||
var iq_oob_xid = self.getFeatureResource(xid, NS_IQOOB);
|
||||
|
||||
if(iq_oob_xid || NS_XOOB in features) {
|
||||
file.show();
|
||||
|
||||
// Set a marker
|
||||
file.attr(
|
||||
'data-oob',
|
||||
iq_oob_xid ? 'iq' : 'x'
|
||||
);
|
||||
} else {
|
||||
// Remove the tooltip elements
|
||||
file.hide();
|
||||
file.find('.bubble-style').remove();
|
||||
|
||||
// Reset the marker
|
||||
file.removeAttr('data-oob');
|
||||
}
|
||||
|
||||
// Apply receipts
|
||||
if(NS_URN_RECEIPTS in features) {
|
||||
message_area.attr('data-receipts', 'true');
|
||||
} else {
|
||||
message_area.removeAttr('data-receipts');
|
||||
}
|
||||
// Apply Features
|
||||
self._applyDiscoXHTMLIM(xid, features, style_sel, message_area_sel);
|
||||
self._applyDiscoJingle(xid, path_sel, roster_sel);
|
||||
self._applyDiscoOOB(xid, features, file_sel);
|
||||
self._applyDiscoReceipts(xid, features, message_area_sel);
|
||||
self._applyDiscoCorrection(xid, features, path_sel);
|
||||
self._applyDiscoMarkers(xid, features, path_sel);
|
||||
self._applyDiscoAttention(xid, features, path_sel);
|
||||
} catch(e) {
|
||||
Console.error('Caps.displayDiscoInfos', e);
|
||||
}
|
||||
|
@ -426,40 +653,40 @@ var Caps = (function () {
|
|||
/**
|
||||
* Generates the CAPS hash
|
||||
* @public
|
||||
* @param {object} cIdentities
|
||||
* @param {object} cFeatures
|
||||
* @param {object} cDataForms
|
||||
* @param {object} identities
|
||||
* @param {object} features
|
||||
* @param {object} dataforms
|
||||
* @return {string}
|
||||
*/
|
||||
self.process = function(cIdentities, cFeatures, cDataForms) {
|
||||
self.process = function(identities, features, dataforms) {
|
||||
|
||||
try {
|
||||
// Initialize
|
||||
var cString = '';
|
||||
|
||||
var caps_str = '';
|
||||
|
||||
// Sort the arrays
|
||||
cIdentities = cIdentities.sort();
|
||||
cFeatures = cFeatures.sort();
|
||||
cDataForms = cDataForms.sort();
|
||||
|
||||
identities = identities.sort();
|
||||
features = features.sort();
|
||||
dataforms = dataforms.sort();
|
||||
|
||||
// Process the sorted identity string
|
||||
for(var a in cIdentities) {
|
||||
cString += cIdentities[a] + '<';
|
||||
for(var a in identities) {
|
||||
caps_str += identities[a] + '<';
|
||||
}
|
||||
|
||||
|
||||
// Process the sorted feature string
|
||||
for(var b in cFeatures) {
|
||||
cString += cFeatures[b] + '<';
|
||||
for(var b in features) {
|
||||
caps_str += features[b] + '<';
|
||||
}
|
||||
|
||||
|
||||
// Process the sorted data-form string
|
||||
for(var c in cDataForms) {
|
||||
cString += cDataForms[c] + '<';
|
||||
for(var c in dataforms) {
|
||||
caps_str += dataforms[c] + '<';
|
||||
}
|
||||
|
||||
|
||||
// Process the SHA-1 hash
|
||||
var cHash = b64_sha1(cString);
|
||||
|
||||
var cHash = b64_sha1(caps_str);
|
||||
|
||||
return cHash;
|
||||
} catch(e) {
|
||||
Console.error('Caps.process', e);
|
||||
|
@ -477,7 +704,12 @@ var Caps = (function () {
|
|||
|
||||
try {
|
||||
return self.process(
|
||||
['client/web//Jappix'],
|
||||
[
|
||||
self.disco_infos.identity.category + '/' +
|
||||
self.disco_infos.identity.type + '//' +
|
||||
self.disco_infos.identity.name
|
||||
],
|
||||
|
||||
self.myDiscoInfos(),
|
||||
[]
|
||||
);
|
||||
|
@ -507,8 +739,14 @@ var Caps = (function () {
|
|||
var max_priority = null;
|
||||
var cur_xid_full, cur_presence_sel, cur_caps, cur_features, cur_priority;
|
||||
|
||||
for(var cur_resource in Presence.resources(xid)) {
|
||||
cur_xid_full = xid + '/' + cur_resource;
|
||||
var resources_obj = Presence.resources(xid);
|
||||
var fn_parse_resource = function(cur_resource) {
|
||||
cur_xid_full = xid;
|
||||
|
||||
if(cur_resource) {
|
||||
cur_xid_full += '/' + cur_resource;
|
||||
}
|
||||
|
||||
cur_presence_sel = $(Presence.readStanza(cur_xid_full));
|
||||
|
||||
cur_priority = parseInt((cur_presence_sel.find('priority').text() || 0), 10);
|
||||
|
@ -523,6 +761,14 @@ var Caps = (function () {
|
|||
selected_xid = cur_xid_full;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if(resources_obj.bare === 1) {
|
||||
fn_parse_resource(null);
|
||||
}
|
||||
|
||||
for(var cur_resource in resources_obj.list) {
|
||||
fn_parse_resource(cur_resource);
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Caps.getFeatureResource', e);
|
||||
|
@ -538,4 +784,4 @@ var Caps = (function () {
|
|||
*/
|
||||
return self;
|
||||
|
||||
})();
|
||||
})();
|
||||
|
|
|
@ -22,7 +22,7 @@ var Carbons = (function () {
|
|||
|
||||
/**
|
||||
* Configures Message Carbons options
|
||||
* @public
|
||||
* @private
|
||||
* @param {string} type
|
||||
* @return {undefined}
|
||||
*/
|
||||
|
@ -35,9 +35,9 @@ var Carbons = (function () {
|
|||
|
||||
var iq = new JSJaCIQ();
|
||||
iq.setType('set');
|
||||
|
||||
|
||||
iq.appendNode(type, {'xmlns': NS_URN_CARBONS});
|
||||
|
||||
|
||||
con.send(iq, function(iq) {
|
||||
self._handleConfigure(iq, type);
|
||||
});
|
||||
|
@ -50,7 +50,7 @@ var Carbons = (function () {
|
|||
|
||||
/**
|
||||
* Configures Message Carbons options
|
||||
* @public
|
||||
* @private
|
||||
* @param {object} iq
|
||||
* @param {string} type
|
||||
* @return {undefined}
|
||||
|
@ -193,6 +193,9 @@ var Carbons = (function () {
|
|||
} else {
|
||||
Console.debug('Got a sent message from another resource to: ' + (to || 'none') + ', was ignored because body empty');
|
||||
}
|
||||
|
||||
// Handle chat markers change
|
||||
Markers.handleCarbonChange(forwarded_message);
|
||||
} else {
|
||||
Console.debug('Got a sent message from another resource to: ' + (to || 'none') + ', was ignored because chat not open');
|
||||
}
|
||||
|
|
|
@ -20,6 +20,290 @@ var Chat = (function () {
|
|||
var self = {};
|
||||
|
||||
|
||||
/**
|
||||
* Apply generate events
|
||||
* @private
|
||||
* @param {string} path
|
||||
* @param {string} id
|
||||
* @param {string} xid
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._generateEvents = function(path, id, xid) {
|
||||
|
||||
try {
|
||||
// Click event: chat cleaner
|
||||
$(path + 'tools-clear').click(function() {
|
||||
self.clean(id);
|
||||
});
|
||||
|
||||
// Click event: call (audio)
|
||||
$(path + 'tools-jingle-audio').click(function() {
|
||||
Jingle.start(xid, 'audio');
|
||||
});
|
||||
|
||||
// Click event: call (video)
|
||||
$(path + 'tools-jingle-video').click(function() {
|
||||
Jingle.start(xid, 'video');
|
||||
});
|
||||
|
||||
// Click event: user-infos
|
||||
$(path + 'tools-infos').click(function() {
|
||||
UserInfos.open(xid);
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Chat._generateEvents', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply generate events
|
||||
* @private
|
||||
* @param {object} input_sel
|
||||
* @param {string} xid
|
||||
* @param {string} hash
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._createEvents = function(input_sel, xid, hash) {
|
||||
|
||||
try {
|
||||
self._createEventsInput(input_sel, hash);
|
||||
self._createEventsKey(input_sel, xid, hash);
|
||||
self._createEventsMouse(xid, hash);
|
||||
} catch(e) {
|
||||
Console.error('Chat._createEvents', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply generate events (input)
|
||||
* @private
|
||||
* @param {object} input_sel
|
||||
* @param {string} hash
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._createEventsInput = function(input_sel, hash) {
|
||||
|
||||
try {
|
||||
input_sel.focus(function() {
|
||||
// Clean notifications for this chat
|
||||
Interface.chanCleanNotify(hash);
|
||||
|
||||
// Store focus on this chat!
|
||||
Interface.chat_focus_hash = hash;
|
||||
});
|
||||
|
||||
input_sel.blur(function() {
|
||||
// Reset storage about focus on this chat!
|
||||
if(Interface.chat_focus_hash == hash) {
|
||||
Interface.chat_focus_hash = null;
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Chat._createEventsInput', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply generate events (key)
|
||||
* @private
|
||||
* @param {object} input_sel
|
||||
* @param {string} xid
|
||||
* @param {string} hash
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._createEventsKey = function(input_sel, xid, hash) {
|
||||
|
||||
try {
|
||||
input_sel.keydown(function(e) {
|
||||
if(e.keyCode == 13) {
|
||||
// Enter key
|
||||
if(e.shiftKey || e.ctrlKey) {
|
||||
// Add a new line
|
||||
input_sel.val(input_sel.val() + '\n');
|
||||
} else {
|
||||
if(Correction.isIn(xid) === true) {
|
||||
var corrected_value = input_sel.val().trim();
|
||||
|
||||
if(corrected_value) {
|
||||
// Send the corrected message
|
||||
Correction.send(xid, 'chat', corrected_value);
|
||||
}
|
||||
|
||||
Correction.leave(xid);
|
||||
} else {
|
||||
// Send the message
|
||||
Message.send(hash, 'chat');
|
||||
}
|
||||
|
||||
// Reset the composing database entry
|
||||
DataStore.setDB(Connection.desktop_hash, 'chatstate', xid, 'off');
|
||||
}
|
||||
|
||||
return false;
|
||||
} else if(e.keyCode == 8) {
|
||||
// Leave correction mode? (another way, by flushing input value progressively)
|
||||
if(Correction.isIn(xid) === true && !input_sel.val()) {
|
||||
Correction.leave(xid);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
input_sel.keyup(function(e) {
|
||||
if(e.keyCode == 27) {
|
||||
// Escape key
|
||||
input_sel.val('');
|
||||
|
||||
// Leave correction mode? (simple escape way)
|
||||
if(Correction.isIn(xid) === true) {
|
||||
Correction.leave(xid);
|
||||
}
|
||||
} else {
|
||||
Correction.detect(xid, input_sel);
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Chat._createEventsKey', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply generate events (mouse)
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @param {string} hash
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._createEventsMouse = function(xid, hash) {
|
||||
|
||||
try {
|
||||
// Scroll in chat content
|
||||
$('#page-engine #' + hash + ' .content').scroll(function() {
|
||||
var self = this;
|
||||
|
||||
if(Features.enabledMAM() && !(xid in MAM.map_pending)) {
|
||||
var has_state = xid in MAM.map_states;
|
||||
var rsm_count = has_state ? MAM.map_states[xid].rsm.count : 1;
|
||||
var rsm_before = has_state ? MAM.map_states[xid].rsm.first : '';
|
||||
|
||||
// Request more archives?
|
||||
if(rsm_count > 0 && $(this).scrollTop() < MAM.SCROLL_THRESHOLD) {
|
||||
var was_scroll_top = $(self).scrollTop() <= 32;
|
||||
var wait_mam = $('#' + hash).find('.wait-mam');
|
||||
wait_mam.show();
|
||||
|
||||
MAM.getArchives({
|
||||
'with': xid
|
||||
}, {
|
||||
'max': MAM.REQ_MAX,
|
||||
'before': rsm_before
|
||||
}, function() {
|
||||
var wait_mam_height = was_scroll_top ? 0 : wait_mam.height();
|
||||
wait_mam.hide();
|
||||
|
||||
// Restore scroll?
|
||||
if($(self).scrollTop() < MAM.SCROLL_THRESHOLD) {
|
||||
var sel_mam_chunk = $(self).find('.mam-chunk:first');
|
||||
|
||||
var cont_padding_top = parseInt($(self).css('padding-top').replace(/[^-\d\.]/g, ''));
|
||||
var cont_one_group_margin_bottom = parseInt(sel_mam_chunk.find('.one-group:last').css('margin-bottom').replace(/[^-\d\.]/g, ''));
|
||||
var cont_mam_chunk_height = sel_mam_chunk.height();
|
||||
|
||||
$(self).scrollTop(wait_mam_height + cont_padding_top + cont_one_group_margin_bottom + cont_mam_chunk_height);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Chat._createEventsMouse', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply generate events
|
||||
* @private
|
||||
* @param {string} type
|
||||
* @param {string} id
|
||||
* @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
|
||||
* @public
|
||||
|
@ -34,38 +318,40 @@ var Chat = (function () {
|
|||
|
||||
try {
|
||||
// No XID?
|
||||
if(!xid)
|
||||
if(!xid) {
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
// We generate some stuffs
|
||||
var hash = hex_md5(xid);
|
||||
var name;
|
||||
|
||||
|
||||
// Gets the name of the user/title of the room
|
||||
if(title)
|
||||
if(title) {
|
||||
name = title;
|
||||
|
||||
else {
|
||||
} else {
|
||||
// Private groupchat chat
|
||||
if(type == 'private')
|
||||
if(type == 'private') {
|
||||
name = Common.thisResource(xid);
|
||||
|
||||
}
|
||||
|
||||
// XMPP-ID
|
||||
else if(xid.indexOf('@') != -1)
|
||||
else if(xid.indexOf('@') != -1) {
|
||||
name = Name.getBuddy(xid);
|
||||
|
||||
}
|
||||
|
||||
// Gateway
|
||||
else
|
||||
else {
|
||||
name = xid;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If the target div does not exist
|
||||
if(!Common.exists('#' + hash)) {
|
||||
// We check the type of the chat to open
|
||||
if((type == 'chat') || (type == 'private'))
|
||||
if((type == 'chat') || (type == 'private')) {
|
||||
self.create(hash, xid, name, type);
|
||||
|
||||
else if(type == 'groupchat') {
|
||||
} else if(type == 'groupchat') {
|
||||
// Try to read the room stored configuration
|
||||
if(!Utils.isAnonymous() && (!nickname || !password || !title)) {
|
||||
// Catch the room data
|
||||
|
@ -73,7 +359,7 @@ var Chat = (function () {
|
|||
var fNick = fData.find('nick').text();
|
||||
var fPwd = fData.find('password').text();
|
||||
var fName = fData.find('name').text();
|
||||
|
||||
|
||||
// Apply the room data
|
||||
if(!nickname && fNick)
|
||||
nickname = fNick;
|
||||
|
@ -82,11 +368,11 @@ var Chat = (function () {
|
|||
if(!title && fName)
|
||||
name = fName;
|
||||
}
|
||||
|
||||
|
||||
Groupchat.create(hash, xid, name, nickname, password);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Switch to the newly-created chat
|
||||
Interface.switchChan(hash);
|
||||
} catch(e) {
|
||||
|
@ -113,121 +399,53 @@ var Chat = (function () {
|
|||
// Generate some stuffs
|
||||
var path = '#' + id + ' .';
|
||||
var escaped_xid = escape(xid);
|
||||
|
||||
|
||||
// Special code
|
||||
var specialAttributes, specialAvatar, specialName, specialCode, specialLink, specialDisabled, specialStyle, specialMAM;
|
||||
|
||||
// Groupchat special code
|
||||
if(type == 'groupchat') {
|
||||
specialAttributes = ' data-type="groupchat"';
|
||||
specialAvatar = '';
|
||||
specialName = '<p class="bc-infos"><b>' + Common._e("Subject") + '</b> <span class="muc-topic">' + Common._e("no subject defined for this room.") + '</span></p>';
|
||||
specialCode = '<div class="content groupchat-content" id="chat-content-' + id + '"></div><div class="list"><div class="moderator role"><p class="title">' + Common._e("Moderators") + '</p></div><div class="participant role"><p class="title">' + Common._e("Participants") + '</p></div><div class="visitor role"><p class="title">' + Common._e("Visitors") + '</p></div><div class="none role"><p class="title">' + Common._e("Others") + '</p></div></div>';
|
||||
specialLink = '<a href="#" class="tools-mucadmin tools-tooltip talk-images chat-tools-content" title="' + Common._e("Administration panel for this room") + '"></a>';
|
||||
specialStyle = '';
|
||||
|
||||
// Is this a gateway?
|
||||
if(xid.match(/%/))
|
||||
specialDisabled = '';
|
||||
else
|
||||
specialDisabled = ' disabled=""';
|
||||
}
|
||||
|
||||
// Chat (or other things?!) special code
|
||||
else {
|
||||
specialMAM = '<div class="wait-mam wait-small"></div>';
|
||||
specialAttributes = ' data-type="chat"';
|
||||
specialAvatar = '<div class="avatar-container"><img class="avatar" src="' + './images/others/default-avatar.png' + '" alt="" /></div>';
|
||||
specialName = '<div class="bc-pep"></div><p class="bc-infos"><span class="unavailable show talk-images"></span></p>';
|
||||
specialCode = '<div class="content" id="chat-content-' + id + '">' + specialMAM + '</div>';
|
||||
specialLink = '<a href="#" class="tools-jingle-audio tools-tooltip talk-images chat-tools-content" title="' + Common._e("Call (audio only)") + '"></a>' +
|
||||
'<a href="#" class="tools-jingle-video tools-tooltip talk-images chat-tools-content" title="' + Common._e("Call (video)") + '"></a>' +
|
||||
'<a href="#" class="tools-infos tools-tooltip talk-images chat-tools-content" title="' + Common._e("Show user profile") + '"></a>';
|
||||
specialStyle = ' style="display: none;"';
|
||||
specialDisabled = '';
|
||||
}
|
||||
|
||||
// Not a groupchat private chat, we can use the buddy add icon
|
||||
if((type == 'chat') || (type == 'groupchat')) {
|
||||
var addTitle;
|
||||
|
||||
if(type == 'chat')
|
||||
addTitle = Common._e("Add this contact to your friends");
|
||||
else
|
||||
addTitle = Common._e("Add this groupchat to your favorites");
|
||||
|
||||
specialLink += '<a href="#" class="tools-add tools-tooltip talk-images chat-tools-content" title="' + addTitle + '"></a>';
|
||||
}
|
||||
|
||||
// IE DOM parsing bug fix
|
||||
var specialStylePicker = '<div class="chat-tools-content chat-tools-style"' + specialStyle + '>' +
|
||||
'<a href="#" class="tools-style tools-tooltip talk-images"></a>' +
|
||||
'</div>';
|
||||
|
||||
if((BrowserDetect.browser == 'Explorer') && (BrowserDetect.version < 9))
|
||||
specialStylePicker = '';
|
||||
|
||||
var chat_args = self._generateChatCode(type, id, xid);
|
||||
|
||||
// Append the chat HTML code
|
||||
$('#page-engine').append(
|
||||
'<div id="' + id + '" class="page-engine-chan chat one-counter"' + specialAttributes + ' data-xid="' + escaped_xid + '">' +
|
||||
'<div class="top ' + id + '">' +
|
||||
specialAvatar +
|
||||
|
||||
'<div class="name">' +
|
||||
'<p class="bc-name bc-name-nick">' + nick.htmlEnc() + '</p>' +
|
||||
specialName +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
specialCode +
|
||||
|
||||
'<div class="text">' +
|
||||
'<div class="footer">' +
|
||||
'<div class="chat-tools-content chat-tools-smileys">' +
|
||||
'<a href="#" class="tools-smileys tools-tooltip talk-images"></a>' +
|
||||
'</div>' +
|
||||
|
||||
specialStylePicker +
|
||||
|
||||
'<div class="chat-tools-content chat-tools-file">' +
|
||||
'<a href="#" class="tools-file tools-tooltip talk-images"></a>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="chat-tools-content chat-tools-save">' +
|
||||
'<a href="#" class="tools-save tools-tooltip talk-images"></a>' +
|
||||
'</div>' +
|
||||
|
||||
'<a href="#" class="tools-clear tools-tooltip talk-images chat-tools-content" title="' + Common._e("Clean current chat") + '"></a>' +
|
||||
|
||||
specialLink +
|
||||
'</div>' +
|
||||
|
||||
'<div class="compose">' +
|
||||
'<textarea class="message-area focusable" ' + specialDisabled + ' data-to="' + escaped_xid + '" /></textarea>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'<div id="' + id + '" class="page-engine-chan chat one-counter"' + chat_args.attributes + ' data-xid="' + escaped_xid + '">' +
|
||||
'<div class="top ' + id + '">' +
|
||||
chat_args.avatar +
|
||||
|
||||
'<div class="name">' +
|
||||
'<p class="bc-name bc-name-nick">' + nick.htmlEnc() + '</p>' +
|
||||
chat_args.name +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
chat_args.code +
|
||||
|
||||
'<div class="text">' +
|
||||
'<div class="footer">' +
|
||||
'<div class="chat-tools-content chat-tools-smileys">' +
|
||||
'<a href="#" class="tools-smileys tools-tooltip talk-images"></a>' +
|
||||
'</div>' +
|
||||
|
||||
chat_args.style_picker +
|
||||
|
||||
'<div class="chat-tools-content chat-tools-file">' +
|
||||
'<a href="#" class="tools-file tools-tooltip talk-images"></a>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="chat-tools-content chat-tools-save">' +
|
||||
'<a href="#" class="tools-save tools-tooltip talk-images"></a>' +
|
||||
'</div>' +
|
||||
|
||||
'<a href="#" class="tools-clear tools-tooltip talk-images chat-tools-content" title="' + Common._e("Clean current chat") + '"></a>' +
|
||||
|
||||
chat_args.link +
|
||||
'</div>' +
|
||||
|
||||
'<div class="compose">' +
|
||||
'<textarea class="message-area focusable" ' + chat_args.disabled + ' data-to="' + escaped_xid + '" /></textarea>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>'
|
||||
);
|
||||
|
||||
// Click event: chat cleaner
|
||||
$(path + 'tools-clear').click(function() {
|
||||
self.clean(id);
|
||||
});
|
||||
|
||||
// Click event: call (audio)
|
||||
$(path + 'tools-jingle-audio').click(function() {
|
||||
Jingle.start(xid, 'audio');
|
||||
});
|
||||
|
||||
// Click event: call (video)
|
||||
$(path + 'tools-jingle-video').click(function() {
|
||||
Jingle.start(xid, 'video');
|
||||
});
|
||||
|
||||
// Click event: user-infos
|
||||
$(path + 'tools-infos').click(function() {
|
||||
UserInfos.open(xid);
|
||||
});
|
||||
self._generateEvents(path, id, xid);
|
||||
} catch(e) {
|
||||
Console.error('Chat.generate', e);
|
||||
}
|
||||
|
@ -249,32 +467,38 @@ var Chat = (function () {
|
|||
try {
|
||||
// Path to the element
|
||||
var chat_switch = '#page-switch .';
|
||||
|
||||
|
||||
// Special code
|
||||
var specialClass = ' unavailable';
|
||||
var special_class = ' unavailable';
|
||||
var show_close = true;
|
||||
|
||||
|
||||
// Groupchat
|
||||
if(type == 'groupchat') {
|
||||
specialClass = ' groupchat-default';
|
||||
|
||||
if(Utils.isAnonymous() && (xid == Common.generateXID(ANONYMOUS_ROOM, 'groupchat')))
|
||||
special_class = ' groupchat-default';
|
||||
|
||||
if(Utils.isAnonymous() && (xid == Common.generateXID(ANONYMOUS_ROOM, 'groupchat'))) {
|
||||
show_close = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Generate the HTML code
|
||||
var html = '<div class="' + id + ' switcher chan" onclick="return Interface.switchChan(\'' + Utils.encodeOnclick(id) + '\')">' +
|
||||
'<div class="icon talk-images' + specialClass + '"></div>' +
|
||||
|
||||
'<div class="name">' + nick.htmlEnc() + '</div>';
|
||||
|
||||
var html = '<div class="' + id + ' switcher chan" onclick="return Interface.switchChan(\'' + Utils.encodeOnclick(id) + '\')">' +
|
||||
'<div class="icon talk-images' + special_class + '"></div>' +
|
||||
|
||||
'<div class="name">' + nick.htmlEnc() + '</div>';
|
||||
|
||||
// Show the close button if not MUC and not anonymous
|
||||
if(show_close)
|
||||
html += '<div class="exit" title="' + Common._e("Close this tab") + '" onclick="return Interface.quitThisChat(\'' + Utils.encodeOnclick(xid) + '\', \'' + Utils.encodeOnclick(id) + '\', \'' + Utils.encodeOnclick(type) + '\');">x</div>';
|
||||
|
||||
if(show_close) {
|
||||
html += '<div class="exit" ' +
|
||||
'title="' + Common._e("Close this tab") + '" ' +
|
||||
'onclick="return Interface.quitThisChat(\'' + Utils.encodeOnclick(xid) + '\', \'' + Utils.encodeOnclick(id) + '\', \'' + Utils.encodeOnclick(type) + '\');">' +
|
||||
'x' +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
// Close the HTML
|
||||
html += '</div>';
|
||||
|
||||
|
||||
// Append the HTML code
|
||||
$(chat_switch + 'chans, ' + chat_switch + 'more-content').append(html);
|
||||
} catch(e) {
|
||||
|
@ -295,10 +519,10 @@ var Chat = (function () {
|
|||
try {
|
||||
// Remove the messages
|
||||
$('#page-engine #' + chat + ' .content .one-group').remove();
|
||||
|
||||
|
||||
// Clear the history database
|
||||
Message.removeLocalArchive(chat);
|
||||
|
||||
|
||||
// Focus again
|
||||
$(document).oneTime(10, function() {
|
||||
$('#page-engine #' + chat + ' .text .message-area').focus();
|
||||
|
@ -346,14 +570,14 @@ var Chat = (function () {
|
|||
|
||||
try {
|
||||
Console.info('New chat: ' + xid);
|
||||
|
||||
|
||||
// Create the chat content
|
||||
self.generate(type, hash, xid, nick);
|
||||
|
||||
|
||||
// Create the chat switcher
|
||||
self.generateSwitch(type, hash, xid, nick);
|
||||
|
||||
// If the user is not in our roster
|
||||
|
||||
// Is this a chat?
|
||||
if(type == 'chat') {
|
||||
// MAM? Get archives from there!
|
||||
if(Features.enabledMAM()) {
|
||||
|
@ -366,130 +590,73 @@ var Chat = (function () {
|
|||
} else {
|
||||
// Restore the chat history
|
||||
var chat_history = Message.readLocalArchive(hash);
|
||||
|
||||
|
||||
if(chat_history) {
|
||||
// Generate hashs
|
||||
var my_hash = hex_md5(Common.getXID());
|
||||
var friend_hash = hex_md5(xid);
|
||||
|
||||
|
||||
// Add chat history HTML
|
||||
$('#' + hash + ' .content').append(chat_history);
|
||||
|
||||
var path_sel = $('#' + hash);
|
||||
|
||||
path_sel.find('.content').append(chat_history);
|
||||
|
||||
// Filter old groups & messages
|
||||
$('#' + hash + ' .one-group[data-type="user-message"]').addClass('from-history').attr('data-type', 'old-message');
|
||||
$('#' + hash + ' .user-message').removeClass('user-message').addClass('old-message');
|
||||
|
||||
var one_group_sel = path_sel.find('.one-group');
|
||||
one_group_sel.filter('[data-type="user-message"]').addClass('from-history').attr('data-type', 'old-message');
|
||||
path_sel.find('.user-message').removeClass('user-message').addClass('old-message');
|
||||
|
||||
// Regenerate user names
|
||||
$('#' + hash + ' .one-group.' + my_hash + ' b.name').text(Name.getBuddy(Common.getXID()));
|
||||
$('#' + hash + ' .one-group.' + friend_hash + ' b.name').text(Name.getBuddy(xid));
|
||||
|
||||
one_group_sel.filter('.' + my_hash + ' b.name').text(
|
||||
Name.getBuddy(Common.getXID())
|
||||
);
|
||||
|
||||
one_group_sel.filter('.' + friend_hash + ' b.name').text(
|
||||
Name.getBuddy(xid)
|
||||
);
|
||||
|
||||
// Regenerate group dates
|
||||
$('#' + hash + ' .one-group').each(function() {
|
||||
var current_stamp = parseInt($(this).attr('data-stamp'));
|
||||
one_group_sel.each(function() {
|
||||
var current_stamp = parseInt($(this).attr('data-stamp'), 10);
|
||||
$(this).find('span.date').text(DateUtils.relative(current_stamp));
|
||||
});
|
||||
|
||||
|
||||
// Regenerate avatars
|
||||
if(Common.exists('#' + hash + ' .one-group.' + my_hash + ' .avatar-container'))
|
||||
if(Common.exists('#' + hash + ' .one-group.' + my_hash + ' .avatar-container')) {
|
||||
Avatar.get(Common.getXID(), 'cache', 'true', 'forget');
|
||||
if(Common.exists('#' + hash + ' .one-group.' + friend_hash + ' .avatar-container'))
|
||||
}
|
||||
|
||||
if(Common.exists('#' + hash + ' .one-group.' + friend_hash + ' .avatar-container')) {
|
||||
Avatar.get(xid, 'cache', 'true', 'forget');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add button
|
||||
if(!Roster.isFriend(xid))
|
||||
if(!Roster.isFriend(xid)) {
|
||||
$('#' + hash + ' .tools-add').click(function() {
|
||||
// Hide the icon (to tell the user all is okay)
|
||||
$(this).hide();
|
||||
|
||||
|
||||
// Send the subscribe request
|
||||
Roster.addThisContact(xid, nick);
|
||||
}).show();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// We catch the user's informations (like this avatar, vcard, and so on...)
|
||||
UserInfos.get(hash, xid, nick, type);
|
||||
|
||||
|
||||
// The icons-hover functions
|
||||
Tooltip.icons(xid, hash);
|
||||
|
||||
|
||||
// The event handlers
|
||||
var inputDetect = $('#page-engine #' + hash + ' .message-area');
|
||||
|
||||
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;
|
||||
}
|
||||
});
|
||||
var input_sel = $('#page-engine #' + hash + ' .message-area');
|
||||
self._createEvents(input_sel, xid, hash);
|
||||
|
||||
// Scroll in chat content
|
||||
$('#page-engine #' + hash + ' .content').scroll(function() {
|
||||
var self = this;
|
||||
|
||||
if(Features.enabledMAM() && !(xid in MAM.map_pending)) {
|
||||
var has_state = xid in MAM.map_states;
|
||||
var rsm_count = has_state ? MAM.map_states[xid].rsm.count : 1;
|
||||
var rsm_before = has_state ? MAM.map_states[xid].rsm.first : '';
|
||||
|
||||
// Request more archives?
|
||||
if(rsm_count > 0 && $(this).scrollTop() < MAM.SCROLL_THRESHOLD) {
|
||||
var was_scroll_top = $(self).scrollTop() <= 32;
|
||||
var wait_mam = $('#' + hash).find('.wait-mam');
|
||||
wait_mam.show();
|
||||
|
||||
MAM.getArchives({
|
||||
'with': xid
|
||||
}, {
|
||||
'max': MAM.REQ_MAX,
|
||||
'before': rsm_before
|
||||
}, function() {
|
||||
var wait_mam_height = was_scroll_top ? 0 : wait_mam.height();
|
||||
wait_mam.hide();
|
||||
|
||||
// Restore scroll?
|
||||
if($(self).scrollTop() < MAM.SCROLL_THRESHOLD) {
|
||||
var sel_mam_chunk = $(self).find('.mam-chunk:first');
|
||||
|
||||
var cont_padding_top = parseInt($(self).css('padding-top').replace(/[^-\d\.]/g, ''));
|
||||
var cont_one_group_margin_bottom = parseInt(sel_mam_chunk.find('.one-group:last').css('margin-bottom').replace(/[^-\d\.]/g, ''));
|
||||
var cont_mam_chunk_height = sel_mam_chunk.height();
|
||||
|
||||
$(self).scrollTop(wait_mam_height + cont_padding_top + cont_one_group_margin_bottom + cont_mam_chunk_height);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Chatstate events
|
||||
ChatState.events(inputDetect, xid, hash, 'chat');
|
||||
// Input events
|
||||
ChatState.events(input_sel, xid, hash, 'chat');
|
||||
Markers.events(input_sel, xid, hash, 'chat');
|
||||
} catch(e) {
|
||||
Console.error('Chat.create', e);
|
||||
}
|
||||
|
@ -502,4 +669,4 @@ var Chat = (function () {
|
|||
*/
|
||||
return self;
|
||||
|
||||
})();
|
||||
})();
|
||||
|
|
|
@ -32,24 +32,27 @@ var ChatState = (function () {
|
|||
|
||||
try {
|
||||
var user_type = $('#' + hash).attr('data-type');
|
||||
|
||||
|
||||
// If the friend client supports chatstates and is online
|
||||
if((user_type == 'groupchat') || ((user_type == 'chat') && $('#' + hash + ' .message-area').attr('data-chatstates') && !Common.exists('#page-switch .' + hash + ' .unavailable'))) {
|
||||
// Already sent?
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'currentchatstate', xid) == state)
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'currentchatstate', xid) == state) {
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// Write the state
|
||||
DataStore.setDB(Connection.desktop_hash, 'currentchatstate', xid, state);
|
||||
|
||||
|
||||
// New message stanza
|
||||
var aMsg = new JSJaCMessage();
|
||||
aMsg.setTo(xid);
|
||||
aMsg.setType(user_type);
|
||||
|
||||
|
||||
// Append the chatstate node
|
||||
aMsg.appendNode(state, {'xmlns': NS_CHATSTATES});
|
||||
|
||||
aMsg.appendNode(state, {
|
||||
'xmlns': NS_CHATSTATES
|
||||
});
|
||||
|
||||
// Send this!
|
||||
con.send(aMsg);
|
||||
}
|
||||
|
@ -74,58 +77,61 @@ var ChatState = (function () {
|
|||
// Groupchat?
|
||||
if(type == 'groupchat') {
|
||||
self.reset(hash, type);
|
||||
|
||||
|
||||
// "gone" state not allowed
|
||||
if(state != 'gone')
|
||||
if(state != 'gone') {
|
||||
$('#page-engine .page-engine-chan .user.' + hash).addClass(state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Chat
|
||||
else {
|
||||
// We change the buddy name color in the page-switch
|
||||
self.reset(hash, type);
|
||||
$('#page-switch .' + hash + ' .name').addClass(state);
|
||||
|
||||
|
||||
// We generate the chatstate text
|
||||
var text = '';
|
||||
|
||||
|
||||
switch(state) {
|
||||
// Active
|
||||
case 'active':
|
||||
text = Common._e("Your friend is paying attention to the conversation.");
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
// Composing
|
||||
case 'composing':
|
||||
text = Common._e("Your friend is writing a message...");
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
// Paused
|
||||
case 'paused':
|
||||
text = Common._e("Your friend stopped writing a message.");
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
// Inactive
|
||||
case 'inactive':
|
||||
text = Common._e("Your friend is doing something else.");
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
// Gone
|
||||
case 'gone':
|
||||
text = Common._e("Your friend closed the chat.");
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// We reset the previous state
|
||||
$('#' + hash + ' .chatstate').remove();
|
||||
|
||||
|
||||
// We create the chatstate
|
||||
$('#' + hash + ' .content').after('<div class="' + state + ' chatstate">' + text + '</div>');
|
||||
$('#' + hash + ' .content').after(
|
||||
'<div class="' + state + ' chatstate">' + text + '</div>'
|
||||
);
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('ChatState.display', e);
|
||||
|
@ -146,12 +152,13 @@ var ChatState = (function () {
|
|||
try {
|
||||
// Define the selector
|
||||
var selector;
|
||||
|
||||
if(type == 'groupchat')
|
||||
|
||||
if(type == 'groupchat') {
|
||||
selector = $('#page-engine .page-engine-chan .user.' + hash);
|
||||
else
|
||||
} else {
|
||||
selector = $('#page-switch .' + hash + ' .name');
|
||||
|
||||
}
|
||||
|
||||
// Reset!
|
||||
selector.removeClass('active composing paused inactive gone');
|
||||
} catch(e) {
|
||||
|
@ -179,53 +186,56 @@ var ChatState = (function () {
|
|||
if($(this).val() && (DataStore.getDB(Connection.desktop_hash, 'chatstate', xid) != 'on')) {
|
||||
// We change the state detect input
|
||||
DataStore.setDB(Connection.desktop_hash, 'chatstate', xid, 'on');
|
||||
|
||||
|
||||
// We send the friend a "composing" chatstate
|
||||
self.send('composing', xid, hash);
|
||||
}
|
||||
|
||||
|
||||
// Flushed the message which was being composed
|
||||
else if(!$(this).val() && (DataStore.getDB(Connection.desktop_hash, 'chatstate', xid) == 'on')) {
|
||||
// We change the state detect input
|
||||
DataStore.setDB(Connection.desktop_hash, 'chatstate', xid, 'off');
|
||||
|
||||
|
||||
// We send the friend an "active" chatstate
|
||||
self.send('active', xid, hash);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
target.change(function() {
|
||||
// Reset the composing database entry
|
||||
DataStore.setDB(Connection.desktop_hash, 'chatstate', xid, 'off');
|
||||
});
|
||||
|
||||
|
||||
target.focus(function() {
|
||||
// Not needed
|
||||
if(target.is(':disabled'))
|
||||
if(target.is(':disabled')) {
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// Something was written, user started writing again
|
||||
if($(this).val())
|
||||
if($(this).val()) {
|
||||
self.send('composing', xid, hash);
|
||||
}
|
||||
|
||||
// Chat only: Nothing in the input, user is active
|
||||
else if(type == 'chat')
|
||||
else if(type == 'chat') {
|
||||
self.send('active', xid, hash);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
target.blur(function() {
|
||||
// Not needed
|
||||
if(target.is(':disabled'))
|
||||
if(target.is(':disabled')) {
|
||||
return;
|
||||
|
||||
// Something was written, user paused
|
||||
if($(this).val())
|
||||
self.send('paused', xid, hash);
|
||||
}
|
||||
|
||||
// Chat only: Nothing in the input, user is inactive
|
||||
else if(type == 'chat')
|
||||
// Something was written, user paused
|
||||
if($(this).val()) {
|
||||
self.send('paused', xid, hash);
|
||||
} else if(type == 'chat') {
|
||||
self.send('inactive', xid, hash);
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('ChatState.events', e);
|
||||
|
|
|
@ -20,6 +20,10 @@ var Common = (function () {
|
|||
var self = {};
|
||||
|
||||
|
||||
/* Constants */
|
||||
self.R_DOMAIN_NAME = /^(([a-zA-Z0-9-\.]+)\.)?[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9]\.[a-zA-Z]{2,}$/i;
|
||||
|
||||
|
||||
/**
|
||||
* Checks if an element exists in the DOM
|
||||
* @public
|
||||
|
@ -109,6 +113,29 @@ var Common = (function () {
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* Matches a domain name
|
||||
* @public
|
||||
* @param {string} xid
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.isDomain = function(xid) {
|
||||
|
||||
is_domain = false;
|
||||
|
||||
try {
|
||||
if(xid.match(self.R_DOMAIN_NAME)) {
|
||||
is_domain = true;
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Common.isDomain', e);
|
||||
} finally {
|
||||
return is_domain;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Generates the good XID
|
||||
* @public
|
||||
|
@ -120,22 +147,23 @@ var Common = (function () {
|
|||
|
||||
try {
|
||||
// XID needs to be transformed
|
||||
// .. and made lowercase (uncertain though this is the right place...)
|
||||
xid = xid.toLowerCase();
|
||||
|
||||
if(xid && (xid.indexOf('@') == -1)) {
|
||||
// Groupchat
|
||||
if(type == 'groupchat')
|
||||
if(xid && (xid.indexOf('@') === -1)) {
|
||||
// Groupchat XID
|
||||
if(type == 'groupchat') {
|
||||
return xid + '@' + HOST_MUC;
|
||||
|
||||
// One-to-one chat
|
||||
if(xid.indexOf('.') == -1)
|
||||
return xid + '@' + HOST_MAIN;
|
||||
|
||||
// It might be a gateway?
|
||||
return xid;
|
||||
}
|
||||
|
||||
// Gateway XID
|
||||
if(self.isDomain(xid) === true) {
|
||||
return xid;
|
||||
}
|
||||
|
||||
// User XID
|
||||
return xid + '@' + HOST_MAIN;
|
||||
}
|
||||
|
||||
|
||||
// Nothing special (yet bare XID)
|
||||
return xid;
|
||||
} catch(e) {
|
||||
|
@ -190,15 +218,17 @@ var Common = (function () {
|
|||
self.strAfterLast = function(given_char, str) {
|
||||
|
||||
try {
|
||||
if(!given_char || !str)
|
||||
if(!given_char || !str) {
|
||||
return '';
|
||||
|
||||
}
|
||||
|
||||
var char_index = str.lastIndexOf(given_char);
|
||||
var str_return = str;
|
||||
|
||||
if(char_index >= 0)
|
||||
|
||||
if(char_index >= 0) {
|
||||
str_return = str.substr(char_index + 1);
|
||||
|
||||
}
|
||||
|
||||
return str_return;
|
||||
} catch(e) {
|
||||
Console.error('Common.strAfterLast', e);
|
||||
|
@ -220,15 +250,16 @@ var Common = (function () {
|
|||
try {
|
||||
// Get the index of our char to explode
|
||||
var index = toStr.indexOf(toEx);
|
||||
|
||||
|
||||
// We split if necessary the string
|
||||
if(index !== -1) {
|
||||
if(i === 0)
|
||||
if(i === 0) {
|
||||
toStr = toStr.substr(0, index);
|
||||
else
|
||||
} else {
|
||||
toStr = toStr.substr(index + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// We return the value
|
||||
return toStr;
|
||||
} catch(e) {
|
||||
|
@ -309,8 +340,9 @@ var Common = (function () {
|
|||
// Spec: http://tools.ietf.org/html/rfc6122#appendix-A
|
||||
|
||||
try {
|
||||
if(!node)
|
||||
if(!node) {
|
||||
return node;
|
||||
}
|
||||
|
||||
// Remove prohibited chars
|
||||
var prohibited_chars = ['"', '&', '\'', '/', ':', '<', '>', '@'];
|
||||
|
@ -347,6 +379,40 @@ var Common = (function () {
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* Escapes quotes in a string
|
||||
* @public
|
||||
* @param {string} str
|
||||
* @return {string}
|
||||
*/
|
||||
self.escapeQuotes = function(str) {
|
||||
|
||||
try {
|
||||
return escape(self.encodeQuotes(str));
|
||||
} catch(e) {
|
||||
Console.error('Common.escapeQuotes', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Unescapes quotes in a string
|
||||
* @public
|
||||
* @param {string} str
|
||||
* @return {string}
|
||||
*/
|
||||
self.unescapeQuotes = function(str) {
|
||||
|
||||
try {
|
||||
return unescape(str);
|
||||
} catch(e) {
|
||||
Console.error('Common.unescapeQuotes', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gets the bare XID from a XID
|
||||
* @public
|
||||
|
@ -358,12 +424,12 @@ var Common = (function () {
|
|||
try {
|
||||
// Cut the resource
|
||||
xid = self.cutResource(xid);
|
||||
|
||||
|
||||
// Launch nodeprep
|
||||
if(xid.indexOf('@') != -1) {
|
||||
xid = self.nodeprep(self.getXIDNick(xid)) + '@' + self.getXIDHost(xid);
|
||||
if(xid.indexOf('@') !== -1) {
|
||||
xid = self.nodeprep(self.getXIDNick(xid, true)) + '@' + self.getXIDHost(xid);
|
||||
}
|
||||
|
||||
|
||||
return xid;
|
||||
} catch(e) {
|
||||
Console.error('Common.bareXID', e);
|
||||
|
@ -384,11 +450,12 @@ var Common = (function () {
|
|||
// Normalizes the XID
|
||||
var full = self.bareXID(xid);
|
||||
var resource = self.thisResource(xid);
|
||||
|
||||
|
||||
// Any resource?
|
||||
if(resource)
|
||||
if(resource) {
|
||||
full += '/' + resource;
|
||||
|
||||
}
|
||||
|
||||
return full;
|
||||
} catch(e) {
|
||||
Console.error('Common.fullXID', e);
|
||||
|
@ -401,15 +468,19 @@ var Common = (function () {
|
|||
* Gets the nick from a XID
|
||||
* @public
|
||||
* @param {string} aXID
|
||||
* @param {boolean} raw_explode
|
||||
* @return {string}
|
||||
*/
|
||||
self.getXIDNick = function(aXID) {
|
||||
self.getXIDNick = function(aXID, raw_explode) {
|
||||
|
||||
try {
|
||||
// Gateway nick?
|
||||
if(aXID.match(/\\40/))
|
||||
return self.explodeThis('\\40', aXID, 0);
|
||||
|
||||
if(raw_explode !== true) {
|
||||
// Gateway nick?
|
||||
if(aXID.match(/\\40/)) {
|
||||
return self.explodeThis('\\40', aXID, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return self.explodeThis('@', aXID, 0);
|
||||
} catch(e) {
|
||||
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
|
||||
* @return {string}
|
||||
*/
|
||||
|
@ -495,7 +566,7 @@ var Common = (function () {
|
|||
if(con.username && con.domain) {
|
||||
return con.username + '@' + con.domain;
|
||||
}
|
||||
|
||||
|
||||
return '';
|
||||
} catch(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
|
||||
* @public
|
||||
|
@ -521,15 +615,15 @@ var Common = (function () {
|
|||
'00236b',
|
||||
'4e005c'
|
||||
);
|
||||
|
||||
|
||||
var number = 0;
|
||||
|
||||
|
||||
for(var i = 0; i < xid.length; i++) {
|
||||
number += xid.charCodeAt(i);
|
||||
}
|
||||
|
||||
|
||||
var color = '#' + colors[number % (colors.length)];
|
||||
|
||||
|
||||
return color;
|
||||
} catch(e) {
|
||||
Console.error('Common.generateColor', e);
|
||||
|
@ -549,7 +643,7 @@ var Common = (function () {
|
|||
is_gateway = true;
|
||||
|
||||
try {
|
||||
if(xid.indexOf('@') != -1) {
|
||||
if(xid.indexOf('@') !== -1) {
|
||||
is_gateway = false;
|
||||
}
|
||||
} catch(e) {
|
||||
|
@ -571,12 +665,12 @@ var Common = (function () {
|
|||
|
||||
try {
|
||||
var from = stanza.getFrom();
|
||||
|
||||
|
||||
// No from, we assume this is our XID
|
||||
if(!from) {
|
||||
from = self.getXID();
|
||||
}
|
||||
|
||||
|
||||
return from;
|
||||
} catch(e) {
|
||||
Console.error('Common.getStanzaFrom', e);
|
||||
|
@ -618,13 +712,15 @@ var Common = (function () {
|
|||
|
||||
try {
|
||||
// Negative number (without first 0)
|
||||
if(i > -10 && i < 0)
|
||||
if(i > -10 && i < 0) {
|
||||
return '-0' + (i * -1);
|
||||
|
||||
}
|
||||
|
||||
// Positive number (without first 0)
|
||||
if(i < 10 && i >= 0)
|
||||
if(i < 10 && i >= 0) {
|
||||
return '0' + i;
|
||||
|
||||
}
|
||||
|
||||
// All is okay
|
||||
return i;
|
||||
} catch(e) {
|
||||
|
@ -643,23 +739,31 @@ var Common = (function () {
|
|||
*/
|
||||
self.escapeRegex = function(query) {
|
||||
|
||||
if (query instanceof Array) {
|
||||
var result = new Array(query.length);
|
||||
for(i=0; i<query.length; i++) {
|
||||
var result = [];
|
||||
|
||||
try {
|
||||
if(query instanceof Array) {
|
||||
result = [query.length];
|
||||
|
||||
for(i = 0; i < query.length; i++) {
|
||||
try {
|
||||
result[i] = Common.escapeRegex(query[i]);
|
||||
} catch(e) {
|
||||
Console.error('Common.escapeRegex', e);
|
||||
result[i] = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
result[i] = Common.escapeRegex(query[i]);
|
||||
result = query.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
|
||||
} catch(e) {
|
||||
Console.error('Common.escapeRegex', e);
|
||||
result[i] = null;
|
||||
Console.error('Common.escapeRegex[inner]', e);
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Common.escapeRegex', e);
|
||||
} finally {
|
||||
return result;
|
||||
} else {
|
||||
try {
|
||||
return query.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
|
||||
} catch(e) {
|
||||
Console.error('Common.escapeRegex', e);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -717,7 +821,7 @@ var Common = (function () {
|
|||
if(window.XMLSerializer) {
|
||||
xml_str = (new XMLSerializer()).serializeToString(xmlData);
|
||||
}
|
||||
|
||||
|
||||
// For Internet Explorer
|
||||
if(window.ActiveXObject) {
|
||||
xml_str = xmlData.xml;
|
||||
|
@ -744,21 +848,21 @@ var Common = (function () {
|
|||
if(!sXML) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
// Add the XML tag
|
||||
if(!sXML.match(/^<\?xml/i)) {
|
||||
sXML = '<?xml version="1.0"?>' + sXML;
|
||||
}
|
||||
|
||||
|
||||
// Parse it!
|
||||
if(window.DOMParser) {
|
||||
return (new DOMParser()).parseFromString(sXML, 'text/xml');
|
||||
}
|
||||
|
||||
|
||||
if(window.ActiveXObject) {
|
||||
var oXML = new ActiveXObject('Microsoft.XMLDOM');
|
||||
oXML.loadXML(sXML);
|
||||
|
||||
|
||||
return oXML;
|
||||
}
|
||||
} catch(e) {
|
||||
|
@ -780,7 +884,7 @@ var Common = (function () {
|
|||
|
||||
try {
|
||||
var timer = 0;
|
||||
|
||||
|
||||
return function(callback, ms) {
|
||||
clearTimeout(timer);
|
||||
timer = setTimeout(callback, ms);
|
||||
|
@ -799,4 +903,4 @@ var Common = (function () {
|
|||
|
||||
})();
|
||||
|
||||
var JappixCommon = Common;
|
||||
var JappixCommon = Common;
|
||||
|
|
|
@ -29,6 +29,205 @@ var Connection = (function () {
|
|||
self.resume = false;
|
||||
|
||||
|
||||
/**
|
||||
* Do registration on Register API
|
||||
* @private
|
||||
* @param {string} username
|
||||
* @param {string} domain
|
||||
* @param {string} pass
|
||||
* @param {string} captcha
|
||||
* @return {boolean}
|
||||
*/
|
||||
self._doRegisterAPI = function(username, domain, pass, captcha) {
|
||||
|
||||
var is_success = false;
|
||||
|
||||
try {
|
||||
// Show the waiting image
|
||||
Interface.showGeneralWait();
|
||||
|
||||
// Change the page title
|
||||
Interface.title('wait');
|
||||
|
||||
// Send request
|
||||
$.post('./server/register.php', {username: username, domain: domain, password: pass, captcha: captcha}, function(data) {
|
||||
// Error registering
|
||||
Interface.removeGeneralWait();
|
||||
Interface.title('home');
|
||||
|
||||
// In all case, update CAPTCHA
|
||||
$('#home img.captcha_img').attr('src', './server/captcha.php?id=' + genID());
|
||||
$('#home input.captcha').val('');
|
||||
|
||||
// Registration okay
|
||||
if($(data).find('query status').text() == '1') {
|
||||
is_success = true;
|
||||
self.handleRegistered();
|
||||
} else {
|
||||
// Show error message
|
||||
var error_message = '';
|
||||
|
||||
switch($(data).find('query message').text()) {
|
||||
case 'CAPTCHA Not Matching':
|
||||
error_message = Common._e("The security code you entered is invalid. Please retry with another one.");
|
||||
|
||||
$('#home input.captcha').focus();
|
||||
|
||||
break;
|
||||
|
||||
case 'Username Unavailable':
|
||||
error_message = Common._e("The username you picked is not available. Please try another one.");
|
||||
|
||||
$('#home input.nick').focus();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
error_message = Common._e("There was an error registering your account. Please retry.");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(error_message) {
|
||||
Errors.show('', error_message, '');
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Connection._doRegisterAPI', e);
|
||||
} finally {
|
||||
return is_success;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Do registration throug in-band stream
|
||||
* @private
|
||||
* @param {string} username
|
||||
* @param {string} domain
|
||||
* @param {string} pass
|
||||
* @return {boolean}
|
||||
*/
|
||||
self._doRegisterInBand = function(username, domain, pass) {
|
||||
|
||||
var is_success = true;
|
||||
|
||||
try {
|
||||
if(Common.hasWebSocket()) {
|
||||
// WebSocket supported & configured
|
||||
con = new JSJaCWebSocketConnection({
|
||||
httpbase: HOST_WEBSOCKET
|
||||
});
|
||||
} else {
|
||||
var httpbase = (HOST_BOSH_MAIN || HOST_BOSH);
|
||||
|
||||
// Check BOSH origin
|
||||
BOSH_SAME_ORIGIN = Origin.isSame(httpbase);
|
||||
|
||||
// We create the new http-binding connection
|
||||
con = new JSJaCHttpBindingConnection({
|
||||
httpbase: httpbase
|
||||
});
|
||||
}
|
||||
|
||||
// We setup the connection !
|
||||
con.registerHandler('onconnect', self.handleRegistered);
|
||||
con.registerHandler('onerror', Errors.handle);
|
||||
|
||||
con.connect({
|
||||
'domain': $.trim(domain),
|
||||
'username': $.trim(username),
|
||||
'resource': JAPPIX_RESOURCE + ' Register (' + (new Date()).getTime() + ')',
|
||||
'pass': pass,
|
||||
'register': true,
|
||||
'secure': true,
|
||||
'xmllang': XML_LANG
|
||||
});
|
||||
|
||||
// Show the waiting image
|
||||
Interface.showGeneralWait();
|
||||
|
||||
// Change the page title
|
||||
Interface.title('wait');
|
||||
} catch(e) {
|
||||
Console.error('Connection._doRegisterInBand', e);
|
||||
is_success = false;
|
||||
} finally {
|
||||
return is_success;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Attaches reconnect events
|
||||
* @private
|
||||
* @param {string} mode
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._eventsReconnect = function(mode) {
|
||||
|
||||
try {
|
||||
// Click events
|
||||
if(mode == 'normal') {
|
||||
$('#reconnect a.finish.cancel').click(function() {
|
||||
return self.cancelReconnect();
|
||||
});
|
||||
}
|
||||
|
||||
$('#reconnect a.finish.reconnect').click(function() {
|
||||
return self.acceptReconnect(mode);
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Connection._eventsReconnect', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Schedules the next auto reconnect
|
||||
* @private
|
||||
* @param {string} mode
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._scheduleReconnect = function(mode) {
|
||||
|
||||
try {
|
||||
// Try to reconnect automatically after a while
|
||||
if(self.reconnect_try < 5) {
|
||||
self.reconnect_timer = 5 + (5 * self.reconnect_try);
|
||||
} else {
|
||||
self.reconnect_timer = 120;
|
||||
}
|
||||
|
||||
// Change the try number
|
||||
self.reconnect_try++;
|
||||
|
||||
// Fire the event!
|
||||
$('#reconnect a.finish.reconnect').everyTime('1s', function() {
|
||||
// We can reconnect!
|
||||
if(self.reconnect_timer === 0) {
|
||||
return self.acceptReconnect(mode);
|
||||
}
|
||||
|
||||
// Button text
|
||||
if(self.reconnect_timer <= 10) {
|
||||
$(this).text(Common._e("Reconnect") + ' (' + self.reconnect_timer + ')');
|
||||
}
|
||||
|
||||
// Remove 1 second
|
||||
self.reconnect_timer--;
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Connection._scheduleReconnect', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Does the user login
|
||||
* @public
|
||||
|
@ -45,14 +244,14 @@ var Connection = (function () {
|
|||
|
||||
try {
|
||||
// get optionnal conn handlers
|
||||
oExtend = loginOpts || {};
|
||||
extend_obj = loginOpts || {};
|
||||
|
||||
// We remove the not completed class to avoid problems
|
||||
$('#home .loginer input').removeClass('please-complete');
|
||||
|
||||
|
||||
// We add the login wait div
|
||||
Interface.showGeneralWait();
|
||||
|
||||
|
||||
if(Common.hasWebSocket()) {
|
||||
// WebSocket supported & configured
|
||||
con = new JSJaCWebSocketConnection({
|
||||
|
@ -63,56 +262,56 @@ var Connection = (function () {
|
|||
|
||||
// Check BOSH origin
|
||||
BOSH_SAME_ORIGIN = Origin.isSame(httpbase);
|
||||
|
||||
|
||||
// We create the new http-binding connection
|
||||
con = new JSJaCHttpBindingConnection({
|
||||
httpbase: httpbase
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// And we handle everything that happen
|
||||
self.setupCon(con, oExtend);
|
||||
|
||||
self.setupCon(con, extend_obj);
|
||||
|
||||
// Generate a resource
|
||||
var random_resource = DataStore.getDB(self.desktop_hash, 'session', 'resource');
|
||||
|
||||
|
||||
if(!random_resource) {
|
||||
random_resource = lResource + ' (' + (new Date()).getTime() + ')';
|
||||
}
|
||||
|
||||
// We retrieve what the user typed in the login inputs
|
||||
oArgs = {};
|
||||
oArgs.domain = $.trim(lServer);
|
||||
oArgs.username = $.trim(lNick);
|
||||
oArgs.resource = random_resource;
|
||||
oArgs.pass = lPass;
|
||||
oArgs.secure = true;
|
||||
oArgs.xmllang = XML_LANG;
|
||||
|
||||
self.desktop_hash = 'jd.' + hex_md5(oArgs.username + '@' + oArgs.domain);
|
||||
|
||||
var con_args = {
|
||||
'domain': lServer.trim(),
|
||||
'username': lNick.trim(),
|
||||
'resource': random_resource,
|
||||
'pass': lPass,
|
||||
'secure': true,
|
||||
'xmllang': XML_LANG
|
||||
};
|
||||
|
||||
self.desktop_hash = 'jd.' + hex_md5(con_args.username + '@' + con_args.domain);
|
||||
|
||||
// Store the resource (for reconnection)
|
||||
DataStore.setDB(self.desktop_hash, 'session', 'resource', random_resource);
|
||||
|
||||
|
||||
// Store session XML in temporary database
|
||||
self.storeSession(lNick, lServer, lPass, lResource, lPriority, lRemember);
|
||||
|
||||
|
||||
// We store the infos of the user into the data-base
|
||||
DataStore.setDB(self.desktop_hash, 'priority', 1, lPriority);
|
||||
|
||||
|
||||
// We connect !
|
||||
con.connect(oArgs);
|
||||
|
||||
con.connect(con_args);
|
||||
|
||||
// Change the page title
|
||||
Interface.title('wait');
|
||||
|
||||
|
||||
Console.info('Jappix is connecting...');
|
||||
} catch(e) {
|
||||
Console.error('Connection.doLogin', e);
|
||||
|
||||
// Reset Jappix
|
||||
Talk.destroy();
|
||||
|
||||
|
||||
// Open an unknown error
|
||||
Board.openThisError(2);
|
||||
} finally {
|
||||
|
@ -131,16 +330,16 @@ var Connection = (function () {
|
|||
|
||||
try {
|
||||
Console.info('A new account has been registered.');
|
||||
|
||||
|
||||
// We remove the waiting image
|
||||
Interface.removeGeneralWait();
|
||||
|
||||
|
||||
// Reset the title
|
||||
Interface.title('home');
|
||||
|
||||
|
||||
// We show the success information
|
||||
$('#home .registerer .success').fadeIn('fast');
|
||||
|
||||
|
||||
// We quit the session
|
||||
if(Common.isConnected()) {
|
||||
self.logout();
|
||||
|
@ -165,116 +364,25 @@ var Connection = (function () {
|
|||
|
||||
try {
|
||||
Console.info('Trying to register an account...');
|
||||
|
||||
|
||||
// We change the registered information text
|
||||
$('#home .homediv.registerer').append(
|
||||
'<div class="info success">' +
|
||||
Common._e("You have been registered, here is your XMPP address:") + ' <b>' + username.htmlEnc() + '@' + domain.htmlEnc() + '</b> - <a href="#">' + Common._e("Login") + '</a>' +
|
||||
'<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>' +
|
||||
'</div>'
|
||||
);
|
||||
|
||||
|
||||
// Login link
|
||||
$('#home .homediv.registerer .success a').click(function() {
|
||||
return self.doLogin(username, domain, pass, '', '10', false);
|
||||
});
|
||||
|
||||
|
||||
if((REGISTER_API == 'on') && (domain == HOST_MAIN) && captcha) {
|
||||
// Show the waiting image
|
||||
Interface.showGeneralWait();
|
||||
|
||||
// Change the page title
|
||||
Interface.title('wait');
|
||||
|
||||
// Send request
|
||||
$.post('./server/register.php', {username: username, domain: domain, password: pass, captcha: captcha}, function(data) {
|
||||
// Error registering
|
||||
Interface.removeGeneralWait();
|
||||
Interface.title('home');
|
||||
|
||||
// In all case, update CAPTCHA
|
||||
$('#home img.captcha_img').attr('src', './server/captcha.php?id=' + genID());
|
||||
$('#home input.captcha').val('');
|
||||
|
||||
// Registration okay
|
||||
if($(data).find('query status').text() == '1') {
|
||||
self.handleRegistered();
|
||||
} else {
|
||||
// Show error message
|
||||
var error_message = '';
|
||||
|
||||
switch($(data).find('query message').text()) {
|
||||
case 'CAPTCHA Not Matching':
|
||||
error_message = Common._e("The security code you entered is invalid. Please retry with another one.");
|
||||
|
||||
$('#home input.captcha').focus();
|
||||
|
||||
break;
|
||||
|
||||
case 'Username Unavailable':
|
||||
error_message = Common._e("The username you picked is not available. Please try another one.");
|
||||
|
||||
$('#home input.nick').focus();
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
error_message = Common._e("There was an error registering your account. Please retry.");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(error_message)
|
||||
Errors.show('', error_message, '');
|
||||
}
|
||||
});
|
||||
self._doRegisterAPI(username, domain, pass, captcha);
|
||||
} else {
|
||||
try {
|
||||
oArgs = {};
|
||||
|
||||
if(Common.hasWebSocket()) {
|
||||
// WebSocket supported & configured
|
||||
con = new JSJaCWebSocketConnection({
|
||||
httpbase: HOST_WEBSOCKET
|
||||
});
|
||||
} else {
|
||||
var httpbase = (HOST_BOSH_MAIN || HOST_BOSH);
|
||||
|
||||
// Check BOSH origin
|
||||
BOSH_SAME_ORIGIN = Origin.isSame(httpbase);
|
||||
|
||||
// We create the new http-binding connection
|
||||
con = new JSJaCHttpBindingConnection({
|
||||
httpbase: httpbase
|
||||
});
|
||||
}
|
||||
|
||||
// We setup the connection !
|
||||
con.registerHandler('onconnect', self.handleRegistered);
|
||||
con.registerHandler('onerror', Errors.handle);
|
||||
|
||||
// We retrieve what the user typed in the register inputs
|
||||
oArgs = {};
|
||||
oArgs.domain = $.trim(domain);
|
||||
oArgs.username = $.trim(username);
|
||||
oArgs.resource = JAPPIX_RESOURCE + ' Register (' + (new Date()).getTime() + ')';
|
||||
oArgs.pass = pass;
|
||||
oArgs.register = true;
|
||||
oArgs.secure = true;
|
||||
oArgs.xmllang = XML_LANG;
|
||||
|
||||
con.connect(oArgs);
|
||||
|
||||
// Show the waiting image
|
||||
Interface.showGeneralWait();
|
||||
|
||||
// Change the page title
|
||||
Interface.title('wait');
|
||||
}
|
||||
|
||||
catch(e) {
|
||||
// Logs errors
|
||||
Console.error('doRegister', e);
|
||||
}
|
||||
self._doRegisterInBand(username, domain, pass);
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Connection.doRegister', e);
|
||||
|
@ -294,31 +402,29 @@ var Connection = (function () {
|
|||
|
||||
try {
|
||||
Console.info('Trying to login anonymously...');
|
||||
|
||||
var aPath = '#home .anonymouser ';
|
||||
var room = $(aPath + '.room').val();
|
||||
var nick = $(aPath + '.nick').val();
|
||||
|
||||
// If the form is correctly completed
|
||||
|
||||
var path_sel = $('#home .anonymouser');
|
||||
var room = path_sel.find('.room').val();
|
||||
var nick = path_sel.find('.nick').val();
|
||||
|
||||
// Form correctly completed?
|
||||
if(room && nick) {
|
||||
// We remove the not completed class to avoid problems
|
||||
$('#home .anonymouser input').removeClass('please-complete');
|
||||
|
||||
|
||||
// Redirect the user to the anonymous room
|
||||
window.location.href = JAPPIX_LOCATION + '?r=' + room + '&n=' + nick;
|
||||
}
|
||||
|
||||
// We check if the form is entirely completed
|
||||
else {
|
||||
$(aPath + 'input[type="text"]').each(function() {
|
||||
var select = $(this);
|
||||
|
||||
if(!select.val())
|
||||
} else {
|
||||
path_sel.find('input[type="text"]').each(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
if(!this_sel.val()) {
|
||||
$(document).oneTime(10, function() {
|
||||
select.addClass('please-complete').focus();
|
||||
this_sel.addClass('please-complete').focus();
|
||||
});
|
||||
else
|
||||
select.removeClass('please-complete');
|
||||
} else {
|
||||
this_sel.removeClass('please-complete');
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch(e) {
|
||||
|
@ -339,23 +445,23 @@ var Connection = (function () {
|
|||
|
||||
try {
|
||||
Console.info('Jappix is now connected.');
|
||||
|
||||
|
||||
// Connection markers
|
||||
self.connected = true;
|
||||
self.reconnect_try = 0;
|
||||
self.reconnect_timer = 0;
|
||||
|
||||
|
||||
// We hide the home page
|
||||
$('#home').hide();
|
||||
|
||||
|
||||
// Any suggest to do before triggering connected event?
|
||||
Groupchat.suggestCheck();
|
||||
|
||||
|
||||
// Remove the waiting item
|
||||
Interface.removeGeneralWait();
|
||||
|
||||
// Init Jingle
|
||||
Jingle.init();
|
||||
// Init call
|
||||
Call.init();
|
||||
} catch(e) {
|
||||
Console.error('Connection.handleConnected', e);
|
||||
}
|
||||
|
@ -374,27 +480,28 @@ var Connection = (function () {
|
|||
// Not resumed?
|
||||
if(!self.resume) {
|
||||
// Remember the session?
|
||||
if(DataStore.getDB(self.desktop_hash, 'remember', 'session'))
|
||||
if(DataStore.getDB(self.desktop_hash, 'remember', 'session')) {
|
||||
DataStore.setPersistent('global', 'session', 1, self.current_session);
|
||||
|
||||
}
|
||||
|
||||
// We show the chatting app.
|
||||
Talk.create();
|
||||
|
||||
|
||||
// We reset the homepage
|
||||
Home.change('default');
|
||||
|
||||
|
||||
// We get all the other things
|
||||
self.getEverything();
|
||||
|
||||
|
||||
// Set last activity stamp
|
||||
DateUtils.last_activity = DateUtils.getTimeStamp();
|
||||
}
|
||||
|
||||
|
||||
// Resumed
|
||||
else {
|
||||
// Send our presence
|
||||
Presence.sendActions();
|
||||
|
||||
|
||||
// Change the title
|
||||
Interface.updateTitle();
|
||||
}
|
||||
|
@ -414,7 +521,10 @@ var Connection = (function () {
|
|||
|
||||
try {
|
||||
Console.info('Jappix is now disconnected.');
|
||||
|
||||
|
||||
// Abort ongoing call (if any)
|
||||
Call.stop(true);
|
||||
|
||||
// Normal disconnection
|
||||
if(!self.current_session && !self.connected) {
|
||||
Talk.destroy();
|
||||
|
@ -431,24 +541,32 @@ var Connection = (function () {
|
|||
* Setups the normal connection
|
||||
* @public
|
||||
* @param {object} con
|
||||
* @param {object} oExtend
|
||||
* @param {object} extend_obj
|
||||
* @return {undefined}
|
||||
*/
|
||||
self.setupCon = function(con, oExtend) {
|
||||
self.setupCon = function(con, extend_obj) {
|
||||
|
||||
try {
|
||||
// Setup connection handlers
|
||||
con.registerHandler('message', Message.handle);
|
||||
con.registerHandler('presence', Presence.handle);
|
||||
con.registerHandler('iq', IQ.handle);
|
||||
con.registerHandler('onconnect', self.handleConnected);
|
||||
con.registerHandler('onerror', Errors.handle);
|
||||
con.registerHandler('ondisconnect', self.handleDisconnected);
|
||||
|
||||
var connection_handlers = {
|
||||
'message': Message.handle,
|
||||
'presence': Presence.handle,
|
||||
'iq': IQ.handle,
|
||||
'onconnect': self.handleConnected,
|
||||
'onerror': Errors.handle,
|
||||
'ondisconnect': self.handleDisconnected
|
||||
};
|
||||
|
||||
for(var cur_handler in connection_handlers) {
|
||||
con.registerHandler(
|
||||
cur_handler,
|
||||
connection_handlers[cur_handler]
|
||||
);
|
||||
}
|
||||
|
||||
// Extended handlers
|
||||
oExtend = oExtend || {};
|
||||
|
||||
jQuery.each(oExtend, function(keywd,funct) {
|
||||
extend_obj = extend_obj || {};
|
||||
|
||||
jQuery.each(extend_obj, function(keywd,funct) {
|
||||
con.registerHandler(keywd, funct);
|
||||
});
|
||||
} catch(e) {
|
||||
|
@ -496,13 +614,13 @@ var Connection = (function () {
|
|||
if(Common.isConnected()) {
|
||||
// Clear temporary session storage
|
||||
self.resetConMarkers();
|
||||
|
||||
|
||||
// Show the waiting item (useful if BOSH is sloooow)
|
||||
Interface.showGeneralWait();
|
||||
|
||||
|
||||
// Change the page title
|
||||
Interface.title('wait');
|
||||
|
||||
|
||||
// Disconnect from the XMPP server
|
||||
self.logout();
|
||||
}
|
||||
|
@ -525,13 +643,13 @@ var Connection = (function () {
|
|||
if(!Common.isConnected()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// We show the waiting image
|
||||
Interface.showGeneralWait();
|
||||
|
||||
|
||||
// Change the page title
|
||||
Interface.title('wait');
|
||||
|
||||
|
||||
// We disconnect from the XMPP server
|
||||
self.logout();
|
||||
} catch(e) {
|
||||
|
@ -551,60 +669,34 @@ var Connection = (function () {
|
|||
|
||||
try {
|
||||
Console.error('This is not a normal disconnection, show the reconnect pane...');
|
||||
|
||||
|
||||
// Reconnect pane not yet displayed?
|
||||
if(!Common.exists('#reconnect')) {
|
||||
// Blur the focused input/textarea/select
|
||||
$('input, select, textarea').blur();
|
||||
|
||||
|
||||
// Create the HTML code
|
||||
var html = '<div id="reconnect" class="lock">' +
|
||||
'<div class="pane">' +
|
||||
Common._e("Due to a network issue, you were disconnected. What do you want to do now?");
|
||||
|
||||
var html = '<div id="reconnect" class="lock">' +
|
||||
'<div class="pane">' +
|
||||
Common._e("Due to a network issue, you were disconnected. What do you want to do now?");
|
||||
|
||||
// Can we cancel reconnection?
|
||||
if(mode == 'normal')
|
||||
if(mode == 'normal') {
|
||||
html += '<a href="#" class="finish cancel">' + Common._e("Cancel") + '</a>';
|
||||
|
||||
html += '<a href="#" class="finish reconnect">' + Common._e("Reconnect") + '</a>' +
|
||||
'</div></div>';
|
||||
|
||||
}
|
||||
|
||||
html += '<a href="#" class="finish reconnect">' + Common._e("Reconnect") + '</a>' +
|
||||
'</div></div>';
|
||||
|
||||
// Append the code
|
||||
$('body').append(html);
|
||||
|
||||
// Click events
|
||||
if(mode == 'normal')
|
||||
$('#reconnect a.finish.cancel').click(function() {
|
||||
return self.cancelReconnect();
|
||||
});
|
||||
|
||||
$('#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--;
|
||||
});
|
||||
|
||||
|
||||
// Attach events
|
||||
self._eventsReconnect(mode);
|
||||
|
||||
// Schedule next reconnect
|
||||
self._scheduleReconnect(mode);
|
||||
|
||||
// Page title
|
||||
Interface.updateTitle();
|
||||
}
|
||||
|
@ -625,30 +717,33 @@ var Connection = (function () {
|
|||
|
||||
try {
|
||||
Console.info('Trying to reconnect the user...');
|
||||
|
||||
|
||||
// Resume marker
|
||||
self.resume = true;
|
||||
|
||||
|
||||
// Show waiting item
|
||||
Interface.showGeneralWait();
|
||||
|
||||
|
||||
// Reset some various stuffs
|
||||
var groupchats = '#page-engine .page-engine-chan[data-type="groupchat"]';
|
||||
$(groupchats + ' .list .role').hide();
|
||||
$(groupchats + ' .one-group, ' + groupchats + ' .list .user').remove();
|
||||
$(groupchats).attr('data-initial', 'false');
|
||||
|
||||
var groupchats_sel = $(groupchats);
|
||||
|
||||
groupchats_sel.find('.list .role').hide();
|
||||
groupchats_sel.find('.one-group, ' + groupchats + ' .list .user').remove();
|
||||
groupchats_sel.attr('data-initial', 'false');
|
||||
|
||||
// Stop the timer
|
||||
$('#reconnect a.finish.reconnect').stopTime();
|
||||
|
||||
|
||||
// Remove the reconnect pane
|
||||
$('#reconnect').remove();
|
||||
|
||||
|
||||
// Try to login again
|
||||
if(mode == 'normal')
|
||||
if(mode == 'normal') {
|
||||
self.loginFromSession(Common.XMLFromString(self.current_session));
|
||||
else if(mode == 'anonymous')
|
||||
} else if(mode == 'anonymous') {
|
||||
Anonymous.login(HOST_ANONYMOUS);
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Connection.acceptReconnect', e);
|
||||
} finally {
|
||||
|
@ -667,16 +762,16 @@ var Connection = (function () {
|
|||
|
||||
try {
|
||||
Console.info('User has canceled automatic reconnection...');
|
||||
|
||||
|
||||
// Stop the timer
|
||||
$('#reconnect a.finish.reconnect').stopTime();
|
||||
|
||||
|
||||
// Remove the reconnect pane
|
||||
$('#reconnect').remove();
|
||||
|
||||
|
||||
// Destroy the talk page
|
||||
Talk.destroy();
|
||||
|
||||
|
||||
// Renitialize the previous session parameters
|
||||
self.resetConMarkers();
|
||||
} catch(e) {
|
||||
|
@ -698,7 +793,7 @@ var Connection = (function () {
|
|||
try {
|
||||
// Clear temporary storage
|
||||
self.resetConMarkers();
|
||||
|
||||
|
||||
// Clear persistent storage
|
||||
if($(Common.XMLFromString(DataStore.getPersistent('global', 'session', 1))).find('stored').text() == 'true') {
|
||||
DataStore.removePersistent('global', 'session', 1);
|
||||
|
@ -741,7 +836,7 @@ var Connection = (function () {
|
|||
try {
|
||||
// Select the data
|
||||
var session = $(data);
|
||||
|
||||
|
||||
// Fire the login event
|
||||
self.doLogin(
|
||||
session.find('username').text(),
|
||||
|
@ -768,10 +863,10 @@ var Connection = (function () {
|
|||
try {
|
||||
// Reset our database
|
||||
self.clearLastSession();
|
||||
|
||||
|
||||
// We quit the current session
|
||||
self.quit();
|
||||
|
||||
|
||||
// We show an info
|
||||
Board.openThisInfo(3);
|
||||
} catch(e) {
|
||||
|
@ -817,16 +912,23 @@ var Connection = (function () {
|
|||
|
||||
try {
|
||||
// Generate a session XML to be stored
|
||||
session_xml = '<session><stored>true</stored><domain>' + lServer.htmlEnc() + '</domain><username>' + lNick.htmlEnc() + '</username><resource>' + lResource.htmlEnc() + '</resource><password>' + lPass.htmlEnc() + '</password><priority>' + lPriority.htmlEnc() + '</priority></session>';
|
||||
|
||||
session_xml = '<session>' +
|
||||
'<stored>true</stored>' +
|
||||
'<domain>' + lServer.htmlEnc() + '</domain>' +
|
||||
'<username>' + lNick.htmlEnc() + '</username>' +
|
||||
'<resource>' + lResource.htmlEnc() + '</resource>' +
|
||||
'<password>' + lPass.htmlEnc() + '</password>' +
|
||||
'<priority>' + lPriority.htmlEnc() + '</priority>' +
|
||||
'</session>';
|
||||
|
||||
// Save the session parameters (for reconnect if network issue)
|
||||
self.current_session = session_xml;
|
||||
|
||||
|
||||
// Remember me?
|
||||
if(lRemember) {
|
||||
DataStore.setDB(self.desktop_hash, 'remember', 'session', 1);
|
||||
}
|
||||
|
||||
|
||||
return session_xml;
|
||||
} catch(e) {
|
||||
Console.error('Connection.storeSession', e);
|
||||
|
@ -846,11 +948,12 @@ var Connection = (function () {
|
|||
$(document).ready(function() {
|
||||
// Logouts when Jappix is closed
|
||||
$(window).bind('beforeunload', Connection.terminate);
|
||||
|
||||
|
||||
// Nothing to do when anonymous!
|
||||
if(Utils.isAnonymous())
|
||||
if(Utils.isAnonymous()) {
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// Connection params submitted in URL?
|
||||
if(XMPPLinks.links_var.u && XMPPLinks.links_var.q) {
|
||||
// Generate login data
|
||||
|
@ -861,51 +964,56 @@ var Connection = (function () {
|
|||
var login_resource = JAPPIX_RESOURCE + ' (' + (new Date()).getTime() + ')';
|
||||
var login_priority = '10';
|
||||
var login_remember = 1;
|
||||
|
||||
|
||||
// Must store session?
|
||||
if(XMPPLinks.links_var.h && (XMPPLinks.links_var.h === '1')) {
|
||||
// Store session
|
||||
var session_xml = self.storeSession(login_nick, login_server, login_pwd, login_resource, login_priority, true);
|
||||
var session_xml = self.storeSession(
|
||||
login_nick,
|
||||
login_server,
|
||||
login_pwd,
|
||||
login_resource,
|
||||
login_priority,
|
||||
true
|
||||
);
|
||||
|
||||
DataStore.setPersistent('global', 'session', 1, session_xml);
|
||||
|
||||
|
||||
// Redirect to a clean URL
|
||||
document.location.href = './';
|
||||
} else {
|
||||
// Hide the homepage
|
||||
$('#home').hide();
|
||||
|
||||
|
||||
// Show the waiting icon
|
||||
Interface.showGeneralWait();
|
||||
|
||||
|
||||
// Proceed login
|
||||
self.doLogin(login_nick, login_server, login_pwd, login_resource, login_priority, login_remember);
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Try to resume a stored session, if not anonymous
|
||||
var session = Common.XMLFromString(
|
||||
DataStore.getPersistent('global', 'session', 1)
|
||||
);
|
||||
|
||||
|
||||
if($(session).find('stored').text() == 'true') {
|
||||
// Hide the homepage
|
||||
$('#home').hide();
|
||||
|
||||
|
||||
// Show the waiting icon
|
||||
Interface.showGeneralWait();
|
||||
|
||||
|
||||
// Login!
|
||||
self.loginFromSession(session);
|
||||
|
||||
|
||||
Console.info('Saved session found, resuming it...');
|
||||
}
|
||||
|
||||
// Not connected, maybe a XMPP link is submitted?
|
||||
else if((parent.location.hash != '#OK') && XMPPLinks.links_var.x) {
|
||||
} else if((parent.location.hash != '#OK') && XMPPLinks.links_var.x) {
|
||||
Home.change('loginer');
|
||||
|
||||
|
||||
Console.info('A XMPP link is set, switch to login page.');
|
||||
}
|
||||
});
|
||||
|
|
|
@ -11,103 +11,109 @@ Authors: Stefan Strigler, Valérian Saliou, Kloadut, Maranda
|
|||
*/
|
||||
|
||||
// XMPP XMLNS attributes
|
||||
var NS_PROTOCOL = 'http://jabber.org/protocol/';
|
||||
var NS_FEATURES = 'http://jabber.org/features/';
|
||||
var NS_CLIENT = 'jabber:client';
|
||||
var NS_IQ = 'jabber:iq:';
|
||||
var NS_X = 'jabber:x:';
|
||||
var NS_IETF = 'urn:ietf:params:xml:ns:';
|
||||
var NS_IETF_XMPP = NS_IETF + 'xmpp-';
|
||||
var NS_XMPP = 'urn:xmpp:';
|
||||
var NS_PROTOCOL = 'http://jabber.org/protocol/';
|
||||
var NS_FEATURES = 'http://jabber.org/features/';
|
||||
var NS_CLIENT = 'jabber:client';
|
||||
var NS_IQ = 'jabber:iq:';
|
||||
var NS_X = 'jabber:x:';
|
||||
var NS_IETF = 'urn:ietf:params:xml:ns:';
|
||||
var NS_IETF_XMPP = NS_IETF + 'xmpp-';
|
||||
var NS_XMPP = 'urn:xmpp:';
|
||||
|
||||
var NS_STORAGE = 'storage:';
|
||||
var NS_BOOKMARKS = NS_STORAGE + 'bookmarks';
|
||||
var NS_ROSTERNOTES = NS_STORAGE + 'rosternotes';
|
||||
var NS_STORAGE = 'storage:';
|
||||
var NS_BOOKMARKS = NS_STORAGE + 'bookmarks';
|
||||
var NS_ROSTERNOTES = NS_STORAGE + 'rosternotes';
|
||||
|
||||
var NS_JAPPIX = 'jappix:';
|
||||
var NS_INBOX = NS_JAPPIX + 'inbox';
|
||||
var NS_OPTIONS = NS_JAPPIX + 'options';
|
||||
var NS_JAPPIX = 'jappix:';
|
||||
var NS_INBOX = NS_JAPPIX + 'inbox';
|
||||
var NS_OPTIONS = NS_JAPPIX + 'options';
|
||||
|
||||
var NS_DISCO_ITEMS = NS_PROTOCOL + 'disco#items';
|
||||
var NS_DISCO_INFO = NS_PROTOCOL + 'disco#info';
|
||||
var NS_VCARD = 'vcard-temp';
|
||||
var NS_VCARD_P = NS_VCARD + ':x:update';
|
||||
var NS_IETF_VCARD4 = NS_IETF + 'vcard-4.0';
|
||||
var NS_XMPP_VCARD4 = NS_XMPP + 'vcard4';
|
||||
var NS_URN_ADATA = NS_XMPP + 'avatar:data';
|
||||
var NS_URN_AMETA = NS_XMPP + 'avatar:metadata';
|
||||
var NS_AUTH = NS_IQ + 'auth';
|
||||
var NS_AUTH_ERROR = NS_IQ + 'auth:error';
|
||||
var NS_REGISTER = NS_IQ + 'register';
|
||||
var NS_SEARCH = NS_IQ + 'search';
|
||||
var NS_ROSTER = NS_IQ + 'roster';
|
||||
var NS_PRIVACY = NS_IQ + 'privacy';
|
||||
var NS_PRIVATE = NS_IQ + 'private';
|
||||
var NS_VERSION = NS_IQ + 'version';
|
||||
var NS_TIME = NS_IQ + 'time';
|
||||
var NS_LAST = NS_IQ + 'last';
|
||||
var NS_IQDATA = NS_IQ + 'data';
|
||||
var NS_XDATA = NS_X + 'data';
|
||||
var NS_IQOOB = NS_IQ + 'oob';
|
||||
var NS_XOOB = NS_X + 'oob';
|
||||
var NS_DELAY = NS_X + 'delay';
|
||||
var NS_EXPIRE = NS_X + 'expire';
|
||||
var NS_EVENT = NS_X + 'event';
|
||||
var NS_XCONFERENCE = NS_X + 'conference';
|
||||
var NS_STATS = NS_PROTOCOL + 'stats';
|
||||
var NS_MUC = NS_PROTOCOL + 'muc';
|
||||
var NS_MUC_USER = NS_MUC + '#user';
|
||||
var NS_MUC_ADMIN = NS_MUC + '#admin';
|
||||
var NS_MUC_OWNER = NS_MUC + '#owner';
|
||||
var NS_MUC_CONFIG = NS_MUC + '#roomconfig';
|
||||
var NS_PUBSUB = NS_PROTOCOL + 'pubsub';
|
||||
var NS_PUBSUB_EVENT = NS_PUBSUB + '#event';
|
||||
var NS_PUBSUB_OWNER = NS_PUBSUB + '#owner';
|
||||
var NS_PUBSUB_NMI = NS_PUBSUB + '#node-meta-info';
|
||||
var NS_PUBSUB_NC = NS_PUBSUB + '#node_config';
|
||||
var NS_PUBSUB_CN = NS_PUBSUB + '#config-node';
|
||||
var NS_PUBSUB_RI = NS_PUBSUB + '#retrieve-items';
|
||||
var NS_COMMANDS = NS_PROTOCOL + 'commands';
|
||||
var NS_BOSH = NS_PROTOCOL + 'httpbind';
|
||||
var NS_DISCO_ITEMS = NS_PROTOCOL + 'disco#items';
|
||||
var NS_DISCO_INFO = NS_PROTOCOL + 'disco#info';
|
||||
var NS_VCARD = 'vcard-temp';
|
||||
var NS_VCARD_P = NS_VCARD + ':x:update';
|
||||
var NS_IETF_VCARD4 = NS_IETF + 'vcard-4.0';
|
||||
var NS_XMPP_VCARD4 = NS_XMPP + 'vcard4';
|
||||
var NS_URN_ADATA = NS_XMPP + 'avatar:data';
|
||||
var NS_URN_AMETA = NS_XMPP + 'avatar:metadata';
|
||||
var NS_AUTH = NS_IQ + 'auth';
|
||||
var NS_AUTH_ERROR = NS_IQ + 'auth:error';
|
||||
var NS_REGISTER = NS_IQ + 'register';
|
||||
var NS_SEARCH = NS_IQ + 'search';
|
||||
var NS_ROSTER = NS_IQ + 'roster';
|
||||
var NS_PRIVACY = NS_IQ + 'privacy';
|
||||
var NS_PRIVATE = NS_IQ + 'private';
|
||||
var NS_VERSION = NS_IQ + 'version';
|
||||
var NS_TIME = NS_IQ + 'time';
|
||||
var NS_LAST = NS_IQ + 'last';
|
||||
var NS_IQDATA = NS_IQ + 'data';
|
||||
var NS_XDATA = NS_X + 'data';
|
||||
var NS_IQOOB = NS_IQ + 'oob';
|
||||
var NS_XOOB = NS_X + 'oob';
|
||||
var NS_DELAY = NS_X + 'delay';
|
||||
var NS_EXPIRE = NS_X + 'expire';
|
||||
var NS_EVENT = NS_X + 'event';
|
||||
var NS_XCONFERENCE = NS_X + 'conference';
|
||||
var NS_STATS = NS_PROTOCOL + 'stats';
|
||||
var NS_MUC = NS_PROTOCOL + 'muc';
|
||||
var NS_MUC_USER = NS_MUC + '#user';
|
||||
var NS_MUC_ADMIN = NS_MUC + '#admin';
|
||||
var NS_MUC_OWNER = NS_MUC + '#owner';
|
||||
var NS_MUC_CONFIG = NS_MUC + '#roomconfig';
|
||||
var NS_PUBSUB = NS_PROTOCOL + 'pubsub';
|
||||
var NS_PUBSUB_EVENT = NS_PUBSUB + '#event';
|
||||
var NS_PUBSUB_OWNER = NS_PUBSUB + '#owner';
|
||||
var NS_PUBSUB_NMI = NS_PUBSUB + '#node-meta-info';
|
||||
var NS_PUBSUB_NC = NS_PUBSUB + '#node_config';
|
||||
var NS_PUBSUB_CN = NS_PUBSUB + '#config-node';
|
||||
var NS_PUBSUB_RI = NS_PUBSUB + '#retrieve-items';
|
||||
var NS_COMMANDS = NS_PROTOCOL + 'commands';
|
||||
var NS_BOSH = NS_PROTOCOL + 'httpbind';
|
||||
var NS_STREAM = 'http://etherx.jabber.org/streams';
|
||||
var NS_URN_TIME = NS_XMPP + 'time';
|
||||
var NS_URN_PING = NS_XMPP + 'ping';
|
||||
var NS_URN_MBLOG = NS_XMPP + 'microblog:0';
|
||||
var NS_URN_INBOX = NS_XMPP + 'inbox';
|
||||
var NS_URN_FORWARD = NS_XMPP + 'forward:0';
|
||||
var NS_URN_MAM = NS_XMPP + 'mam:tmp';
|
||||
var NS_URN_DELAY = NS_XMPP + 'delay';
|
||||
var NS_URN_RECEIPTS = NS_XMPP + 'receipts';
|
||||
var NS_URN_CARBONS = NS_XMPP + 'carbons:2';
|
||||
var NS_RSM = NS_PROTOCOL + 'rsm';
|
||||
var NS_IPV6 = 'ipv6';
|
||||
var NS_XHTML = 'http://www.w3.org/1999/xhtml';
|
||||
var NS_XHTML_IM = NS_PROTOCOL + 'xhtml-im';
|
||||
var NS_CHATSTATES = NS_PROTOCOL + 'chatstates';
|
||||
var NS_HTTP_AUTH = NS_PROTOCOL + 'http-auth';
|
||||
var NS_ROSTERX = NS_PROTOCOL + 'rosterx';
|
||||
var NS_MOOD = NS_PROTOCOL + 'mood';
|
||||
var NS_ACTIVITY = NS_PROTOCOL + 'activity';
|
||||
var NS_TUNE = NS_PROTOCOL + 'tune';
|
||||
var NS_GEOLOC = NS_PROTOCOL + 'geoloc';
|
||||
var NS_NICK = NS_PROTOCOL + 'nick';
|
||||
var NS_NOTIFY = '+notify';
|
||||
var NS_CAPS = NS_PROTOCOL + 'caps';
|
||||
var NS_ATOM = 'http://www.w3.org/2005/Atom';
|
||||
var NS_URN_TIME = NS_XMPP + 'time';
|
||||
var NS_URN_PING = NS_XMPP + 'ping';
|
||||
var NS_URN_MBLOG = NS_XMPP + 'microblog:0';
|
||||
var NS_URN_INBOX = NS_XMPP + 'inbox';
|
||||
var NS_URN_FORWARD = NS_XMPP + 'forward:0';
|
||||
var NS_URN_MAM = NS_XMPP + 'mam:tmp';
|
||||
var NS_URN_DELAY = NS_XMPP + 'delay';
|
||||
var NS_URN_RECEIPTS = NS_XMPP + 'receipts';
|
||||
var NS_URN_CARBONS = NS_XMPP + 'carbons:2';
|
||||
var NS_URN_CORRECT = NS_XMPP + 'message-correct:0';
|
||||
var NS_URN_IDLE = NS_XMPP + 'idle:1';
|
||||
var NS_URN_REACH = NS_XMPP + 'reach:0';
|
||||
var NS_URN_MARKERS = NS_XMPP + 'chat-markers:0';
|
||||
var NS_URN_ATTENTION = NS_XMPP + 'attention:0';
|
||||
var NS_URN_HINTS = NS_XMPP + 'hints';
|
||||
var NS_RSM = NS_PROTOCOL + 'rsm';
|
||||
var NS_IPV6 = 'ipv6';
|
||||
var NS_XHTML = 'http://www.w3.org/1999/xhtml';
|
||||
var NS_XHTML_IM = NS_PROTOCOL + 'xhtml-im';
|
||||
var NS_CHATSTATES = NS_PROTOCOL + 'chatstates';
|
||||
var NS_HTTP_AUTH = NS_PROTOCOL + 'http-auth';
|
||||
var NS_ROSTERX = NS_PROTOCOL + 'rosterx';
|
||||
var NS_MOOD = NS_PROTOCOL + 'mood';
|
||||
var NS_ACTIVITY = NS_PROTOCOL + 'activity';
|
||||
var NS_TUNE = NS_PROTOCOL + 'tune';
|
||||
var NS_GEOLOC = NS_PROTOCOL + 'geoloc';
|
||||
var NS_NICK = NS_PROTOCOL + 'nick';
|
||||
var NS_NOTIFY = '+notify';
|
||||
var NS_CAPS = NS_PROTOCOL + 'caps';
|
||||
var NS_ATOM = 'http://www.w3.org/2005/Atom';
|
||||
|
||||
var NS_STANZAS = NS_IETF_XMPP + 'stanzas';
|
||||
var NS_STREAMS = NS_IETF_XMPP + 'streams';
|
||||
var NS_STANZAS = NS_IETF_XMPP + 'stanzas';
|
||||
var NS_STREAMS = NS_IETF_XMPP + 'streams';
|
||||
|
||||
var NS_TLS = NS_IETF_XMPP + 'tls';
|
||||
var NS_SASL = NS_IETF_XMPP + 'sasl';
|
||||
var NS_SESSION = NS_IETF_XMPP + 'session';
|
||||
var NS_BIND = NS_IETF_XMPP + 'bind';
|
||||
var NS_TLS = NS_IETF_XMPP + 'tls';
|
||||
var NS_SASL = NS_IETF_XMPP + 'sasl';
|
||||
var NS_SESSION = NS_IETF_XMPP + 'session';
|
||||
var NS_BIND = NS_IETF_XMPP + 'bind';
|
||||
|
||||
var NS_FEATURE_IQAUTH = NS_FEATURES + 'iq-auth';
|
||||
var NS_FEATURE_IQAUTH = NS_FEATURES + 'iq-auth';
|
||||
var NS_FEATURE_IQREGISTER = NS_FEATURES + 'iq-register';
|
||||
var NS_FEATURE_COMPRESS = NS_FEATURES + 'compress';
|
||||
var NS_FEATURE_COMPRESS = NS_FEATURES + 'compress';
|
||||
|
||||
var NS_COMPRESS = NS_PROTOCOL + 'compress';
|
||||
var NS_COMPRESS = NS_PROTOCOL + 'compress';
|
||||
|
||||
var NS_METRONOME_MAM_PURGE = 'http://metronome.im/protocol/mam-purge';
|
||||
|
||||
|
@ -181,7 +187,7 @@ function STANZA_ERROR(code, type, cond) {
|
|||
if(window == this) {
|
||||
return new STANZA_ERROR(code, type, cond);
|
||||
}
|
||||
|
||||
|
||||
this.code = code;
|
||||
this.type = type;
|
||||
this.cond = cond;
|
||||
|
|
509
source/app/javascripts/correction.js
Normal file
|
@ -0,0 +1,509 @@
|
|||
/*
|
||||
|
||||
Jappix - An open social platform
|
||||
Implementation of XEP-0308: Last Message Correction
|
||||
|
||||
-------------------------------------------------
|
||||
|
||||
License: AGPL
|
||||
Author: Valérian Saliou
|
||||
|
||||
*/
|
||||
|
||||
// Bundle
|
||||
var Correction = (function () {
|
||||
|
||||
/**
|
||||
* Alias of this
|
||||
* @private
|
||||
*/
|
||||
var self = {};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @return {boolean}
|
||||
*/
|
||||
self._hasSupport = function(xid) {
|
||||
|
||||
var support = false;
|
||||
|
||||
try {
|
||||
if($('#' + hex_md5(xid) + '[data-correction="true"]').size()) {
|
||||
support = true;
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Correction._hasSupport', e);
|
||||
} finally {
|
||||
return support;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @return {string}
|
||||
*/
|
||||
self._getLastID = function(xid) {
|
||||
|
||||
var last_id = null;
|
||||
|
||||
try {
|
||||
if(self._hasSupport(xid) === true) {
|
||||
// Check last message from ourselves
|
||||
last_id = $('#' + hex_md5(xid) + ' .content .one-line.user-message[data-mode="me"]:last').attr('data-id') || null;
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Correction._getLastID', e);
|
||||
} finally {
|
||||
return last_id;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @return {string}
|
||||
*/
|
||||
self._getCurrentID = function(xid) {
|
||||
|
||||
var current_id = null;
|
||||
|
||||
try {
|
||||
if(self._hasSupport(xid) === true) {
|
||||
// Check the ID of the message being edited (if any)
|
||||
current_id = $('#' + hex_md5(xid) + ' .message-area').attr('data-correction-current') || null;
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Correction._getCurrentID', e);
|
||||
} finally {
|
||||
return current_id;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @return {object}
|
||||
*/
|
||||
self._getLastMessage = function(xid) {
|
||||
|
||||
var last_message_val = null;
|
||||
var last_message_sel = null;
|
||||
|
||||
try {
|
||||
if(self._hasSupport(xid) === true) {
|
||||
// Check last message from ourselves
|
||||
last_message_sel = $('#' + hex_md5(xid) + ' .content .one-line.user-message[data-mode="me"]:last');
|
||||
last_message_val = last_message_sel.find('.message-content').text() || null;
|
||||
|
||||
if(last_message_val === null) {
|
||||
last_message_sel = null;
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Correction._getLastMessage', e);
|
||||
} finally {
|
||||
return {
|
||||
'value': last_message_val,
|
||||
'selector': last_message_sel
|
||||
};
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @param {object} message_sel
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._bindInterface = function(xid, message_sel) {
|
||||
|
||||
try {
|
||||
// Add message area elements
|
||||
var text_sel = $('#' + hex_md5(xid) + ' .text');
|
||||
|
||||
text_sel.addClass('correction-active');
|
||||
text_sel.prepend(
|
||||
'<div class="correction-toolbox">' +
|
||||
'<span class="correction-editing">' + Common._e("Editing") + '</span>' +
|
||||
'<a class="correction-cancel" href="#">' + Common._e("Cancel") + '</a>' +
|
||||
'</div>'
|
||||
);
|
||||
|
||||
// Add message correction marker
|
||||
message_sel.addClass('correction-active');
|
||||
message_sel.find('.correction-label').remove();
|
||||
message_sel.find('.correction-edit').hide();
|
||||
|
||||
message_sel.append(
|
||||
'<span class="correction-label">' +
|
||||
Common._e("Being edited") +
|
||||
'</span>'
|
||||
);
|
||||
|
||||
// Bind click events
|
||||
text_sel.find('.correction-cancel').click(function() {
|
||||
self.leave(xid);
|
||||
return false;
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Correction._bindInterface', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @param {object} message_sel
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._unbindInterface = function(xid, message_sel) {
|
||||
|
||||
try {
|
||||
// Remove message area elements
|
||||
var text_sel = $('#' + hex_md5(xid) + ' .text');
|
||||
text_sel.removeClass('correction-active');
|
||||
text_sel.find('.correction-toolbox, .correction-label').remove();
|
||||
|
||||
if(message_sel.size()) {
|
||||
message_sel.find('.correction-edit').css('display', '');
|
||||
|
||||
// Remove message correction marker
|
||||
message_sel.removeClass('correction-active');
|
||||
message_sel.find('.correction-label').remove();
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Correction._unbindInterface', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {string} xid
|
||||
* @param {string} full_xid
|
||||
* @param {string} type
|
||||
* @param {string} message_id
|
||||
* @param {string} message_body
|
||||
* @return {string}
|
||||
*/
|
||||
self._sendStanza = function(xid, full_xid, type, message_id, message_body) {
|
||||
|
||||
var args = {
|
||||
'id': null,
|
||||
'xhtml': false,
|
||||
'message': null
|
||||
};
|
||||
|
||||
try {
|
||||
var hash = hex_md5(xid);
|
||||
var id = genID();
|
||||
args.id = id;
|
||||
|
||||
// Initialize message stanza
|
||||
var message = new JSJaCMessage();
|
||||
args.message = message;
|
||||
|
||||
message.setType(type);
|
||||
message.setTo(full_xid);
|
||||
message.setID(id);
|
||||
|
||||
// Generates the correct message depending of the choosen style
|
||||
var generate_message = Message.generate(message, message_body, hash);
|
||||
args.xhtml = (generate_message === 'XHTML');
|
||||
|
||||
// Receipt request
|
||||
var receipt_request = Receipts.request(hash);
|
||||
|
||||
if(receipt_request) {
|
||||
message.appendNode('request', {'xmlns': NS_URN_RECEIPTS});
|
||||
}
|
||||
|
||||
// Chatstate
|
||||
message.appendNode('active', {'xmlns': NS_CHATSTATES});
|
||||
|
||||
if(message_id !== null) {
|
||||
message.appendNode('replace', {
|
||||
'xmlns': NS_URN_CORRECT,
|
||||
'id': message_id
|
||||
});
|
||||
}
|
||||
|
||||
con.send(message, Errors.handleReply);
|
||||
} catch(e) {
|
||||
Console.error('Correction._sendStanza', e);
|
||||
} finally {
|
||||
return args;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Detects correction mode request (in input)
|
||||
* @public
|
||||
* @param {string} xid
|
||||
* @param {object} input_sel
|
||||
* @return {undefined}
|
||||
*/
|
||||
self.detect = function(xid, input_sel) {
|
||||
|
||||
try {
|
||||
// Other keys
|
||||
if(input_sel.val().match(/^\/correct/) && self.isIn(xid) === false) {
|
||||
// Enter correction mode?
|
||||
self.enter(xid);
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Correction.detect', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Enter correction mode (for last message)
|
||||
* @public
|
||||
* @param {string} xid
|
||||
* @return {undefined}
|
||||
*/
|
||||
self.enter = function(xid) {
|
||||
|
||||
try {
|
||||
Console.debug('Correction.enter', 'Requested to enter the correction mode with: ' + xid);
|
||||
|
||||
if(self._hasSupport(xid) === true && self.isIn(xid) === false) {
|
||||
var last_message = self._getLastMessage(xid);
|
||||
|
||||
if(last_message.value && last_message.selector) {
|
||||
Console.info('Correction.enter', 'Valid last message found for correction mode with: ' + xid);
|
||||
|
||||
var message_area_sel = $('#' + hex_md5(xid) + ' .message-area');
|
||||
message_area_sel.val(last_message.value);
|
||||
|
||||
self._bindInterface(
|
||||
xid,
|
||||
last_message.selector
|
||||
);
|
||||
|
||||
// Focus hack (to get cursor at the end of textarea)
|
||||
message_area_sel.oneTime(10, function() {
|
||||
message_area_sel[0].select();
|
||||
message_area_sel[0].selectionStart = message_area_sel[0].selectionEnd;
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Correction.enter', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Leave correction mode
|
||||
* @public
|
||||
* @param {string} xid
|
||||
* @return {undefined}
|
||||
*/
|
||||
self.leave = function(xid) {
|
||||
|
||||
try {
|
||||
if(self.isIn(xid) === true) {
|
||||
var base_sel = $('#' + hex_md5(xid));
|
||||
var active_message_sel = base_sel.find('.content .one-line.user-message.correction-active');
|
||||
|
||||
self._unbindInterface(xid, active_message_sel);
|
||||
|
||||
var message_area_sel = base_sel.find('.message-area');
|
||||
message_area_sel.val('');
|
||||
message_area_sel.focus();
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Correction.leave', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Send corrected message
|
||||
* @public
|
||||
* @param {string} xid
|
||||
* @param {string} type
|
||||
* @param {string} replacement
|
||||
* @return {undefined}
|
||||
*/
|
||||
self.send = function(xid, type, replacement) {
|
||||
|
||||
try {
|
||||
if(self._hasSupport(xid) === true) {
|
||||
if(self._getLastMessage(xid).value != replacement) {
|
||||
var own_xid = Common.getXID();
|
||||
var hash = hex_md5(xid);
|
||||
var replace_id = self._getLastID(xid);
|
||||
|
||||
Console.info('Correction.send', 'Sending replacement message for: ' + xid + ' "' + replacement + '" with ID: ' + (replace_id || 'none'));
|
||||
|
||||
// Send the stanza itself
|
||||
var full_xid = Presence.highestPriority(xid) || xid;
|
||||
var stanza_args = self._sendStanza(
|
||||
xid,
|
||||
full_xid,
|
||||
type,
|
||||
replace_id,
|
||||
replacement
|
||||
);
|
||||
|
||||
// Update DOM (for chat only)
|
||||
if(type == 'chat') {
|
||||
// Filter the xHTML message (for us!)
|
||||
var replacement_formatted = replacement;
|
||||
|
||||
if(stanza_args.xhtml) {
|
||||
replacement_formatted = Filter.xhtml(stanza_args.message.getNode());
|
||||
}
|
||||
|
||||
// Remove old message
|
||||
old_message_sel = $('#' + hash + ' .content .one-line.user-message[data-mode="me"]').filter(function() {
|
||||
return ($(this).attr('data-id') + '') === (replace_id + '');
|
||||
}).filter(':last');
|
||||
|
||||
var edit_count = old_message_sel.attr('data-edit-count') || 0;
|
||||
edit_count = isNaN(edit_count) ? 0 : parseInt(edit_count, 10);
|
||||
|
||||
if(type == 'chat') {
|
||||
old_message_sel.remove();
|
||||
}
|
||||
|
||||
// Display edited message
|
||||
Message.display(
|
||||
'chat',
|
||||
own_xid,
|
||||
hash,
|
||||
Name.getBuddy(own_xid).htmlEnc(),
|
||||
replacement_formatted,
|
||||
DateUtils.getCompleteTime(),
|
||||
DateUtils.getTimeStamp(),
|
||||
'user-message',
|
||||
!stanza_args.xhtml,
|
||||
'',
|
||||
'me',
|
||||
stanza_args.id,
|
||||
undefined,
|
||||
undefined,
|
||||
true,
|
||||
(edit_count + 1)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Correction.send', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Catches a replace message
|
||||
* @public
|
||||
* @param {object} message
|
||||
* @param {string} hash
|
||||
* @param {string} type
|
||||
* @return {object}
|
||||
*/
|
||||
self.catch = function(message, hash, type) {
|
||||
|
||||
var edit_results = {
|
||||
'has_replace': false,
|
||||
'is_edited': false,
|
||||
'count': 0,
|
||||
'next_count': 0
|
||||
};
|
||||
|
||||
try {
|
||||
var replace_node = message.getChild('replace', NS_URN_CORRECT);
|
||||
|
||||
if(replace_node) {
|
||||
edit_results.has_replace = true;
|
||||
var message_edit_id = $(replace_node).attr('id');
|
||||
|
||||
if(typeof message_edit_id != 'undefined') {
|
||||
var message_edit_sel = $('#' + hash + ' .one-line.user-message').filter(function() {
|
||||
var this_sel = $(this);
|
||||
var is_valid_mode = true;
|
||||
|
||||
if(type == 'chat') {
|
||||
is_valid_mode = true ? this_sel.attr('data-mode') == 'him' : false;
|
||||
}
|
||||
|
||||
return is_valid_mode && ((this_sel.attr('data-id') + '') === (message_edit_id + ''));
|
||||
}).filter(':last');
|
||||
|
||||
if(message_edit_sel.size()) {
|
||||
edit_results.count = message_edit_sel.attr('data-edit-count') || 0;
|
||||
edit_results.count = isNaN(edit_results.count) ? 0 : parseInt(edit_results.count, 10);
|
||||
edit_results.next_count = edit_results.count + 1;
|
||||
edit_results.is_edited = true;
|
||||
|
||||
// Empty group?
|
||||
var message_edit_group_sel = message_edit_sel.parents('.one-group');
|
||||
|
||||
if(message_edit_group_sel.find('.one-line').size() <= 1) {
|
||||
message_edit_group_sel.remove();
|
||||
} else {
|
||||
message_edit_sel.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Correction.catch', e);
|
||||
} finally {
|
||||
return edit_results;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether we are in correction mode or not
|
||||
* @public
|
||||
* @param {string} xid
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.isIn = function(xid) {
|
||||
|
||||
var is_in = false;
|
||||
|
||||
try {
|
||||
is_in = $('#' + hex_md5(xid) + ' .text').hasClass('correction-active');
|
||||
} catch(e) {
|
||||
Console.error('Correction.isIn', e);
|
||||
} finally {
|
||||
return is_in;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return class scope
|
||||
*/
|
||||
return self;
|
||||
|
||||
})();
|
|
@ -39,8 +39,9 @@ var DataStore = (function () {
|
|||
|
||||
this.key = function(key) {
|
||||
if(legacy) {
|
||||
if(key >= this.length)
|
||||
if(key >= this.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var c = 0;
|
||||
|
||||
|
@ -56,8 +57,9 @@ var DataStore = (function () {
|
|||
|
||||
this.getItem = function(key) {
|
||||
if(legacy) {
|
||||
if(storage_emulated[key] !== undefined)
|
||||
if(storage_emulated[key] !== undefined) {
|
||||
return storage_emulated[key];
|
||||
}
|
||||
|
||||
return null;
|
||||
} else {
|
||||
|
@ -67,8 +69,9 @@ var DataStore = (function () {
|
|||
|
||||
this.setItem = function(key, data) {
|
||||
if(legacy) {
|
||||
if(!(key in storage_emulated))
|
||||
if(!(key in storage_emulated)) {
|
||||
this.length++;
|
||||
}
|
||||
|
||||
storage_emulated[key] = (data + '');
|
||||
} else {
|
||||
|
@ -162,7 +165,7 @@ var DataStore = (function () {
|
|||
try {
|
||||
return self.storageDB.getItem(dbID + '_' + type + '_' + id);
|
||||
}
|
||||
|
||||
|
||||
catch(e) {
|
||||
Console.error('Error while getting a temporary database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', e);
|
||||
}
|
||||
|
@ -192,7 +195,7 @@ var DataStore = (function () {
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
catch(e) {
|
||||
Console.error('Error while writing a temporary database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', e);
|
||||
}
|
||||
|
@ -218,10 +221,10 @@ var DataStore = (function () {
|
|||
try {
|
||||
try {
|
||||
self.storageDB.removeItem(dbID + '_' + type + '_' + id);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
catch(e) {
|
||||
Console.error('Error while removing a temporary database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', e);
|
||||
}
|
||||
|
@ -263,15 +266,15 @@ var DataStore = (function () {
|
|||
try {
|
||||
try {
|
||||
self.storageDB.clear();
|
||||
|
||||
|
||||
Console.info('Temporary database cleared.');
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
catch(e) {
|
||||
Console.error('Error while clearing temporary database', e);
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
} catch(e) {
|
||||
|
@ -294,7 +297,7 @@ var DataStore = (function () {
|
|||
// Try to write something
|
||||
self.storagePersistent.setItem('haspersistent_check', 'ok');
|
||||
self.storagePersistent.removeItem('haspersistent_check');
|
||||
|
||||
|
||||
has_persistent = true;
|
||||
} catch(e) {
|
||||
Console.error('DataStore.hasPersistent', e);
|
||||
|
@ -319,10 +322,10 @@ var DataStore = (function () {
|
|||
try {
|
||||
return self.storagePersistent.getItem(dbID + '_' + type + '_' + id);
|
||||
}
|
||||
|
||||
|
||||
catch(e) {
|
||||
Console.error('Error while getting a persistent database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', e);
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
} catch(e) {
|
||||
|
@ -346,24 +349,24 @@ var DataStore = (function () {
|
|||
try {
|
||||
try {
|
||||
self.storagePersistent.setItem(dbID + '_' + type + '_' + id, value);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Database might be full
|
||||
catch(e) {
|
||||
Console.warn('Retrying: could not write a persistent database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', e);
|
||||
|
||||
|
||||
// Flush it!
|
||||
self.flushPersistent();
|
||||
|
||||
|
||||
// Set the item again
|
||||
try {
|
||||
self.storagePersistent.setItem(dbID + ' -> ' + type + '_' + id, value);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// New error!
|
||||
catch(_e) {
|
||||
Console.error('Aborted: error while writing a persistent database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', _e);
|
||||
|
@ -394,7 +397,7 @@ var DataStore = (function () {
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
catch(e) {
|
||||
Console.error('Error while removing a persistent database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', e);
|
||||
}
|
||||
|
@ -439,10 +442,10 @@ var DataStore = (function () {
|
|||
self.storagePersistent.clear();
|
||||
|
||||
Console.info('Persistent database cleared.');
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
catch(e) {
|
||||
Console.error('Error while clearing persistent database', e);
|
||||
}
|
||||
|
@ -467,19 +470,20 @@ var DataStore = (function () {
|
|||
try {
|
||||
// Get the stored session entry
|
||||
var session = self.getPersistent('global', 'session', 1);
|
||||
|
||||
|
||||
// Reset the persistent database
|
||||
self.resetPersistent();
|
||||
|
||||
|
||||
// Restaure the stored session entry
|
||||
if(session)
|
||||
if(session) {
|
||||
self.setPersistent('global', 'session', 1, session);
|
||||
|
||||
}
|
||||
|
||||
Console.info('Persistent database flushed.');
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
catch(e) {
|
||||
Console.error('Error while flushing persistent database', e);
|
||||
}
|
||||
|
|
|
@ -84,9 +84,10 @@ var DateUtils = (function () {
|
|||
|
||||
try {
|
||||
// Last activity not yet initialized?
|
||||
if(self.last_activity === 0)
|
||||
if(self.last_activity === 0) {
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
return self.getTimeStamp() - self.last_activity;
|
||||
} catch(e) {
|
||||
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
|
||||
* @public
|
||||
|
@ -104,9 +126,10 @@ var DateUtils = (function () {
|
|||
|
||||
try {
|
||||
// Last presence stamp not yet initialized?
|
||||
if(self.presence_last_activity === 0)
|
||||
if(self.presence_last_activity === 0) {
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
return self.getTimeStamp() - self.presence_last_activity;
|
||||
} catch(e) {
|
||||
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
|
||||
* @public
|
||||
|
@ -123,43 +196,11 @@ var DateUtils = (function () {
|
|||
*/
|
||||
self.getXMPPTime = function(location) {
|
||||
|
||||
/* FROM : http://trac.jwchat.org/jsjac/browser/branches/jsjac_1.0/jsextras.js?rev=221 */
|
||||
|
||||
try {
|
||||
// Initialize
|
||||
var jInit = new Date();
|
||||
var year, month, day, hours, minutes, seconds;
|
||||
|
||||
// Gets the UTC date
|
||||
if(location == 'utc') {
|
||||
year = jInit.getUTCFullYear();
|
||||
month = jInit.getUTCMonth();
|
||||
day = jInit.getUTCDate();
|
||||
hours = jInit.getUTCHours();
|
||||
minutes = jInit.getUTCMinutes();
|
||||
seconds = jInit.getUTCSeconds();
|
||||
}
|
||||
|
||||
// Gets the local date
|
||||
else {
|
||||
year = jInit.getFullYear();
|
||||
month = jInit.getMonth();
|
||||
day = jInit.getDate();
|
||||
hours = jInit.getHours();
|
||||
minutes = jInit.getMinutes();
|
||||
seconds = jInit.getSeconds();
|
||||
}
|
||||
|
||||
// Generates the date string
|
||||
var jDate = year + '-';
|
||||
jDate += Common.padZero(month + 1) + '-';
|
||||
jDate += Common.padZero(day) + 'T';
|
||||
jDate += Common.padZero(hours) + ':';
|
||||
jDate += Common.padZero(minutes) + ':';
|
||||
jDate += Common.padZero(seconds) + 'Z';
|
||||
|
||||
// Returns the date string
|
||||
return jDate;
|
||||
return self.getDatetime(
|
||||
(new Date()),
|
||||
location
|
||||
);
|
||||
} catch(e) {
|
||||
Console.error('DateUtils.getXMPPTime', e);
|
||||
}
|
||||
|
@ -176,10 +217,11 @@ var DateUtils = (function () {
|
|||
|
||||
try {
|
||||
var init = new Date();
|
||||
|
||||
var time = Common.padZero(init.getHours()) + ':';
|
||||
time += Common.padZero(init.getMinutes()) + ':';
|
||||
time += Common.padZero(init.getSeconds());
|
||||
|
||||
|
||||
return time;
|
||||
} catch(e) {
|
||||
Console.error('DateUtils.getCompleteTime', e);
|
||||
|
@ -199,26 +241,26 @@ var DateUtils = (function () {
|
|||
// Get the date
|
||||
var date = new Date();
|
||||
var offset = date.getTimezoneOffset();
|
||||
|
||||
|
||||
// Default vars
|
||||
var sign = '';
|
||||
var hours = 0;
|
||||
var minutes = 0;
|
||||
|
||||
|
||||
// Process a neutral offset
|
||||
if(offset < 0) {
|
||||
offset = offset * -1;
|
||||
sign = '+';
|
||||
}
|
||||
|
||||
|
||||
// Get the values
|
||||
var n_date = new Date(offset * 60 * 1000);
|
||||
hours = n_date.getHours() - 1;
|
||||
minutes = n_date.getMinutes();
|
||||
|
||||
|
||||
// Process the TZO
|
||||
tzo = sign + Common.padZero(hours) + ':' + Common.padZero(minutes);
|
||||
|
||||
|
||||
// Return the processed value
|
||||
return tzo;
|
||||
} catch(e) {
|
||||
|
@ -259,7 +301,7 @@ var DateUtils = (function () {
|
|||
try {
|
||||
var date = Date.jab2date(to_parse);
|
||||
var parsed = date.toLocaleDateString() + ' (' + date.toLocaleTimeString() + ')';
|
||||
|
||||
|
||||
return parsed;
|
||||
} catch(e) {
|
||||
Console.error('DateUtils.parse', e);
|
||||
|
@ -279,7 +321,7 @@ var DateUtils = (function () {
|
|||
try {
|
||||
var date = Date.jab2date(to_parse);
|
||||
var parsed = date.toLocaleDateString();
|
||||
|
||||
|
||||
return parsed;
|
||||
} catch(e) {
|
||||
Console.error('DateUtils.parseDay', e);
|
||||
|
@ -299,7 +341,7 @@ var DateUtils = (function () {
|
|||
try {
|
||||
var date = Date.jab2date(to_parse);
|
||||
var parsed = date.toLocaleTimeString();
|
||||
|
||||
|
||||
return parsed;
|
||||
} catch(e) {
|
||||
Console.error('DateUtils.parseTime', e);
|
||||
|
@ -321,32 +363,36 @@ var DateUtils = (function () {
|
|||
var current_date = Date.jab2date(self.getXMPPTime('utc'));
|
||||
var current_day = current_date.getDate();
|
||||
var current_stamp = current_date.getTime();
|
||||
|
||||
|
||||
// Parse the given date
|
||||
var old_date = Date.jab2date(to_parse);
|
||||
var old_day = old_date.getDate();
|
||||
var old_stamp = old_date.getTime();
|
||||
var old_time = old_date.toLocaleTimeString();
|
||||
|
||||
|
||||
// Get the day number between the two dates
|
||||
var days = Math.round((current_stamp - old_stamp) / 86400000);
|
||||
|
||||
|
||||
// Invalid date?
|
||||
if(isNaN(old_stamp) || isNaN(days))
|
||||
if(isNaN(old_stamp) || isNaN(days)) {
|
||||
return self.getCompleteTime();
|
||||
|
||||
}
|
||||
|
||||
// Is it today?
|
||||
if(current_day == old_day)
|
||||
if(current_day == old_day) {
|
||||
return old_time;
|
||||
|
||||
}
|
||||
|
||||
// It is yesterday?
|
||||
if(days <= 1)
|
||||
if(days <= 1) {
|
||||
return Common._e("Yesterday") + ' - ' + old_time;
|
||||
|
||||
}
|
||||
|
||||
// Is it less than a week ago?
|
||||
if(days <= 7)
|
||||
if(days <= 7) {
|
||||
return Common.printf(Common._e("%s days ago"), days) + ' - ' + old_time;
|
||||
|
||||
}
|
||||
|
||||
// Another longer period
|
||||
return old_date.toLocaleDateString() + ' - ' + old_time;
|
||||
} catch(e) {
|
||||
|
@ -360,30 +406,36 @@ var DateUtils = (function () {
|
|||
* Reads a message delay
|
||||
* @public
|
||||
* @param {string} node
|
||||
* @return {string}
|
||||
* @param {boolean} return_date
|
||||
* @return {string|Date}
|
||||
*/
|
||||
self.readMessageDelay = function(node) {
|
||||
self.readMessageDelay = function(node, return_date) {
|
||||
|
||||
try {
|
||||
// Initialize
|
||||
var delay, d_delay;
|
||||
|
||||
|
||||
// Read the delay
|
||||
d_delay = jQuery(node).find('delay[xmlns="' + NS_URN_DELAY + '"]:first').attr('stamp');
|
||||
|
||||
// New delay (valid XEP)
|
||||
if(d_delay)
|
||||
|
||||
// Get delay
|
||||
if(d_delay) {
|
||||
// New delay (valid XEP)
|
||||
delay = d_delay;
|
||||
|
||||
// Old delay (obsolete XEP!)
|
||||
else {
|
||||
// Try to read the old-school delay
|
||||
} else {
|
||||
// Old delay (obsolete XEP!)
|
||||
var x_delay = jQuery(node).find('x[xmlns="' + NS_DELAY + '"]:first').attr('stamp');
|
||||
|
||||
if(x_delay)
|
||||
|
||||
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');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Return a date object?
|
||||
if(return_date === true && delay) {
|
||||
return Date.jab2date(delay);
|
||||
}
|
||||
|
||||
return delay;
|
||||
} catch(e) {
|
||||
Console.error('DateUtils.readMessageDelay', e);
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/**
|
||||
* Version: 1.0 Alpha-1
|
||||
* Build Date: 13-Nov-2007
|
||||
* Copyright (c) 2006-2007, Coolite Inc. (http://www.coolite.com/). All rights reserved.
|
||||
* License: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/.
|
||||
* Website: http://www.datejs.com/ or http://www.coolite.com/datejs/
|
||||
*/
|
||||
/**
|
||||
* Version: 1.0 Alpha-1
|
||||
* Build Date: 13-Nov-2007
|
||||
* Copyright (c) 2006-2007, Coolite Inc. (http://www.coolite.com/). All rights reserved.
|
||||
* License: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/.
|
||||
* Website: http://www.datejs.com/ or http://www.coolite.com/datejs/
|
||||
*/
|
||||
Date.CultureInfo={name:"en-US",englishName:"English (United States)",nativeName:"English (United States)",dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],abbreviatedDayNames:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],shortestDayNames:["Su","Mo","Tu","We","Th","Fr","Sa"],firstLetterDayNames:["S","M","T","W","T","F","S"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],abbreviatedMonthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],amDesignator:"AM",pmDesignator:"PM",firstDayOfWeek:0,twoDigitYearMax:2029,dateElementOrder:"mdy",formatPatterns:{shortDate:"M/d/yyyy",longDate:"dddd, MMMM dd, yyyy",shortTime:"h:mm tt",longTime:"h:mm:ss tt",fullDateTime:"dddd, MMMM dd, yyyy h:mm:ss tt",sortableDateTime:"yyyy-MM-ddTHH:mm:ss",universalSortableDateTime:"yyyy-MM-dd HH:mm:ssZ",rfc1123:"ddd, dd MMM yyyy HH:mm:ss GMT",monthDay:"MMMM dd",yearMonth:"MMMM, yyyy"},regexPatterns:{jan:/^jan(uary)?/i,feb:/^feb(ruary)?/i,mar:/^mar(ch)?/i,apr:/^apr(il)?/i,may:/^may/i,jun:/^jun(e)?/i,jul:/^jul(y)?/i,aug:/^aug(ust)?/i,sep:/^sep(t(ember)?)?/i,oct:/^oct(ober)?/i,nov:/^nov(ember)?/i,dec:/^dec(ember)?/i,sun:/^su(n(day)?)?/i,mon:/^mo(n(day)?)?/i,tue:/^tu(e(s(day)?)?)?/i,wed:/^we(d(nesday)?)?/i,thu:/^th(u(r(s(day)?)?)?)?/i,fri:/^fr(i(day)?)?/i,sat:/^sa(t(urday)?)?/i,future:/^next/i,past:/^last|past|prev(ious)?/i,add:/^(\+|after|from)/i,subtract:/^(\-|before|ago)/i,yesterday:/^yesterday/i,today:/^t(oday)?/i,tomorrow:/^tomorrow/i,now:/^n(ow)?/i,millisecond:/^ms|milli(second)?s?/i,second:/^sec(ond)?s?/i,minute:/^min(ute)?s?/i,hour:/^h(ou)?rs?/i,week:/^w(ee)?k/i,month:/^m(o(nth)?s?)?/i,day:/^d(ays?)?/i,year:/^y((ea)?rs?)?/i,shortMeridian:/^(a|p)/i,longMeridian:/^(a\.?m?\.?|p\.?m?\.?)/i,timezone:/^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\s*(\+|\-)\s*\d\d\d\d?)|gmt)/i,ordinalSuffix:/^\s*(st|nd|rd|th)/i,timeContext:/^\s*(\:|a|p)/i},abbreviatedTimeZoneStandard:{GMT:"-000",EST:"-0400",CST:"-0500",MST:"-0600",PST:"-0700"},abbreviatedTimeZoneDST:{GMT:"-000",EDT:"-0500",CDT:"-0600",MDT:"-0700",PDT:"-0800"}};
|
||||
Date.getMonthNumberFromName=function(name){var n=Date.CultureInfo.monthNames,m=Date.CultureInfo.abbreviatedMonthNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
|
||||
return-1;};Date.getDayNumberFromName=function(name){var n=Date.CultureInfo.dayNames,m=Date.CultureInfo.abbreviatedDayNames,o=Date.CultureInfo.shortestDayNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
|
||||
|
@ -101,4 +101,4 @@ return _.any.apply(null,rx);}else{return _get(fx);}};g._formats=g.formats(["yyyy
|
|||
return g._start.call({},s);};}());Date._parse=Date.parse;Date.parse=function(s){var r=null;if(!s){return null;}
|
||||
try{r=Date.Grammar.start.call({},s);}catch(e){return null;}
|
||||
return((r[1].length===0)?r[0]:null);};Date.getParseFunction=function(fx){var fn=Date.Grammar.formats(fx);return function(s){var r=null;try{r=fn.call({},s);}catch(e){return null;}
|
||||
return((r[1].length===0)?r[0]:null);};};Date.parseExact=function(s,fx){return Date.getParseFunction(fx)(s);};
|
||||
return((r[1].length===0)?r[0]:null);};};Date.parseExact=function(s,fx){return Date.getParseFunction(fx)(s);};
|
||||
|
|
|
@ -29,31 +29,31 @@ var Directory = (function () {
|
|||
|
||||
try {
|
||||
// Popup HTML content
|
||||
var html =
|
||||
'<div class="top">' + Common._e("User directory") + '</div>' +
|
||||
|
||||
'<div class="content">' +
|
||||
'<div class="directory-head">' +
|
||||
'<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) + '" />' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="results directory-results"></div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="bottom">' +
|
||||
'<div class="wait wait-medium"></div>' +
|
||||
|
||||
'<a href="#" class="finish">' + Common._e("Close") + '</a>' +
|
||||
var html =
|
||||
'<div class="top">' + Common._e("User directory") + '</div>' +
|
||||
|
||||
'<div class="content">' +
|
||||
'<div class="directory-head">' +
|
||||
'<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) + '" />' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="results directory-results"></div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="bottom">' +
|
||||
'<div class="wait wait-medium"></div>' +
|
||||
|
||||
'<a href="#" class="finish">' + Common._e("Close") + '</a>' +
|
||||
'</div>';
|
||||
|
||||
|
||||
// Create the popup
|
||||
Popup.create('directory', html);
|
||||
|
||||
|
||||
// Associate the events
|
||||
self.instance();
|
||||
|
||||
|
||||
// Start a search!
|
||||
self.start();
|
||||
} catch(e) {
|
||||
|
@ -94,10 +94,10 @@ var Directory = (function () {
|
|||
try {
|
||||
// Get the server to query
|
||||
var server = $('#directory .directory-server-input').val();
|
||||
|
||||
|
||||
// Launch the search!
|
||||
DataForm.go($('#directory .directory-server-input').val(), 'search', '', '', 'directory');
|
||||
|
||||
|
||||
Console.log('Directory search launched: ' + server);
|
||||
} catch(e) {
|
||||
Console.error('Directory.start', e);
|
||||
|
@ -118,17 +118,18 @@ var Directory = (function () {
|
|||
try {
|
||||
// Click event
|
||||
$('#directory .bottom .finish').click(self.close);
|
||||
|
||||
|
||||
// Keyboard event
|
||||
$('#directory .directory-server-input').keyup(function(e) {
|
||||
if(e.keyCode == 13) {
|
||||
// No value?
|
||||
if(!$(this).val())
|
||||
if(!$(this).val()) {
|
||||
$(this).val(HOST_VJUD);
|
||||
|
||||
}
|
||||
|
||||
// Start the directory search
|
||||
self.start();
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -29,99 +29,99 @@ var Discovery = (function () {
|
|||
|
||||
try {
|
||||
// Popup HTML content
|
||||
var html =
|
||||
'<div class="top">' + Common._e("Service discovery") + '</div>' +
|
||||
|
||||
'<div class="content">' +
|
||||
'<div class="discovery-head">' +
|
||||
'<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) + '" />' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="results discovery-results">' +
|
||||
'<div class="disco-category disco-account">' +
|
||||
'<p class="disco-category-title">' + Common._e("Accounts") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="disco-category disco-auth">' +
|
||||
'<p class="disco-category-title">' + Common._e("Authentications") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="disco-category disco-automation">' +
|
||||
'<p class="disco-category-title">' + Common._e("Automation") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="disco-category disco-client">' +
|
||||
'<p class="disco-category-title">' + Common._e("Clients") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="disco-category disco-collaboration">' +
|
||||
'<p class="disco-category-title">' + Common._e("Collaboration") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="disco-category disco-component">' +
|
||||
'<p class="disco-category-title">' + Common._e("Components") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="disco-category disco-conference">' +
|
||||
'<p class="disco-category-title">' + Common._e("Rooms") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="disco-category disco-directory">' +
|
||||
'<p class="disco-category-title">' + Common._e("Directories") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="disco-category disco-gateway">' +
|
||||
'<p class="disco-category-title">' + Common._e("Gateways") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="disco-category disco-headline">' +
|
||||
'<p class="disco-category-title">' + Common._e("News") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="disco-category disco-hierarchy">' +
|
||||
'<p class="disco-category-title">' + Common._e("Hierarchy") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="disco-category disco-proxy">' +
|
||||
'<p class="disco-category-title">' + Common._e("Proxies") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="disco-category disco-pubsub">' +
|
||||
'<p class="disco-category-title">' + Common._e("Publication/Subscription") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="disco-category disco-server">' +
|
||||
'<p class="disco-category-title">' + Common._e("Server") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="disco-category disco-store">' +
|
||||
'<p class="disco-category-title">' + Common._e("Storage") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="disco-category disco-others">' +
|
||||
'<p class="disco-category-title">' + Common._e("Others") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="disco-category disco-wait">' +
|
||||
'<p class="disco-category-title">' + Common._e("Loading") + '</p>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="bottom">' +
|
||||
'<div class="wait wait-medium"></div>' +
|
||||
|
||||
'<a href="#" class="finish">' + Common._e("Close") + '</a>' +
|
||||
var html =
|
||||
'<div class="top">' + Common._e("Service discovery") + '</div>' +
|
||||
|
||||
'<div class="content">' +
|
||||
'<div class="discovery-head">' +
|
||||
'<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) + '" />' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="results discovery-results">' +
|
||||
'<div class="disco-category disco-account">' +
|
||||
'<p class="disco-category-title">' + Common._e("Accounts") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="disco-category disco-auth">' +
|
||||
'<p class="disco-category-title">' + Common._e("Authentications") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="disco-category disco-automation">' +
|
||||
'<p class="disco-category-title">' + Common._e("Automation") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="disco-category disco-client">' +
|
||||
'<p class="disco-category-title">' + Common._e("Clients") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="disco-category disco-collaboration">' +
|
||||
'<p class="disco-category-title">' + Common._e("Collaboration") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="disco-category disco-component">' +
|
||||
'<p class="disco-category-title">' + Common._e("Components") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="disco-category disco-conference">' +
|
||||
'<p class="disco-category-title">' + Common._e("Rooms") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="disco-category disco-directory">' +
|
||||
'<p class="disco-category-title">' + Common._e("Directories") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="disco-category disco-gateway">' +
|
||||
'<p class="disco-category-title">' + Common._e("Gateways") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="disco-category disco-headline">' +
|
||||
'<p class="disco-category-title">' + Common._e("News") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="disco-category disco-hierarchy">' +
|
||||
'<p class="disco-category-title">' + Common._e("Hierarchy") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="disco-category disco-proxy">' +
|
||||
'<p class="disco-category-title">' + Common._e("Proxies") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="disco-category disco-pubsub">' +
|
||||
'<p class="disco-category-title">' + Common._e("Publication/Subscription") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="disco-category disco-server">' +
|
||||
'<p class="disco-category-title">' + Common._e("Server") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="disco-category disco-store">' +
|
||||
'<p class="disco-category-title">' + Common._e("Storage") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="disco-category disco-others">' +
|
||||
'<p class="disco-category-title">' + Common._e("Others") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="disco-category disco-wait">' +
|
||||
'<p class="disco-category-title">' + Common._e("Loading") + '</p>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="bottom">' +
|
||||
'<div class="wait wait-medium"></div>' +
|
||||
|
||||
'<a href="#" class="finish">' + Common._e("Close") + '</a>' +
|
||||
'</div>';
|
||||
|
||||
|
||||
// Create the popup
|
||||
Popup.create('discovery', html);
|
||||
|
||||
|
||||
// Associate the events
|
||||
self.instance();
|
||||
|
||||
|
||||
// We request a disco to the default server
|
||||
self.start();
|
||||
} catch(e) {
|
||||
|
@ -164,10 +164,10 @@ var Discovery = (function () {
|
|||
try {
|
||||
// We get the server to query
|
||||
var discoServer = $('#discovery .disco-server-input').val();
|
||||
|
||||
|
||||
// We launch the items query
|
||||
DataForm.go(discoServer, 'browse', '', '', 'discovery');
|
||||
|
||||
|
||||
Console.log('Service discovery launched: ' + discoServer);
|
||||
} catch(e) {
|
||||
Console.error('Discovery.start', e);
|
||||
|
@ -188,10 +188,10 @@ var Discovery = (function () {
|
|||
try {
|
||||
// We remove the results
|
||||
$('#discovery .discovery-oneresult, #discovery .oneinstructions, #discovery .onetitle, #discovery .no-results').remove();
|
||||
|
||||
|
||||
// We clean the user info
|
||||
$('#discovery .disco-server-info').text('');
|
||||
|
||||
|
||||
// We hide the wait icon, the no result alert and the results
|
||||
$('#discovery .wait, #discovery .disco-category').hide();
|
||||
} catch(e) {
|
||||
|
@ -211,17 +211,18 @@ var Discovery = (function () {
|
|||
try {
|
||||
// Click event
|
||||
$('#discovery .bottom .finish').click(self.close);
|
||||
|
||||
|
||||
// Keyboard event
|
||||
$('#discovery .disco-server-input').keyup(function(e) {
|
||||
if(e.keyCode == 13) {
|
||||
// No value?
|
||||
if(!$(this).val())
|
||||
if(!$(this).val()) {
|
||||
$(this).val(HOST_MAIN);
|
||||
|
||||
}
|
||||
|
||||
// Start the discovery
|
||||
self.start();
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -35,30 +35,33 @@ var Errors = (function () {
|
|||
if(condition || reason) {
|
||||
// Initialize the error text
|
||||
var eText = '';
|
||||
|
||||
|
||||
// Any error condition
|
||||
if(condition)
|
||||
if(condition) {
|
||||
eText += condition;
|
||||
|
||||
}
|
||||
|
||||
// Any error type
|
||||
if(type && eText)
|
||||
if(type && eText) {
|
||||
eText += ' (' + type + ')';
|
||||
|
||||
}
|
||||
|
||||
// Any error reason
|
||||
if(reason) {
|
||||
if(eText)
|
||||
if(eText) {
|
||||
eText += ' - ';
|
||||
|
||||
}
|
||||
|
||||
eText += reason;
|
||||
}
|
||||
|
||||
|
||||
// We reveal the error
|
||||
Board.openThisError(1);
|
||||
|
||||
|
||||
// Create the error text
|
||||
$('#board .one-board.error[data-id="1"] span').text(eText);
|
||||
}
|
||||
|
||||
|
||||
// Not enough data to output the error: output a generic board
|
||||
else {
|
||||
Board.openThisError(2);
|
||||
|
@ -84,75 +87,76 @@ var Errors = (function () {
|
|||
// Initialize
|
||||
var type, code, reason, condition;
|
||||
var node = $(packet);
|
||||
|
||||
|
||||
// First level error (connection error)
|
||||
if(node.is('error')) {
|
||||
// Get the value
|
||||
code = node.attr('code');
|
||||
|
||||
|
||||
// Specific error reason
|
||||
switch(code) {
|
||||
case '401':
|
||||
reason = Common._e("Authorization failed");
|
||||
break;
|
||||
|
||||
|
||||
case '409':
|
||||
reason = Common._e("Registration failed, please choose a different username");
|
||||
break;
|
||||
|
||||
|
||||
case '503':
|
||||
reason = Common._e("Service unavailable");
|
||||
break;
|
||||
|
||||
|
||||
case '500':
|
||||
reason = Common._e("Internal server error, try later");
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
reason = node.find('text').text();
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Remove the general wait item (security)
|
||||
Interface.removeGeneralWait();
|
||||
|
||||
|
||||
// Show reconnect pane
|
||||
if(Connection.current_session && Connection.connected) {
|
||||
// Anonymous?
|
||||
if(Utils.isAnonymous())
|
||||
if(Utils.isAnonymous()) {
|
||||
Connection.createReconnect('anonymous');
|
||||
else
|
||||
} else {
|
||||
Connection.createReconnect('normal');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Show the homepage (security)
|
||||
else if(!Connection.current_session || !Connection.connected) {
|
||||
$('#home').show();
|
||||
Interface.title('home');
|
||||
}
|
||||
|
||||
|
||||
// Still connected? (security)
|
||||
if(Common.isConnected()) {
|
||||
con.disconnect();
|
||||
}
|
||||
|
||||
|
||||
Console.error('First level error received.');
|
||||
}
|
||||
|
||||
|
||||
// Second level error (another error)
|
||||
else if(node.find('error').size()) {
|
||||
type = node.find('error').attr('type');
|
||||
reason = node.find('error text').text();
|
||||
condition = packet.getElementsByTagName('error').item(0).childNodes.item(0).nodeName.replace(/-/g, ' ');
|
||||
|
||||
|
||||
Console.error('Second level error received.');
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Show the error board
|
||||
self.show(condition, reason, type);
|
||||
|
||||
|
||||
// Return there's an error
|
||||
return true;
|
||||
} catch(e) {
|
||||
|
|
|
@ -29,103 +29,103 @@ var Favorites = (function () {
|
|||
|
||||
try {
|
||||
// Popup HTML content
|
||||
var html =
|
||||
'<div class="top">' + Common._e("Manage favorite rooms") + '</div>' +
|
||||
|
||||
'<div class="content">' +
|
||||
'<div class="switch-fav">' +
|
||||
'<div class="room-switcher room-list">' +
|
||||
'<div class="icon list-icon talk-images"></div>' +
|
||||
|
||||
Common._e("Change favorites") +
|
||||
'</div>' +
|
||||
|
||||
'<div class="room-switcher room-search">' +
|
||||
'<div class="icon search-icon talk-images"></div>' +
|
||||
|
||||
Common._e("Search a room") +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="static-fav">' +
|
||||
'<div class="favorites-edit favorites-content">' +
|
||||
'<div class="head fedit-head static-fav-head">' +
|
||||
'<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>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="results fedit-results static-fav-results">' +
|
||||
'<div class="fedit-line">' +
|
||||
'<label>' + Common._e("Name") + '</label>' +
|
||||
|
||||
'<input class="fedit-title" type="text" required="" />' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="fedit-line">' +
|
||||
'<label>' + Common._e("Nickname") + '</label>' +
|
||||
|
||||
'<input class="fedit-nick" type="text" value="' + Name.getNick() + '" required="" />' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="fedit-line">' +
|
||||
'<label>' + Common._e("Room") + '</label>' +
|
||||
|
||||
'<input class="fedit-chan" type="text" required="" />' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="fedit-line">' +
|
||||
'<label>' + Common._e("Server") + '</label>' +
|
||||
|
||||
'<input class="fedit-server" type="text" value="' + HOST_MUC + '" required="" />' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="fedit-line">' +
|
||||
'<label>' + Common._e("Password") + '</label>' +
|
||||
|
||||
'<input class="fedit-password" type="password" />' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="fedit-line">' +
|
||||
'<label>' + Common._e("Automatic") + '</label>' +
|
||||
|
||||
'<input type="checkbox" class="fedit-autojoin" />' +
|
||||
'</div>' +
|
||||
|
||||
'<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-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>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="favorites-search favorites-content">' +
|
||||
'<div class="head fsearch-head static-fav-head">' +
|
||||
'<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 + '" />' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="results fsearch-results static-fav-results">' +
|
||||
'<p class="fsearch-noresults">' + Common._e("No room found on this server.") + '</p>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="bottom">' +
|
||||
'<div class="wait wait-medium"></div>' +
|
||||
|
||||
'<a href="#" class="finish">' + Common._e("Close") + '</a>' +
|
||||
var html =
|
||||
'<div class="top">' + Common._e("Manage favorite rooms") + '</div>' +
|
||||
|
||||
'<div class="content">' +
|
||||
'<div class="switch-fav">' +
|
||||
'<div class="room-switcher room-list">' +
|
||||
'<div class="icon list-icon talk-images"></div>' +
|
||||
|
||||
Common._e("Change favorites") +
|
||||
'</div>' +
|
||||
|
||||
'<div class="room-switcher room-search">' +
|
||||
'<div class="icon search-icon talk-images"></div>' +
|
||||
|
||||
Common._e("Search a room") +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="static-fav">' +
|
||||
'<div class="favorites-edit favorites-content">' +
|
||||
'<div class="head fedit-head static-fav-head">' +
|
||||
'<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>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="results fedit-results static-fav-results">' +
|
||||
'<div class="fedit-line">' +
|
||||
'<label>' + Common._e("Name") + '</label>' +
|
||||
|
||||
'<input class="fedit-title" type="text" required="" />' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="fedit-line">' +
|
||||
'<label>' + Common._e("Nickname") + '</label>' +
|
||||
|
||||
'<input class="fedit-nick" type="text" value="' + Name.getNick() + '" required="" />' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="fedit-line">' +
|
||||
'<label>' + Common._e("Room") + '</label>' +
|
||||
|
||||
'<input class="fedit-chan" type="text" required="" />' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="fedit-line">' +
|
||||
'<label>' + Common._e("Server") + '</label>' +
|
||||
|
||||
'<input class="fedit-server" type="text" value="' + HOST_MUC + '" required="" />' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="fedit-line">' +
|
||||
'<label>' + Common._e("Password") + '</label>' +
|
||||
|
||||
'<input class="fedit-password" type="password" />' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="fedit-line">' +
|
||||
'<label>' + Common._e("Automatic") + '</label>' +
|
||||
|
||||
'<input type="checkbox" class="fedit-autojoin" />' +
|
||||
'</div>' +
|
||||
|
||||
'<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-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>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="favorites-search favorites-content">' +
|
||||
'<div class="head fsearch-head static-fav-head">' +
|
||||
'<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 + '" />' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="results fsearch-results static-fav-results">' +
|
||||
'<p class="fsearch-noresults">' + Common._e("No room found on this server.") + '</p>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="bottom">' +
|
||||
'<div class="wait wait-medium"></div>' +
|
||||
|
||||
'<a href="#" class="finish">' + Common._e("Close") + '</a>' +
|
||||
'</div>';
|
||||
|
||||
|
||||
// Create the popup
|
||||
Popup.create('favorites', html);
|
||||
|
||||
|
||||
// Load the favorites
|
||||
self.load();
|
||||
|
||||
|
||||
// Associate the events
|
||||
self.instance();
|
||||
} catch(e) {
|
||||
|
@ -143,16 +143,21 @@ var Favorites = (function () {
|
|||
self.reset = function() {
|
||||
|
||||
try {
|
||||
var path = '#favorites ';
|
||||
|
||||
$(path + '.wait, ' + path + '.fedit-terminate').hide();
|
||||
$(path + '.fedit-add').show();
|
||||
$(path + '.fsearch-oneresult').remove();
|
||||
$(path + 'input').val('');
|
||||
$(path + '.please-complete').removeClass('please-complete');
|
||||
$(path + '.fedit-nick').val(Name.getNick());
|
||||
$(path + '.fsearch-head-server, ' + path + '.fedit-server').val(HOST_MUC);
|
||||
$(path + '.fedit-autojoin').removeAttr('checked');
|
||||
var path_sel = $('#favorites');
|
||||
|
||||
path_sel.find('.wait');
|
||||
path_sel.find('.fedit-terminate').hide();
|
||||
path_sel.find('.fedit-add').show();
|
||||
|
||||
path_sel.find('.fsearch-oneresult').remove();
|
||||
path_sel.find('input').val('');
|
||||
path_sel.find('.please-complete').removeClass('please-complete');
|
||||
|
||||
path_sel.find('.fedit-nick').val(Name.getNick());
|
||||
path_sel.find('.fsearch-head-server').val(HOST_MUC);
|
||||
path_sel.find('.fedit-server').val(HOST_MUC);
|
||||
|
||||
path_sel.find('.fedit-autojoin').removeAttr('checked');
|
||||
} catch(e) {
|
||||
Console.error('Favorites.reset', e);
|
||||
}
|
||||
|
@ -182,30 +187,35 @@ var Favorites = (function () {
|
|||
/**
|
||||
* Adds a room to the favorites
|
||||
* @public
|
||||
* @param {string} roomXID
|
||||
* @param {string} roomName
|
||||
* @param {string} room_xid
|
||||
* @param {string} room_name
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.addThis = function(roomXID, roomName) {
|
||||
self.addThis = function(room_xid, room_name) {
|
||||
|
||||
try {
|
||||
// Button path
|
||||
var button = '#favorites .fsearch-results div[data-xid="' + escape(roomXID) + '"] a.one-button';
|
||||
|
||||
var button_sel = $('#favorites .fsearch-results div[data-xid="' + escape(room_xid) + '"] a.one-button');
|
||||
|
||||
// Add a remove button instead of the add one
|
||||
$(button + '.add').replaceWith('<a href="#" class="one-button remove talk-images">' + Common._e("Remove") + '</a>');
|
||||
|
||||
button_sel.filter('.add').replaceWith(
|
||||
'<a href="#" class="one-button remove talk-images">' + Common._e("Remove") + '</a>'
|
||||
);
|
||||
|
||||
// Click event
|
||||
$(button + '.remove').click(function() {
|
||||
return self.removeThis(roomXID, roomName);
|
||||
button_sel.filter('.remove').click(function() {
|
||||
return self.removeThis(room_xid, room_name);
|
||||
});
|
||||
|
||||
|
||||
// Hide the add button in the (opened?) groupchat
|
||||
$('#' + hex_md5(roomXID) + ' .tools-add').hide();
|
||||
|
||||
$('#' + hex_md5(room_xid) + ' .tools-add').hide();
|
||||
|
||||
// Add the database entry
|
||||
self.display(roomXID, Common.explodeThis(' (', roomName, 0), Name.getNick(), '0', '');
|
||||
|
||||
self.display(
|
||||
room_xid,
|
||||
Common.explodeThis(' (', room_name, 0), Name.getNick(), '0', ''
|
||||
);
|
||||
|
||||
// Publish the favorites
|
||||
self.publish();
|
||||
} catch(e) {
|
||||
|
@ -220,30 +230,30 @@ var Favorites = (function () {
|
|||
/**
|
||||
* Removes a room from the favorites
|
||||
* @public
|
||||
* @param {string} roomXID
|
||||
* @param {string} roomName
|
||||
* @param {string} room_xid
|
||||
* @param {string} room_name
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.removeThis = function(roomXID, roomName) {
|
||||
self.removeThis = function(room_xid, room_name) {
|
||||
|
||||
try {
|
||||
// Button path
|
||||
var button = '#favorites .fsearch-results div[data-xid="' + escape(roomXID) + '"] a.one-button';
|
||||
|
||||
var button_sel = $('#favorites .fsearch-results div[data-xid="' + escape(room_xid) + '"] a.one-button');
|
||||
|
||||
// Add a remove button instead of the add one
|
||||
$(button + '.remove').replaceWith('<a href="#" class="one-button add talk-images">' + Common._e("Add") + '</a>');
|
||||
|
||||
button_sel.filter('.remove').replaceWith('<a href="#" class="one-button add talk-images">' + Common._e("Add") + '</a>');
|
||||
|
||||
// Click event
|
||||
$(button + '.add').click(function() {
|
||||
return self.addThis(roomXID, roomName);
|
||||
button_sel.filter('.add').click(function() {
|
||||
return self.addThis(room_xid, room_name);
|
||||
});
|
||||
|
||||
|
||||
// Show the add button in the (opened?) groupchat
|
||||
$('#' + hex_md5(roomXID) + ' .tools-add').show();
|
||||
|
||||
$('#' + hex_md5(room_xid) + ' .tools-add').show();
|
||||
|
||||
// Remove the favorite
|
||||
self.remove(roomXID, true);
|
||||
|
||||
self.remove(room_xid, true);
|
||||
|
||||
// Publish the favorites
|
||||
self.publish();
|
||||
} catch(e) {
|
||||
|
@ -264,31 +274,34 @@ var Favorites = (function () {
|
|||
|
||||
try {
|
||||
// Path to favorites
|
||||
var favorites = '#favorites .';
|
||||
|
||||
var favorites_sel = $('#favorites');
|
||||
|
||||
// Reset the favorites
|
||||
self.reset();
|
||||
|
||||
|
||||
// Show the edit/remove button, hide the others
|
||||
$(favorites + 'fedit-terminate').hide();
|
||||
$(favorites + 'fedit-edit').show();
|
||||
$(favorites + 'fedit-remove').show();
|
||||
|
||||
favorites_sel.find('.fedit-terminate').hide();
|
||||
favorites_sel.find('.fedit-edit').show();
|
||||
favorites_sel.find('.fedit-remove').show();
|
||||
|
||||
// We retrieve the values
|
||||
var xid = $(favorites + 'fedit-head-select').val();
|
||||
var data = Common.XMLFromString(DataStore.getDB(Connection.desktop_hash, 'favorites', xid));
|
||||
|
||||
var xid = favorites_sel.find('.fedit-head-select').val();
|
||||
var data_sel = $(Common.XMLFromString(
|
||||
DataStore.getDB(Connection.desktop_hash, 'favorites', xid)
|
||||
));
|
||||
|
||||
// If this is not the default room
|
||||
if(xid != 'none') {
|
||||
// We apply the values
|
||||
$(favorites + 'fedit-title').val($(data).find('name').text());
|
||||
$(favorites + 'fedit-nick').val($(data).find('nick').text());
|
||||
$(favorites + 'fedit-chan').val(Common.getXIDNick(xid));
|
||||
$(favorites + 'fedit-server').val(Common.getXIDHost(xid));
|
||||
$(favorites + 'fedit-password').val($(data).find('password').text());
|
||||
|
||||
if($(data).find('autojoin').text() == 'true')
|
||||
$(favorites + 'fedit-autojoin').attr('checked', true);
|
||||
favorites_sel.find('.fedit-title').val(data_sel.find('name').text());
|
||||
favorites_sel.find('.fedit-nick').val(data_sel.find('nick').text());
|
||||
favorites_sel.find('.fedit-chan').val(Common.getXIDNick(xid));
|
||||
favorites_sel.find('.fedit-server').val(Common.getXIDHost(xid));
|
||||
favorites_sel.find('.fedit-password').val(data_sel.find('password').text());
|
||||
|
||||
if(data_sel.find('autojoin').text() == 'true') {
|
||||
favorites_sel.find('.fedit-autojoin').attr('checked', true);
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Favorites.edit', e);
|
||||
|
@ -307,61 +320,59 @@ var Favorites = (function () {
|
|||
|
||||
try {
|
||||
// Path to favorites
|
||||
var favorites = '#favorites ';
|
||||
|
||||
var favorites_sel = $('#favorites');
|
||||
|
||||
// We get the values of the current edited groupchat
|
||||
var old_xid = $(favorites + '.fedit-head-select').val();
|
||||
|
||||
var title = $(favorites + '.fedit-title').val();
|
||||
var nick = $(favorites + '.fedit-nick').val();
|
||||
var room = $(favorites + '.fedit-chan').val();
|
||||
var server = $(favorites + '.fedit-server').val();
|
||||
var old_xid = favorites_sel.find('.fedit-head-select').val();
|
||||
|
||||
var title = favorites_sel.find('.fedit-title').val();
|
||||
var nick = favorites_sel.find('.fedit-nick').val();
|
||||
var room = favorites_sel.find('.fedit-chan').val();
|
||||
var server = favorites_sel.find('.fedit-server').val();
|
||||
var xid = room + '@' + server;
|
||||
var password = $(favorites + '.fedit-password').val();
|
||||
var password = favorites_sel.find('.fedit-password').val();
|
||||
var autojoin = 'false';
|
||||
|
||||
if($(favorites + '.fedit-autojoin').filter(':checked').size())
|
||||
|
||||
if(favorites_sel.find('.fedit-autojoin').filter(':checked').size()) {
|
||||
autojoin = 'true';
|
||||
|
||||
}
|
||||
|
||||
// We check the missing values and send this if okay
|
||||
if((type == 'add') || (type == 'edit')) {
|
||||
if(title && nick && room && server) {
|
||||
// Remove the edited room
|
||||
if(type == 'edit')
|
||||
if(type == 'edit') {
|
||||
self.remove(old_xid, true);
|
||||
|
||||
}
|
||||
|
||||
// Display the favorites
|
||||
self.display(xid, title, nick, autojoin, password);
|
||||
|
||||
|
||||
// Reset the inputs
|
||||
self.reset();
|
||||
}
|
||||
|
||||
else {
|
||||
$(favorites + 'input[required]').each(function() {
|
||||
} else {
|
||||
favorites_sel.find('input[required]').each(function() {
|
||||
var select = $(this);
|
||||
|
||||
if(!select.val())
|
||||
|
||||
if(!select.val()) {
|
||||
$(document).oneTime(10, function() {
|
||||
select.addClass('please-complete').focus();
|
||||
});
|
||||
else
|
||||
select.removeClass('please-complete');
|
||||
} else {
|
||||
select.removeClass('please-complete');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Must remove a favorite?
|
||||
else if(type == 'remove') {
|
||||
} else if(type == 'remove') {
|
||||
self.remove(old_xid, true);
|
||||
|
||||
|
||||
// Reset the inputs
|
||||
self.reset();
|
||||
}
|
||||
|
||||
|
||||
// Publish the new favorites
|
||||
self.publish();
|
||||
|
||||
|
||||
Console.info('Action on this bookmark: ' + room + '@' + server + ' / ' + type);
|
||||
} catch(e) {
|
||||
Console.error('Favorites.terminateThis', e);
|
||||
|
@ -385,7 +396,7 @@ var Favorites = (function () {
|
|||
// We remove the target favorite everywhere needed
|
||||
$('.buddy-conf-groupchat-select option[value="' + xid + '"]').remove();
|
||||
$('.fedit-head-select option[value="' + xid + '"]').remove();
|
||||
|
||||
|
||||
// Must remove it from database?
|
||||
if(database) {
|
||||
DataStore.removeDB(Connection.desktop_hash, 'favorites', xid);
|
||||
|
@ -407,37 +418,55 @@ var Favorites = (function () {
|
|||
try {
|
||||
var iq = new JSJaCIQ();
|
||||
iq.setType('set');
|
||||
|
||||
|
||||
var query = iq.setQuery(NS_PRIVATE);
|
||||
var storage = query.appendChild(iq.buildNode('storage', {'xmlns': NS_BOOKMARKS}));
|
||||
|
||||
var storage = query.appendChild(iq.buildNode('storage', {
|
||||
'xmlns': NS_BOOKMARKS
|
||||
}));
|
||||
|
||||
// We generate the XML
|
||||
var db_regex = new RegExp(('^' + Connection.desktop_hash + '_') + 'favorites_(.+)');
|
||||
|
||||
for(var i = 0; i < DataStore.storageDB.length; i++) {
|
||||
// Get the pointer values
|
||||
var current = DataStore.storageDB.key(i);
|
||||
|
||||
|
||||
// If the pointer is on a stored favorite
|
||||
if(current.match(db_regex)) {
|
||||
var data = Common.XMLFromString(DataStore.storageDB.getItem(current));
|
||||
var xid = $(data).find('xid').text();
|
||||
var rName = $(data).find('name').text();
|
||||
var nick = $(data).find('nick').text();
|
||||
var password = $(data).find('password').text();
|
||||
var autojoin = $(data).find('autojoin').text();
|
||||
|
||||
var data_sel = $(Common.XMLFromString(
|
||||
DataStore.storageDB.getItem(current)
|
||||
));
|
||||
|
||||
var xid = data_sel.find('xid').text();
|
||||
var rName = data_sel.find('name').text();
|
||||
var nick = data_sel.find('nick').text();
|
||||
var password = data_sel.find('password').text();
|
||||
var autojoin = data_sel.find('autojoin').text();
|
||||
|
||||
// We create the node for this groupchat
|
||||
var item = storage.appendChild(iq.buildNode('conference', {'name': rName, 'jid': xid, 'autojoin': autojoin, xmlns: NS_BOOKMARKS}));
|
||||
item.appendChild(iq.buildNode('nick', {xmlns: NS_BOOKMARKS}, nick));
|
||||
|
||||
if(password)
|
||||
item.appendChild(iq.buildNode('password', {xmlns: NS_BOOKMARKS}, password));
|
||||
|
||||
var item = storage.appendChild(
|
||||
iq.buildNode('conference', {
|
||||
'name': rName,
|
||||
'jid': xid,
|
||||
'autojoin': autojoin,
|
||||
xmlns: NS_BOOKMARKS
|
||||
})
|
||||
);
|
||||
|
||||
item.appendChild(iq.buildNode('nick', {
|
||||
xmlns: NS_BOOKMARKS
|
||||
}, nick));
|
||||
|
||||
if(password) {
|
||||
item.appendChild(iq.buildNode('password', {
|
||||
xmlns: NS_BOOKMARKS
|
||||
}, password));
|
||||
}
|
||||
|
||||
Console.info('Bookmark sent: ' + xid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
con.send(iq);
|
||||
} catch(e) {
|
||||
Console.error('Favorites.publish', e);
|
||||
|
@ -454,20 +483,20 @@ var Favorites = (function () {
|
|||
self.getGCList = function() {
|
||||
|
||||
try {
|
||||
var path = '#favorites .';
|
||||
var gcServer = $('.fsearch-head-server').val();
|
||||
|
||||
var path_sel = $('#favorites');
|
||||
var groupchat_server = $('.fsearch-head-server').val();
|
||||
|
||||
// We reset some things
|
||||
$(path + 'fsearch-oneresult').remove();
|
||||
$(path + 'fsearch-noresults').hide();
|
||||
$(path + 'wait').show();
|
||||
|
||||
path_sel.find('.fsearch-oneresult').remove();
|
||||
path_sel.find('.fsearch-noresults').hide();
|
||||
path_sel.find('.wait').show();
|
||||
|
||||
var iq = new JSJaCIQ();
|
||||
iq.setType('get');
|
||||
iq.setTo(gcServer);
|
||||
|
||||
iq.setTo(groupchat_server);
|
||||
|
||||
iq.setQuery(NS_DISCO_ITEMS);
|
||||
|
||||
|
||||
con.send(iq, self.handleGCList);
|
||||
} catch(e) {
|
||||
Console.error('Favorites.getGCList', e);
|
||||
|
@ -485,60 +514,72 @@ var Favorites = (function () {
|
|||
self.handleGCList = function(iq) {
|
||||
|
||||
try {
|
||||
var path = '#favorites .';
|
||||
var path_sel = $('#favorites');
|
||||
var from = Common.fullXID(Common.getStanzaFrom(iq));
|
||||
|
||||
|
||||
if(!iq || (iq.getType() != 'result')) {
|
||||
Board.openThisError(3);
|
||||
|
||||
$(path + 'wait').hide();
|
||||
|
||||
|
||||
path_sel.find('.wait').hide();
|
||||
|
||||
Console.error('Error while retrieving the rooms: ' + from);
|
||||
}
|
||||
|
||||
|
||||
else {
|
||||
var handleXML = iq.getQuery();
|
||||
|
||||
|
||||
if($(handleXML).find('item').size()) {
|
||||
// Initialize the HTML code
|
||||
var html = '';
|
||||
|
||||
|
||||
$(handleXML).find('item').each(function() {
|
||||
var roomXID = $(this).attr('jid');
|
||||
var roomName = $(this).attr('name');
|
||||
|
||||
if(roomXID && roomName) {
|
||||
var this_sel = $(this);
|
||||
|
||||
var room_xid = this_sel.attr('jid');
|
||||
var room_name = this_sel.attr('name');
|
||||
|
||||
if(room_xid && room_name) {
|
||||
// Escaped values
|
||||
var escaped_xid = Utils.encodeOnclick(roomXID);
|
||||
var escaped_name = Utils.encodeOnclick(roomName);
|
||||
|
||||
var escaped_xid = Utils.encodeOnclick(room_xid);
|
||||
var escaped_name = Utils.encodeOnclick(room_name);
|
||||
|
||||
// Initialize the room HTML
|
||||
html += '<div class="oneresult fsearch-oneresult" data-xid="' + escape(roomXID) + '">' +
|
||||
'<div class="room-name">' + roomName.htmlEnc() + '</div>' +
|
||||
html += '<div class="oneresult fsearch-oneresult" data-xid="' + escape(room_xid) + '">' +
|
||||
'<div class="room-name">' + room_name.htmlEnc() + '</div>' +
|
||||
'<a href="#" class="one-button join talk-images" onclick="return Favorites.join(\'' + escaped_xid + '\');">' + Common._e("Join") + '</a>';
|
||||
|
||||
|
||||
// This room is yet a favorite
|
||||
if(DataStore.existDB('favorites', roomXID))
|
||||
html += '<a href="#" class="one-button remove talk-images" onclick="return Favorites.removeThis(\'' + escaped_xid + '\', \'' + escaped_name + '\');">' + Common._e("Remove") + '</a>';
|
||||
else
|
||||
html += '<a href="#" class="one-button add talk-images" onclick="return Favorites.addThis(\'' + escaped_xid + '\', \'' + escaped_name + '\');">' + Common._e("Add") + '</a>';
|
||||
|
||||
if(DataStore.existDB(Connection.desktop_hash, 'favorites', room_xid)) {
|
||||
html += '<a href="#" ' +
|
||||
'class="one-button remove talk-images" ' +
|
||||
'onclick="return Favorites.removeThis(\'' + escaped_xid + '\', \'' + escaped_name + '\');"' +
|
||||
'>' +
|
||||
Common._e("Remove") +
|
||||
'</a>';
|
||||
} else {
|
||||
html += '<a href="#" ' +
|
||||
'class="one-button add talk-images" ' +
|
||||
'onclick="return Favorites.addThis(\'' + escaped_xid + '\', \'' + escaped_name + '\');"' +
|
||||
'>' +
|
||||
Common._e("Add") +
|
||||
'</a>';
|
||||
}
|
||||
|
||||
// Close the room HTML
|
||||
html += '</div>';
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Append this code to the popup
|
||||
$(path + 'fsearch-results').append(html);
|
||||
path_sel.find('.fsearch-results').append(html);
|
||||
} else {
|
||||
path_sel.find('.fsearch-noresults').show();
|
||||
}
|
||||
|
||||
else
|
||||
$(path + 'fsearch-noresults').show();
|
||||
|
||||
|
||||
Console.info('Rooms retrieved: ' + from);
|
||||
}
|
||||
|
||||
$(path + 'wait').hide();
|
||||
|
||||
path_sel.find('.wait').hide();
|
||||
} catch(e) {
|
||||
Console.error('Favorites.handleGCList', e);
|
||||
}
|
||||
|
@ -556,7 +597,14 @@ var Favorites = (function () {
|
|||
|
||||
try {
|
||||
self.quit();
|
||||
Chat.checkCreate(room, 'groupchat', '', '', Common.getXIDNick(room));
|
||||
|
||||
Chat.checkCreate(
|
||||
room,
|
||||
'groupchat',
|
||||
'',
|
||||
'',
|
||||
Common.getXIDNick(room)
|
||||
);
|
||||
} catch(e) {
|
||||
Console.error('Favorites.join', e);
|
||||
} finally {
|
||||
|
@ -581,15 +629,22 @@ var Favorites = (function () {
|
|||
try {
|
||||
// Generate the HTML code
|
||||
var html = '<option value="' + Common.encodeQuotes(xid) + '">' + name.htmlEnc() + '</option>';
|
||||
|
||||
|
||||
// Remove the existing favorite
|
||||
self.remove(xid, false);
|
||||
|
||||
|
||||
// We complete the select forms
|
||||
$('#roster .gc-join-first-option, #favorites .fedit-head-select-first-option').after(html);
|
||||
|
||||
|
||||
// We store the informations
|
||||
var value = '<groupchat><xid>' + xid.htmlEnc() + '</xid><name>' + name.htmlEnc() + '</name><nick>' + nick.htmlEnc() + '</nick><autojoin>' + autojoin.htmlEnc() + '</autojoin><password>' + password.htmlEnc() + '</password></groupchat>';
|
||||
var value = '<groupchat>' +
|
||||
'<xid>' + xid.htmlEnc() + '</xid>' +
|
||||
'<name>' + name.htmlEnc() + '</name>' +
|
||||
'<nick>' + nick.htmlEnc() + '</nick>' +
|
||||
'<autojoin>' + autojoin.htmlEnc() + '</autojoin>' +
|
||||
'<password>' + password.htmlEnc() + '</password>' +
|
||||
'</groupchat>';
|
||||
|
||||
DataStore.setDB(Connection.desktop_hash, 'favorites', xid, value);
|
||||
} catch(e) {
|
||||
Console.error('Favorites.display', e);
|
||||
|
@ -608,27 +663,34 @@ var Favorites = (function () {
|
|||
try {
|
||||
// Initialize the HTML code
|
||||
var html = '';
|
||||
|
||||
|
||||
// Read the database
|
||||
var db_regex = new RegExp(('^' + Connection.desktop_hash + '_') + 'favorites_(.+)');
|
||||
|
||||
for(var i = 0; i < DataStore.storageDB.length; i++) {
|
||||
// Get the pointer values
|
||||
var current = DataStore.storageDB.key(i);
|
||||
|
||||
|
||||
// If the pointer is on a stored favorite
|
||||
if(current.match(db_regex)) {
|
||||
var data = Common.XMLFromString(DataStore.storageDB.getItem(current));
|
||||
|
||||
|
||||
// Add the current favorite to the HTML code
|
||||
html += '<option value="' + Common.encodeQuotes($(data).find('xid').text()) + '">' + $(data).find('name').text().htmlEnc() + '</option>';
|
||||
html += '<option value="' + Common.encodeQuotes($(data).find('xid').text()) + '">' +
|
||||
$(data).find('name').text().htmlEnc() +
|
||||
'</option>';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Generate specific HTML code
|
||||
var favorites_bubble = '<option value="none" class="gc-join-first-option" selected="">' + Common._e("Select a favorite") + '</option>' + html;
|
||||
var favorites_popup = '<option value="none" class="fedit-head-select-first-option" selected="">' + Common._e("Select a favorite") + '</option>' + html;
|
||||
|
||||
var favorites_bubble = '<option value="none" class="gc-join-first-option" selected="">' +
|
||||
Common._e("Select a favorite") +
|
||||
'</option>' + html;
|
||||
|
||||
var favorites_popup = '<option value="none" class="fedit-head-select-first-option" selected="">' +
|
||||
Common._e("Select a favorite") +
|
||||
'</option>' + html;
|
||||
|
||||
// Append the HTML code
|
||||
$('#roster .buddy-conf-groupchat-select').html(favorites_bubble);
|
||||
$('#favorites .fedit-head-select').html(favorites_popup);
|
||||
|
@ -647,63 +709,65 @@ var Favorites = (function () {
|
|||
self.instance = function() {
|
||||
|
||||
try {
|
||||
var path = '#favorites .';
|
||||
|
||||
var favorites_sel = $('#favorites');
|
||||
|
||||
// Keyboard events
|
||||
$(path + 'fsearch-head-server').keyup(function(e) {
|
||||
favorites_sel.find('.fsearch-head-server').keyup(function(e) {
|
||||
if(e.keyCode == 13) {
|
||||
var this_sel = $(this);
|
||||
|
||||
// No value?
|
||||
if(!$(this).val())
|
||||
$(this).val(HOST_MUC);
|
||||
|
||||
if(!this_sel.val()) {
|
||||
this_sel.val(HOST_MUC);
|
||||
}
|
||||
|
||||
// Get the list
|
||||
self.getGCList();
|
||||
}
|
||||
});
|
||||
|
||||
$(path + 'fedit-line input').keyup(function(e) {
|
||||
|
||||
favorites_sel.find('.fedit-line input').keyup(function(e) {
|
||||
if(e.keyCode == 13) {
|
||||
// Edit a favorite
|
||||
if($(path + 'fedit-edit').is(':visible'))
|
||||
if(favorites_sel.find('.fedit-edit').is(':visible')) {
|
||||
self.terminateThis('edit');
|
||||
|
||||
// Add a favorite
|
||||
else
|
||||
} else {
|
||||
self.terminateThis('add');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Change events
|
||||
$('.fedit-head-select').change(self.edit);
|
||||
|
||||
|
||||
// Click events
|
||||
$(path + 'room-switcher').click(function() {
|
||||
$(path + 'favorites-content').hide();
|
||||
favorites_sel.find('.room-switcher').click(function() {
|
||||
favorites_sel.find('.favorites-content').hide();
|
||||
self.reset();
|
||||
});
|
||||
|
||||
$(path + 'room-list').click(function() {
|
||||
$(path + 'favorites-edit').show();
|
||||
|
||||
favorites_sel.find('.room-list').click(function() {
|
||||
favorites_sel.find('.favorites-edit').show();
|
||||
});
|
||||
|
||||
$(path + 'room-search').click(function() {
|
||||
$(path + 'favorites-search').show();
|
||||
|
||||
favorites_sel.find('.room-search').click(function() {
|
||||
favorites_sel.find('.favorites-search').show();
|
||||
self.getGCList();
|
||||
});
|
||||
|
||||
$(path + 'fedit-add').click(function() {
|
||||
|
||||
favorites_sel.find('.fedit-add').click(function() {
|
||||
return self.terminateThis('add');
|
||||
});
|
||||
|
||||
$(path + 'fedit-edit').click(function() {
|
||||
|
||||
favorites_sel.find('.fedit-edit').click(function() {
|
||||
return self.terminateThis('edit');
|
||||
});
|
||||
|
||||
$(path + 'fedit-remove').click(function() {
|
||||
|
||||
favorites_sel.find('.fedit-remove').click(function() {
|
||||
return self.terminateThis('remove');
|
||||
});
|
||||
|
||||
$(path + 'bottom .finish').click(function() {
|
||||
|
||||
favorites_sel.find('.bottom .finish').click(function() {
|
||||
return self.quit();
|
||||
});
|
||||
} catch(e) {
|
||||
|
|
|
@ -50,29 +50,29 @@ var Features = (function () {
|
|||
var to = Utils.getServer();
|
||||
var caps = con.server_caps;
|
||||
var xml = null;
|
||||
|
||||
|
||||
// Try to get the stored data
|
||||
if(caps) {
|
||||
xml = Common.XMLFromString(
|
||||
DataStore.getPersistent('global', 'caps', caps)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Any stored data?
|
||||
if(xml) {
|
||||
self.handle(xml);
|
||||
|
||||
|
||||
Console.log('Read server CAPS from cache.');
|
||||
} else {
|
||||
// Not stored (or no CAPS)!
|
||||
var iq = new JSJaCIQ();
|
||||
|
||||
|
||||
iq.setTo(to);
|
||||
iq.setType('get');
|
||||
iq.setQuery(NS_DISCO_INFO);
|
||||
|
||||
|
||||
con.send(iq, Caps.handleDiscoInfos);
|
||||
|
||||
|
||||
Console.log('Read server CAPS from network.');
|
||||
}
|
||||
} catch(e) {
|
||||
|
@ -93,7 +93,7 @@ var Features = (function () {
|
|||
try {
|
||||
// Selector
|
||||
var selector = $(xml);
|
||||
|
||||
|
||||
// Functions
|
||||
var check_feature_fn = function(namespace) {
|
||||
// This weird selector fixes an IE8 bug...
|
||||
|
@ -103,7 +103,7 @@ var Features = (function () {
|
|||
};
|
||||
|
||||
// Markers
|
||||
var namespaces = [NS_PUBSUB, NS_PUBSUB_CN, NS_URN_MAM, NS_COMMANDS, NS_URN_CARBONS];
|
||||
var namespaces = [NS_PUBSUB, NS_PUBSUB_CN, NS_URN_MAM, NS_COMMANDS, NS_URN_CARBONS, NS_URN_CORRECT];
|
||||
|
||||
var identity = selector.find('identity');
|
||||
|
||||
|
@ -137,21 +137,21 @@ var Features = (function () {
|
|||
// Get the PEP nodes to initiate
|
||||
Microblog.getInit();
|
||||
PEP.getInitGeoloc();
|
||||
|
||||
|
||||
// Get the notifications
|
||||
Notification.get();
|
||||
|
||||
|
||||
// Geolocate the user
|
||||
PEP.geolocate();
|
||||
|
||||
|
||||
// Enable microblogging send tools
|
||||
Microblog.wait('sync');
|
||||
$('.postit.attach').css('display', 'block');
|
||||
|
||||
|
||||
Console.info('XMPP server supports PEP.');
|
||||
} else {
|
||||
Microblog.wait('unsync');
|
||||
|
||||
|
||||
Console.warn('XMPP server does not support PEP.');
|
||||
}
|
||||
|
||||
|
@ -159,10 +159,10 @@ var Features = (function () {
|
|||
if(features.pep === false && features[NS_URN_MAM] === false) {
|
||||
$('#options fieldset.privacy').hide();
|
||||
}
|
||||
|
||||
|
||||
// Apply the features
|
||||
self.apply('talk');
|
||||
|
||||
|
||||
// Process the roster height
|
||||
if(features.pep === true) {
|
||||
Roster.adapt();
|
||||
|
@ -192,12 +192,12 @@ var Features = (function () {
|
|||
try {
|
||||
// Path to the elements
|
||||
var path = '#' + id + ' .';
|
||||
|
||||
|
||||
// PEP features
|
||||
if(self.enabledPEP()) {
|
||||
$(path + 'pep-hidable').show();
|
||||
}
|
||||
|
||||
|
||||
// PubSub features
|
||||
if(self.enabledPubSub()) {
|
||||
$(path + 'pubsub-hidable').show();
|
||||
|
@ -207,7 +207,7 @@ var Features = (function () {
|
|||
if(self.enabledPubSubCN()) {
|
||||
$(path + 'pubsub-hidable-cn').show();
|
||||
}
|
||||
|
||||
|
||||
// MAM features
|
||||
if(self.enabledMAM()) {
|
||||
$(path + 'mam-hidable').show();
|
||||
|
@ -218,12 +218,17 @@ var Features = (function () {
|
|||
if(self.enabledMAMPurge()) {
|
||||
$(path + 'mam-purge-hidable').show();
|
||||
}
|
||||
|
||||
|
||||
// Message correction features
|
||||
if(self.enabledCorrection()) {
|
||||
$(path + 'correction-hidable').show();
|
||||
}
|
||||
|
||||
// Commands features
|
||||
if(self.enabledCommands()) {
|
||||
$(path + 'commands-hidable').show();
|
||||
}
|
||||
|
||||
|
||||
// XMPP links (browser feature)
|
||||
if(navigator.registerProtocolHandler) {
|
||||
$(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
|
||||
* @private
|
||||
|
|
|
@ -20,6 +20,300 @@ var Filter = (function () {
|
|||
var self = {};
|
||||
|
||||
|
||||
/* Constants */
|
||||
self.message_regex = {
|
||||
'commands': {
|
||||
'me': /((^)|((.+)(>)))(\/me )([^<]+)/
|
||||
},
|
||||
|
||||
'emotes': {
|
||||
'angry': [
|
||||
/(:-?@)($|\s|<)/gi,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'bat': [
|
||||
/(:-?\[)($|\s|<)/gi,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'beer': [
|
||||
/(\(B\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'biggrin': [
|
||||
/((:-?D)|(XD))($|\s|<)/gi,
|
||||
'$4'
|
||||
],
|
||||
|
||||
'blush': [
|
||||
/(:-?\$)($|\s|<)/gi,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'boy': [
|
||||
/(\(Z\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'brflower': [
|
||||
/(\(W\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'brheart': [
|
||||
/((<\/3)|(\(U\)))($|\s|<)/g,
|
||||
'$4'
|
||||
],
|
||||
|
||||
'coffee': [
|
||||
/(\(C\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'coolglasses': [
|
||||
/((8-\))|(\(H\)))($|\s|<)/g,
|
||||
'$4'
|
||||
],
|
||||
|
||||
'cry': [
|
||||
/(:'-?\()($|\s|<)/gi,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'cuffs': [
|
||||
/(\(%\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'devil': [
|
||||
/(\]:-?>)($|\s|<)/gi,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'drink': [
|
||||
/(\(D\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'flower': [
|
||||
/(@}->--)($|\s|<)/gi,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'frowning': [
|
||||
/((:-?\/)|(:-?S))($|\s|<)/gi,
|
||||
'$4'
|
||||
],
|
||||
|
||||
'girl': [
|
||||
/(\(X\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'heart': [
|
||||
/((<3)|(\(L\)))($|\s|<)/g,
|
||||
'$4'
|
||||
],
|
||||
|
||||
'hugleft': [
|
||||
/(\(}\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'hugright': [
|
||||
/(\({\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'kis': [
|
||||
/(:-?{})($|\s|<)/gi,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'lamp': [
|
||||
/(\(I\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'lion': [
|
||||
/(:-?3)($|\s|<)/gi,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'mail': [
|
||||
/(\(E\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'moon': [
|
||||
/(\(S\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'music': [
|
||||
/(\(8\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'oh': [
|
||||
/((=-?O)|(:-?O))($|\s|<)/gi,
|
||||
'$4'
|
||||
],
|
||||
|
||||
'phone': [
|
||||
/(\(T\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'photo': [
|
||||
/(\(P\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'puke': [
|
||||
/(:-?!)($|\s|<)/gi,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'pussy': [
|
||||
/(\(@\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'rainbow': [
|
||||
/(\(R\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'smile': [
|
||||
/(:-?\))($|\s|<)/gi,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'star': [
|
||||
/(\(\*\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'stare': [
|
||||
/(:-?\|)($|\s|<)/gi,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'thumbdown': [
|
||||
/(\(N\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'thumbup': [
|
||||
/(\(Y\))($|\s|<)/g,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'tongue': [
|
||||
/(:-?P)($|\s|<)/gi,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'unhappy': [
|
||||
/(:-?\()($|\s|<)/gi,
|
||||
'$2'
|
||||
],
|
||||
|
||||
'wink': [
|
||||
/(;-?\))($|\s|<)/gi,
|
||||
'$2'
|
||||
]
|
||||
|
||||
},
|
||||
|
||||
'formatting': {
|
||||
'bold': [
|
||||
/(^|\s|>|\()((\*)([^<>'"\*]+)(\*))($|\s|<|\))/gi,
|
||||
'$1<b>$2</b>$6'
|
||||
],
|
||||
|
||||
'italic': [
|
||||
/(^|\s|>|\()((\/)([^<>'"\/]+)(\/))($|\s|<|\))/gi,
|
||||
'$1<em>$2</em>$6'
|
||||
],
|
||||
|
||||
'underline': [
|
||||
/(^|\s|>|\()((_)([^<>'"_]+)(_))($|\s|<|\))/gi,
|
||||
'$1<span style="text-decoration: underline;">$2</span>$6'
|
||||
]
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
self.xhtml_allow = {
|
||||
'elements': [
|
||||
'a',
|
||||
'abbr',
|
||||
'acronym',
|
||||
'address',
|
||||
'blockquote',
|
||||
'body',
|
||||
'br',
|
||||
'cite',
|
||||
'code',
|
||||
'dd',
|
||||
'dfn',
|
||||
'div',
|
||||
'dt',
|
||||
'em',
|
||||
'h1',
|
||||
'h2',
|
||||
'h3',
|
||||
'h4',
|
||||
'h5',
|
||||
'h6',
|
||||
'head',
|
||||
'html',
|
||||
'kbd',
|
||||
'li',
|
||||
'ol',
|
||||
'p',
|
||||
'pre',
|
||||
'q',
|
||||
'samp',
|
||||
'span',
|
||||
'strong',
|
||||
'title',
|
||||
'ul',
|
||||
'var'
|
||||
],
|
||||
|
||||
'attributes': [
|
||||
'accesskey',
|
||||
'alt',
|
||||
'charset',
|
||||
'cite',
|
||||
'class',
|
||||
'height',
|
||||
'href',
|
||||
'hreflang',
|
||||
'id',
|
||||
'longdesc',
|
||||
'profile',
|
||||
'rel',
|
||||
'rev',
|
||||
'src',
|
||||
'style',
|
||||
'tabindex',
|
||||
'title',
|
||||
'type',
|
||||
'uri',
|
||||
'version',
|
||||
'width',
|
||||
'xml:lang',
|
||||
'xmlns'
|
||||
]
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Generates a given emoticon HTML code
|
||||
* @public
|
||||
|
@ -42,83 +336,64 @@ var Filter = (function () {
|
|||
/**
|
||||
* Filters a given message
|
||||
* @public
|
||||
* @param {string} neutralMessage
|
||||
* @param {string} message
|
||||
* @param {string} nick
|
||||
* @param {string} html_escape
|
||||
* @return {string}
|
||||
*/
|
||||
self.message = function(neutralMessage, nick, html_escape) {
|
||||
self.message = function(message, nick, html_escape) {
|
||||
|
||||
try {
|
||||
var filteredMessage = neutralMessage;
|
||||
|
||||
var filtered = message;
|
||||
|
||||
// We encode the HTML special chars
|
||||
if(html_escape)
|
||||
filteredMessage = filteredMessage.htmlEnc();
|
||||
|
||||
// /me command
|
||||
filteredMessage = filteredMessage.replace(/((^)|((.+)(>)))(\/me )([^<]+)/, nick + ' $7')
|
||||
|
||||
// We replace the smilies text into images
|
||||
.replace(/(:-?@)($|\s|<)/gi, self.emoteImage('angry', '$1', '$2'))
|
||||
.replace(/(:-?\[)($|\s|<)/gi, self.emoteImage('bat', '$1', '$2'))
|
||||
.replace(/(\(B\))($|\s|<)/g, self.emoteImage('beer', '$1', '$2'))
|
||||
.replace(/((:-?D)|(XD))($|\s|<)/gi, self.emoteImage('biggrin', '$1', '$4'))
|
||||
.replace(/(:-?\$)($|\s|<)/gi, self.emoteImage('blush', '$1', '$2'))
|
||||
.replace(/(\(Z\))($|\s|<)/g, self.emoteImage('boy', '$1', '$2'))
|
||||
.replace(/(\(W\))($|\s|<)/g, self.emoteImage('brflower', '$1', '$2'))
|
||||
.replace(/((<\/3)|(\(U\)))($|\s|<)/g, self.emoteImage('brheart', '$1', '$4'))
|
||||
.replace(/(\(C\))($|\s|<)/g, self.emoteImage('coffee', '$1', '$2'))
|
||||
.replace(/((8-\))|(\(H\)))($|\s|<)/g, self.emoteImage('coolglasses', '$1', '$4'))
|
||||
.replace(/(:'-?\()($|\s|<)/gi, self.emoteImage('cry', '$1', '$2'))
|
||||
.replace(/(\(%\))($|\s|<)/g, self.emoteImage('cuffs', '$1', '$2'))
|
||||
.replace(/(\]:-?>)($|\s|<)/gi, self.emoteImage('devil', '$1', '$2'))
|
||||
.replace(/(\(D\))($|\s|<)/g, self.emoteImage('drink', '$1', '$2'))
|
||||
.replace(/(@}->--)($|\s|<)/gi, self.emoteImage('flower', '$1', '$2'))
|
||||
.replace(/((:-?\/)|(:-?S))($|\s|<)/gi, self.emoteImage('frowning', '$1', '$4'))
|
||||
.replace(/(\(X\))($|\s|<)/g, self.emoteImage('girl', '$1', '$2'))
|
||||
.replace(/((<3)|(\(L\)))($|\s|<)/g, self.emoteImage('heart', '$1', '$4'))
|
||||
.replace(/(\(}\))($|\s|<)/g, self.emoteImage('hugleft', '$1', '$2'))
|
||||
.replace(/(\({\))($|\s|<)/g, self.emoteImage('hugright', '$1', '$2'))
|
||||
.replace(/(:-?{})($|\s|<)/gi, self.emoteImage('kiss', '$1', '$2'))
|
||||
.replace(/(\(I\))($|\s|<)/g, self.emoteImage('lamp', '$1', '$2'))
|
||||
.replace(/(:-?3)($|\s|<)/gi, self.emoteImage('lion', '$1', '$2'))
|
||||
.replace(/(\(E\))($|\s|<)/g, self.emoteImage('mail', '$1', '$2'))
|
||||
.replace(/(\(S\))($|\s|<)/g, self.emoteImage('moon', '$1', '$2'))
|
||||
.replace(/(\(8\))($|\s|<)/g, self.emoteImage('music', '$1', '$2'))
|
||||
.replace(/((=-?O)|(:-?O))($|\s|<)/gi, self.emoteImage('oh', '$1', '$4'))
|
||||
.replace(/(\(T\))($|\s|<)/g, self.emoteImage('phone', '$1', '$2'))
|
||||
.replace(/(\(P\))($|\s|<)/g, self.emoteImage('photo', '$1', '$2'))
|
||||
.replace(/(:-?!)($|\s|<)/gi, self.emoteImage('puke', '$1', '$2'))
|
||||
.replace(/(\(@\))($|\s|<)/g, self.emoteImage('pussy', '$1', '$2'))
|
||||
.replace(/(\(R\))($|\s|<)/g, self.emoteImage('rainbow', '$1', '$2'))
|
||||
.replace(/(:-?\))($|\s|<)/gi, self.emoteImage('smile', '$1', '$2'))
|
||||
.replace(/(\(\*\))($|\s|<)/g, self.emoteImage('star', '$1', '$2'))
|
||||
.replace(/(:-?\|)($|\s|<)/gi, self.emoteImage('stare', '$1', '$2'))
|
||||
.replace(/(\(N\))($|\s|<)/g, self.emoteImage('thumbdown', '$1', '$2'))
|
||||
.replace(/(\(Y\))($|\s|<)/g, self.emoteImage('thumbup', '$1', '$2'))
|
||||
.replace(/(:-?P)($|\s|<)/gi, self.emoteImage('tongue', '$1', '$2'))
|
||||
.replace(/(:-?\()($|\s|<)/gi, self.emoteImage('unhappy', '$1', '$2'))
|
||||
.replace(/(;-?\))($|\s|<)/gi, self.emoteImage('wink', '$1', '$2'))
|
||||
|
||||
// Text in bold
|
||||
.replace(/(^|\s|>|\()((\*)([^<>'"\*]+)(\*))($|\s|<|\))/gi, '$1<b>$2</b>$6')
|
||||
|
||||
// Italic text
|
||||
.replace(/(^|\s|>|\()((\/)([^<>'"\/]+)(\/))($|\s|<|\))/gi, '$1<em>$2</em>$6')
|
||||
|
||||
// Underlined text
|
||||
.replace(/(^|\s|>|\()((_)([^<>'"_]+)(_))($|\s|<|\))/gi, '$1<span style="text-decoration: underline;">$2</span>$6');
|
||||
|
||||
// Add the links
|
||||
if(html_escape) {
|
||||
filteredMessage = Links.apply(filteredMessage, 'desktop');
|
||||
filtered = filtered.htmlEnc();
|
||||
}
|
||||
|
||||
// Filter integratebox links
|
||||
filteredMessage = IntegrateBox.filter(filteredMessage);
|
||||
|
||||
return filteredMessage;
|
||||
|
||||
// Security: don't filter huge messages (avoids crash attacks)
|
||||
if(filtered.length < 10000) {
|
||||
// /me command
|
||||
filtered = filtered.replace(self.message_regex.commands.me, nick + ' $7');
|
||||
|
||||
// We replace the smilies text into images
|
||||
var cur_emote;
|
||||
|
||||
for(var cur_emote_name in self.message_regex.emotes) {
|
||||
cur_emote = self.message_regex.emotes[cur_emote_name];
|
||||
|
||||
filtered = filtered.replace(
|
||||
cur_emote[0],
|
||||
self.emoteImage(
|
||||
cur_emote_name,
|
||||
'$1',
|
||||
cur_emote[1]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Text formatting
|
||||
var cur_formatting;
|
||||
|
||||
for(var cur_formatting_name in self.message_regex.formatting) {
|
||||
cur_formatting = self.message_regex.formatting[cur_formatting_name];
|
||||
|
||||
filtered = filtered.replace(
|
||||
cur_formatting[0],
|
||||
cur_formatting[1]
|
||||
);
|
||||
}
|
||||
|
||||
// Add the links
|
||||
if(html_escape) {
|
||||
filtered = Links.apply(filtered, 'desktop');
|
||||
}
|
||||
|
||||
// Filter integratebox links
|
||||
filtered = IntegrateBox.filter(filtered);
|
||||
}
|
||||
|
||||
return filtered;
|
||||
} catch(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
|
||||
* @public
|
||||
|
@ -135,106 +436,46 @@ var Filter = (function () {
|
|||
self.xhtml = function(code) {
|
||||
|
||||
try {
|
||||
// Allowed elements array
|
||||
var elements = new Array(
|
||||
'a',
|
||||
'abbr',
|
||||
'acronym',
|
||||
'address',
|
||||
'blockquote',
|
||||
'body',
|
||||
'br',
|
||||
'cite',
|
||||
'code',
|
||||
'dd',
|
||||
'dfn',
|
||||
'div',
|
||||
'dt',
|
||||
'em',
|
||||
'h1',
|
||||
'h2',
|
||||
'h3',
|
||||
'h4',
|
||||
'h5',
|
||||
'h6',
|
||||
'head',
|
||||
'html',
|
||||
'kbd',
|
||||
'li',
|
||||
'ol',
|
||||
'p',
|
||||
'pre',
|
||||
'q',
|
||||
'samp',
|
||||
'span',
|
||||
'strong',
|
||||
'title',
|
||||
'ul',
|
||||
'var'
|
||||
);
|
||||
|
||||
// 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'
|
||||
);
|
||||
|
||||
var code_sel = $(code);
|
||||
|
||||
// Check if Filter for XHTML-IM images is enabled
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'no-xhtml-images') != '1') {
|
||||
elements.push("img");
|
||||
self.xhtml_allow.elements.push("img");
|
||||
}
|
||||
|
||||
|
||||
// Remove forbidden elements
|
||||
$(code).find('html body *').each(function() {
|
||||
code_sel.find('html body *').each(function() {
|
||||
// This element is not authorized
|
||||
if(!Utils.existArrayValue(elements, (this).nodeName.toLowerCase()))
|
||||
if(!Utils.existArrayValue(self.xhtml_allow.elements, (this).nodeName.toLowerCase())) {
|
||||
$(this).remove();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Remove forbidden attributes
|
||||
$(code).find('html body *').each(function() {
|
||||
code_sel.find('html body *').each(function() {
|
||||
// Put a pointer on this element (jQuery way & normal way)
|
||||
var cSelector = $(this);
|
||||
var cElement = (this);
|
||||
|
||||
|
||||
// Loop the attributes of the current element
|
||||
$(cElement.attributes).each(function(index) {
|
||||
// Read the current attribute
|
||||
var cAttr = cElement.attributes[index];
|
||||
var cName = cAttr.name;
|
||||
var cVal = cAttr.value;
|
||||
|
||||
|
||||
// This attribute is not authorized, or contains JS code
|
||||
if(!Utils.existArrayValue(attributes, cName.toLowerCase()) || ((cVal.toLowerCase()).match(/(^|"|')javascript:/)))
|
||||
if(!Utils.existArrayValue(self.xhtml_allow.attributes, cName.toLowerCase()) ||
|
||||
((cVal.toLowerCase()).match(/(^|"|')javascript:/))) {
|
||||
cSelector.removeAttr(cName);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// Filter some other elements
|
||||
$(code).find('a').attr('target', '_blank');
|
||||
|
||||
return $(code).find('html body').html();
|
||||
code_sel.find('a').attr('target', '_blank');
|
||||
|
||||
return code_sel.find('html body').html();
|
||||
} catch(e) {
|
||||
Console.error('Filter.xhtml', e);
|
||||
}
|
||||
|
|
|
@ -21,7 +21,199 @@ var Groupchat = (function () {
|
|||
|
||||
|
||||
/* 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 {
|
||||
// We must be in the "login" mode
|
||||
if(Utils.isAnonymous())
|
||||
if(Utils.isAnonymous()) {
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// We check if the user is a room owner or administrator to give him privileges
|
||||
if(affiliation == 'owner' || affiliation == 'admin')
|
||||
if(affiliation == 'owner' || affiliation == 'admin') {
|
||||
$('#' + id + ' .tools-mucadmin').show();
|
||||
|
||||
}
|
||||
|
||||
// We check if the room hasn't been yet created
|
||||
if(statuscode == 201)
|
||||
if(statuscode == 201) {
|
||||
Board.openThisInfo(4);
|
||||
|
||||
}
|
||||
|
||||
// We add the click event
|
||||
$('#' + id + ' .tools-mucadmin').click(function() {
|
||||
MUCAdmin.open(xid, affiliation);
|
||||
|
@ -72,33 +267,35 @@ var Groupchat = (function () {
|
|||
try {
|
||||
// Room hash
|
||||
var hash = hex_md5(room);
|
||||
|
||||
|
||||
// Reset the elements
|
||||
$('#' + hash + ' .muc-ask').remove();
|
||||
$('#' + hash + ' .compose').show();
|
||||
|
||||
|
||||
// No nickname?
|
||||
if(!nickname) {
|
||||
// Get some values
|
||||
if(!Utils.isAnonymous())
|
||||
if(!Utils.isAnonymous()) {
|
||||
nickname = Name.getNick();
|
||||
else
|
||||
} else {
|
||||
nickname = ANONYMOUS_NICK;
|
||||
|
||||
}
|
||||
|
||||
// If the nickname could not be retrieved, ask it
|
||||
if(!nickname)
|
||||
if(!nickname) {
|
||||
self.generateMUCAsk('nickname', room, hash, nickname, password);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Got our nickname?
|
||||
if(nickname) {
|
||||
// Get our general presence
|
||||
var show = DataStore.getDB(Connection.desktop_hash, 'presence-show', 1);
|
||||
var status = DataStore.getDB(Connection.desktop_hash, 'options', 'presence-status');
|
||||
|
||||
|
||||
// Set my nick
|
||||
$('#' + hash).attr('data-nick', escape(nickname));
|
||||
|
||||
|
||||
// Send the appropriate presence
|
||||
Presence.send(room + '/' + nickname, '', show, status, '', true, password, self.handleMUC);
|
||||
}
|
||||
|
@ -126,43 +323,50 @@ var Groupchat = (function () {
|
|||
var room = Common.bareXID(from);
|
||||
var nickname = Common.thisResource(from);
|
||||
var hash = hex_md5(room);
|
||||
|
||||
var id = presence.getID();
|
||||
|
||||
// No ID: must fix M-Link bug
|
||||
if(presence.getID() === null) {
|
||||
presence.setID(1);
|
||||
if(id === null) {
|
||||
id = 1;
|
||||
presence.setID(id);
|
||||
}
|
||||
|
||||
|
||||
Console.info('First MUC presence: ' + from);
|
||||
|
||||
|
||||
// Catch the errors
|
||||
if(!Errors.handle(xml)) {
|
||||
// Define some stuffs
|
||||
var muc_user = $(xml).find('x[xmlns="' + NS_MUC_USER + '"]');
|
||||
var affiliation = muc_user.find('item').attr('affiliation');
|
||||
var statuscode = parseInt(muc_user.find('status').attr('code'));
|
||||
|
||||
var statuscode = parseInt(muc_user.find('status').attr('code'));
|
||||
|
||||
// Handle my presence
|
||||
Presence.handle(presence);
|
||||
|
||||
|
||||
// Configure the new room
|
||||
if(affiliation == 'owner' || affiliation == 'admin') {
|
||||
self._initialConfiguration(id, room);
|
||||
}
|
||||
|
||||
// Check if I am a room owner
|
||||
self.openAdmin(affiliation, hash, room, statuscode);
|
||||
|
||||
|
||||
// Tell the MUC we can notify the incoming presences
|
||||
$(document).oneTime('15s', function() {
|
||||
$('#' + hash).attr('data-initial', 'true');
|
||||
});
|
||||
|
||||
|
||||
// Enable the chatting input
|
||||
$(document).oneTime(10, function() {
|
||||
$('#' + hash + ' .message-area').removeAttr('disabled').focus();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// A password is required
|
||||
else if($(xml).find('error[type="auth"] not-authorized').size()) {
|
||||
self.generateMUCAsk('password', room, hash, nickname);
|
||||
}
|
||||
|
||||
|
||||
// There's a nickname conflict
|
||||
else if($(xml).find('error[type="cancel"] conflict').size()) {
|
||||
self.generateMUCAsk('nickname', room, hash);
|
||||
|
@ -189,34 +393,34 @@ var Groupchat = (function () {
|
|||
try {
|
||||
// Generate the path to the elements
|
||||
var path_to = '#' + hash + ' .muc-ask';
|
||||
|
||||
|
||||
// Define the label text
|
||||
var label_text;
|
||||
|
||||
|
||||
switch(type) {
|
||||
case 'nickname':
|
||||
label_text = Common._e("Nickname");
|
||||
break;
|
||||
|
||||
|
||||
case 'password':
|
||||
label_text = Common._e("Password");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Create the HTML markup
|
||||
$('#' + hash + ' .compose').hide();
|
||||
|
||||
|
||||
$('#' + hash).append(
|
||||
'<div class="muc-ask text">' +
|
||||
'<label>' + label_text + '</label>' +
|
||||
'<input class="focusable" type="text" />' +
|
||||
'<div class="muc-ask text">' +
|
||||
'<label>' + label_text + '</label>' +
|
||||
'<input class="focusable" type="text" />' +
|
||||
'</div>'
|
||||
);
|
||||
|
||||
|
||||
// When a key is pressed in the input
|
||||
$(path_to + ' input').keyup(function(e) {
|
||||
var value_input = $(this).val();
|
||||
|
||||
|
||||
// Enter key pressed
|
||||
if(e.keyCode == 13) {
|
||||
// $.trim() fixes #304
|
||||
|
@ -224,14 +428,14 @@ var Groupchat = (function () {
|
|||
nickname = $.trim(value_input);
|
||||
return self.getMUC(room, nickname, password);
|
||||
}
|
||||
|
||||
|
||||
if(type == 'password' && value_input) {
|
||||
password = value_input;
|
||||
return self.getMUC(room, nickname, password);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Focus on the input
|
||||
$(document).oneTime(10, function() {
|
||||
$(path_to + ' input').focus();
|
||||
|
@ -259,86 +463,37 @@ var Groupchat = (function () {
|
|||
|
||||
try {
|
||||
Console.info('New groupchat: ' + room);
|
||||
|
||||
|
||||
// Create the chat content
|
||||
Chat.generate('groupchat', hash, room, chan);
|
||||
|
||||
|
||||
// Create the chat switcher
|
||||
Chat.generateSwitch('groupchat', hash, room, chan);
|
||||
|
||||
|
||||
// The icons-hover functions
|
||||
Tooltip.icons(room, hash);
|
||||
|
||||
|
||||
// Click event on the add tool
|
||||
$('#' + hash + ' .tools-add').click(function() {
|
||||
// Hide the icon (to tell the user all is okay)
|
||||
$(this).hide();
|
||||
|
||||
|
||||
// Add the groupchat to the user favorites
|
||||
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
|
||||
Autocompletion.reset(hash);
|
||||
});
|
||||
|
||||
// Lock to the input
|
||||
inputDetect.keydown(function(e) {
|
||||
// Enter key
|
||||
if(e.keyCode == 13) {
|
||||
// If shift key (without any others modifiers) was pressed, add a new line
|
||||
if(e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey)
|
||||
inputDetect.val(inputDetect.val() + '\n');
|
||||
|
||||
// Send the message
|
||||
else {
|
||||
Message.send(hash, 'groupchat');
|
||||
|
||||
// Reset the composing database entry
|
||||
DataStore.setDB(Connection.desktop_hash, 'chatstate', room, 'off');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Tabulation key (without any modifiers)
|
||||
else if(!e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey && e.keyCode == 9) {
|
||||
Autocompletion.create(hash);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Reset the autocompleter
|
||||
else {
|
||||
Autocompletion.reset(hash);
|
||||
}
|
||||
});
|
||||
|
||||
// Must show the add button?
|
||||
if(!DataStore.existDB(Connection.desktop_hash, 'favorites', room)) {
|
||||
$('#' + hash + ' .tools-add').show();
|
||||
}
|
||||
|
||||
// The event handlers
|
||||
var input_sel = $('#' + hash + ' .message-area');
|
||||
self._createEvents(input_sel, hash, room);
|
||||
|
||||
// Chatstate events
|
||||
ChatState.events(inputDetect, room, hash, 'groupchat');
|
||||
|
||||
ChatState.events(input_sel, room, hash, 'groupchat');
|
||||
|
||||
// Get the current muc informations and content
|
||||
self.getMUC(room, nickname, password);
|
||||
} catch(e) {
|
||||
|
@ -359,27 +514,30 @@ var Groupchat = (function () {
|
|||
// Values array
|
||||
var muc_arr = [GROUPCHATS_JOIN];
|
||||
var new_arr = [];
|
||||
|
||||
|
||||
// Try to split it
|
||||
if(GROUPCHATS_JOIN.indexOf(',') != -1)
|
||||
if(GROUPCHATS_JOIN.indexOf(',') != -1) {
|
||||
muc_arr = GROUPCHATS_JOIN.split(',');
|
||||
|
||||
}
|
||||
|
||||
for(var i in muc_arr) {
|
||||
// Get the current value
|
||||
var muc_current = $.trim(muc_arr[i]);
|
||||
|
||||
|
||||
// No current value?
|
||||
if(!muc_current)
|
||||
if(!muc_current) {
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
// Filter the current value
|
||||
muc_current = Common.generateXID(muc_current, 'groupchat');
|
||||
|
||||
|
||||
// Add the current value
|
||||
if(!Utils.existArrayValue(new_arr, muc_current))
|
||||
if(!Utils.existArrayValue(new_arr, muc_current)) {
|
||||
new_arr.push(muc_current);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return new_arr;
|
||||
} catch(e) {
|
||||
Console.error('Groupchat.arrayJoin', e);
|
||||
|
@ -397,13 +555,14 @@ var Groupchat = (function () {
|
|||
|
||||
try {
|
||||
// Nothing to join?
|
||||
if(!JOIN_SUGGEST)
|
||||
if(!self.join_suggest) {
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// Join the chats
|
||||
if(JOIN_SUGGEST.length) {
|
||||
for(var g in JOIN_SUGGEST) {
|
||||
Chat.checkCreate(JOIN_SUGGEST[g], 'groupchat');
|
||||
if(self.join_suggest.length) {
|
||||
for(var g in self.join_suggest) {
|
||||
Chat.checkCreate(self.join_suggest[g], 'groupchat');
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
|
@ -422,16 +581,17 @@ var Groupchat = (function () {
|
|||
|
||||
try {
|
||||
var groupchat_arr = self.arrayJoin();
|
||||
|
||||
|
||||
// Must suggest the user?
|
||||
if((GROUPCHATS_SUGGEST == 'on') && groupchat_arr.length) {
|
||||
if(Common.exists('#suggest'))
|
||||
if(Common.exists('#suggest')) {
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// Create HTML code
|
||||
var html = '<div id="suggest" class="removable">';
|
||||
html += '<div class="title">' + Common._e("Suggested chatrooms") + '</div>';
|
||||
|
||||
|
||||
html += '<div class="content">';
|
||||
for(var g in groupchat_arr) {
|
||||
html += '<a class="one" href="#" data-xid="' + Common.encodeQuotes(groupchat_arr[g]) + '">';
|
||||
|
@ -442,52 +602,21 @@ var Groupchat = (function () {
|
|||
html += '</a>';
|
||||
}
|
||||
html += '</div>';
|
||||
|
||||
|
||||
html += '<div class="bottom">';
|
||||
html += '<a class="next continue disabled" href="#">' + Common._e("Continue") + '</a>';
|
||||
html += '<a class="next skip" href="#">' + Common._e("Skip") + '</a>';
|
||||
html += '</div>';
|
||||
html += '</div>';
|
||||
|
||||
|
||||
// Append HTML code
|
||||
$('body').append(html);
|
||||
|
||||
// Click events
|
||||
$('#suggest .content a.one').click(function() {
|
||||
// Add/remove the active class
|
||||
$(this).toggleClass('active');
|
||||
|
||||
// We require at least one room to be chosen
|
||||
if(Common.exists('#suggest .content a.one.active'))
|
||||
$('#suggest a.next').removeClass('disabled');
|
||||
else
|
||||
$('#suggest a.next').addClass('disabled');
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#suggest a.next').click(function() {
|
||||
// Disabled?
|
||||
if($(this).hasClass('disabled')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Store groupchats to join?
|
||||
if($(this).is('.continue')) {
|
||||
$('#suggest .content a.one.active').each(function() {
|
||||
JOIN_SUGGEST.push($(this).attr('data-xid'));
|
||||
});
|
||||
}
|
||||
|
||||
// Switch to talk UI
|
||||
$('#suggest').remove();
|
||||
Connection.triggerConnected();
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
// Attach events
|
||||
self._suggestCheckEvents();
|
||||
} else {
|
||||
JOIN_SUGGEST = groupchat_arr;
|
||||
|
||||
self.join_suggest = groupchat_arr;
|
||||
|
||||
Connection.triggerConnected();
|
||||
}
|
||||
} catch(e) {
|
||||
|
@ -512,20 +641,26 @@ var Groupchat = (function () {
|
|||
if(!ban_xid) {
|
||||
Board.openThisInfo(6);
|
||||
|
||||
Console.warning('Could not ban user with XID: ' + ban_xid + ' from room: ' + room_xid);
|
||||
Console.warn('Could not ban user with XID: ' + ban_xid + ' from room: ' + room_xid);
|
||||
} else {
|
||||
// We generate the ban IQ
|
||||
var iq = new JSJaCIQ();
|
||||
iq.setTo(room_xid);
|
||||
iq.setType('set');
|
||||
|
||||
|
||||
var iqQuery = iq.setQuery(NS_MUC_ADMIN);
|
||||
var item = iqQuery.appendChild(iq.buildNode('item', {'affiliation': 'outcast', 'jid': ban_xid, 'xmlns': NS_MUC_ADMIN}));
|
||||
|
||||
var item = iqQuery.appendChild(iq.buildNode('item', {
|
||||
'affiliation': 'outcast',
|
||||
'jid': ban_xid,
|
||||
'xmlns': NS_MUC_ADMIN
|
||||
}));
|
||||
|
||||
if(reason) {
|
||||
item.appendChild(iq.buildNode('reason', {'xmlns': NS_MUC_ADMIN}, reason));
|
||||
item.appendChild(iq.buildNode('reason', {
|
||||
'xmlns': NS_MUC_ADMIN
|
||||
}, reason));
|
||||
}
|
||||
|
||||
|
||||
con.send(iq, Errors.handleReply);
|
||||
|
||||
Console.log('Banned user with XID: ' + ban_xid + ' from room: ' + room_xid);
|
||||
|
@ -559,14 +694,20 @@ var Groupchat = (function () {
|
|||
var iq = new JSJaCIQ();
|
||||
iq.setTo(room_xid);
|
||||
iq.setType('set');
|
||||
|
||||
|
||||
var iqQuery = iq.setQuery(NS_MUC_ADMIN);
|
||||
var item = iqQuery.appendChild(iq.buildNode('item', {'nick': nick, 'role': 'none', 'xmlns': NS_MUC_ADMIN}));
|
||||
|
||||
var item = iqQuery.appendChild(iq.buildNode('item', {
|
||||
'nick': nick,
|
||||
'role': 'none',
|
||||
'xmlns': NS_MUC_ADMIN
|
||||
}));
|
||||
|
||||
if(reason) {
|
||||
item.appendChild(iq.buildNode('reason', {'xmlns': NS_MUC_ADMIN}, reason));
|
||||
item.appendChild(iq.buildNode('reason', {
|
||||
'xmlns': NS_MUC_ADMIN
|
||||
}, reason));
|
||||
}
|
||||
|
||||
|
||||
con.send(iq, Errors.handleReply);
|
||||
|
||||
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 self;
|
||||
|
||||
})();
|
||||
})();
|
||||
|
|
|
@ -20,6 +20,119 @@ var Home = (function () {
|
|||
var self = {};
|
||||
|
||||
|
||||
/**
|
||||
* Apply change events
|
||||
* @private
|
||||
* @param {object} current_sel
|
||||
* @param {string} div
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._eventsChange = function(current_sel, div) {
|
||||
|
||||
try {
|
||||
// Create the attached events
|
||||
switch(div) {
|
||||
// Login tool
|
||||
case 'loginer':
|
||||
current_sel.find('a.to-anonymous').click(function() {
|
||||
return self.change('anonymouser');
|
||||
});
|
||||
|
||||
current_sel.find('a.advanced').click(self.showAdvanced);
|
||||
current_sel.find('form').submit(self.loginForm);
|
||||
|
||||
break;
|
||||
|
||||
// Anonymous login tool
|
||||
case 'anonymouser':
|
||||
current_sel.find('a.to-home').click(function() {
|
||||
return self.change('loginer');
|
||||
});
|
||||
|
||||
current_sel.find('form').submit(Connection.doAnonymous);
|
||||
|
||||
// Keyup event on anonymous join's room input
|
||||
current_sel.find('input.room').keyup(function() {
|
||||
var value = $(this).val();
|
||||
var report_sel = current_sel.find('.report');
|
||||
var span_sel = current_sel.find('span');
|
||||
|
||||
if(!value) {
|
||||
report_sel.hide();
|
||||
span_sel.text('');
|
||||
} else {
|
||||
report_sel.show();
|
||||
span_sel.text(JAPPIX_LOCATION + '?r=' + value);
|
||||
}
|
||||
});
|
||||
|
||||
break;
|
||||
|
||||
// Register tool
|
||||
case 'registerer':
|
||||
// Server input change
|
||||
$('#home input.server').keyup(function(e) {
|
||||
if($.trim($(this).val()) == HOST_MAIN) {
|
||||
$('#home .captcha_grp').show();
|
||||
$('#home input.captcha').removeAttr('disabled');
|
||||
} else {
|
||||
$('#home .captcha_grp').hide();
|
||||
$('#home input.captcha').attr('disabled', true);
|
||||
}
|
||||
});
|
||||
|
||||
// Register input placeholder
|
||||
// FIXME: breaks IE compatibility
|
||||
//$('#home input[placeholder]').placeholder();
|
||||
|
||||
// Register form submit
|
||||
current_sel.find('form').submit(self.registerForm);
|
||||
|
||||
break;
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Home._eventsChange', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create obsolete form
|
||||
* @private
|
||||
* @param {string} home
|
||||
* @param {string} locale
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._obsolete = function(home, locale) {
|
||||
|
||||
try {
|
||||
// Add the code
|
||||
$(locale).after(
|
||||
'<div class="obsolete">' +
|
||||
'<p>' + Common._e("Your browser is out of date!") + '</p>' +
|
||||
|
||||
'<a class="firefox browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Mozilla Firefox') + '" href="http://www.mozilla.com/firefox/"></a>' +
|
||||
'<a class="chrome browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Google Chrome') + '" href="http://www.google.com/chrome"></a>' +
|
||||
'<a class="safari browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Safari') + '" href="http://www.apple.com/safari/"></a>' +
|
||||
'<a class="opera browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Opera') + '" href="http://www.opera.com/"></a>' +
|
||||
'<a class="ie browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Internet Explorer') + '" href="http://www.microsoft.com/hk/windows/internet-explorer/"></a>' +
|
||||
'</div>'
|
||||
);
|
||||
|
||||
// Display it later
|
||||
$(home + '.obsolete').oneTime('1s', function() {
|
||||
$(this).slideDown();
|
||||
});
|
||||
|
||||
Console.warn('Jappix does not support this browser!');
|
||||
} catch(e) {
|
||||
Console.error('Home._obsolete', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Allows the user to switch the difference home page elements
|
||||
* @public
|
||||
|
@ -33,19 +146,19 @@ var Home = (function () {
|
|||
var home = '#home .';
|
||||
var right = home + 'right ';
|
||||
var current = right + '.homediv.' + div;
|
||||
|
||||
|
||||
// We switch the div
|
||||
$(right + '.homediv, ' + right + '.top').hide();
|
||||
$(right + '.' + div).show();
|
||||
|
||||
|
||||
// We reset the homedivs
|
||||
$(home + 'homediv:not(.default), ' + home + 'top:not(.default)').remove();
|
||||
|
||||
|
||||
// Get the HTML code to display
|
||||
var disable_form = '';
|
||||
var lock_host = '';
|
||||
var code = '';
|
||||
|
||||
|
||||
// Apply the previous link
|
||||
switch(div) {
|
||||
case 'loginer':
|
||||
|
@ -54,196 +167,144 @@ var Home = (function () {
|
|||
if(!Common.exists(right + '.top.sub')) {
|
||||
// Append the HTML code for previous link
|
||||
$(right + '.top.default').after('<h1 class="top sub loginer anonymouser registerer">« <a href="#" class="previous">' + Common._e("Previous") + '</a></h1>');
|
||||
|
||||
|
||||
// Click event on previous link
|
||||
$(home + 'top.sub a.previous').click(function() {
|
||||
return self.change('default');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Apply the form
|
||||
switch(div) {
|
||||
// Login tool
|
||||
case 'loginer':
|
||||
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>' +
|
||||
|
||||
'<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!") + '" />' +
|
||||
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>' +
|
||||
|
||||
'<div class="clear"></div>' +
|
||||
'</div>' +
|
||||
'<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="" 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>';
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
// Anonymous login tool
|
||||
case 'anonymouser':
|
||||
disable_form = Utils.disableInput(ANONYMOUS, 'off');
|
||||
code = '<p>' + Common.printf(Common._e("Enter the groupchat you want to join and the nick you want to have. You can also go back to the %s."), '<a href="#" class="to-home">' + Common._e("login page") + '</a>') + '</p>';
|
||||
|
||||
if(LEGAL)
|
||||
|
||||
if(LEGAL) {
|
||||
code += '<p>' + Common.printf(Common._e("By using our service, you accept %s."), '<b><a href="' + Common.encodeQuotes(LEGAL) + '" target="_blank">' + Common._e("our terms of use") + '</a></b>') + '</p>';
|
||||
|
||||
code += '<form action="#" method="post">' +
|
||||
'<fieldset>' +
|
||||
'<legend>' + Common._e("Required") + '</legend>' +
|
||||
|
||||
'<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="" />' +
|
||||
'</fieldset>' +
|
||||
|
||||
'<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>' +
|
||||
}
|
||||
|
||||
code += '<form action="#" method="post">' +
|
||||
'<fieldset>' +
|
||||
'<legend>' + Common._e("Required") + '</legend>' +
|
||||
|
||||
'<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="" />' +
|
||||
'</fieldset>' +
|
||||
|
||||
'<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>';
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
// Register tool
|
||||
case 'registerer':
|
||||
disable_form = Utils.disableInput(REGISTRATION, 'off');
|
||||
|
||||
if(!disable_form)
|
||||
|
||||
if(!disable_form) {
|
||||
lock_host = Utils.disableInput(LOCK_HOST, 'on');
|
||||
|
||||
}
|
||||
|
||||
code = '<p>' + Common._e("Register a new XMPP account to join your friends on your own social cloud. That's simple!") + '</p>';
|
||||
|
||||
if(LEGAL)
|
||||
|
||||
if(LEGAL) {
|
||||
code += '<p>' + Common.printf(Common._e("By using our service, you accept %s."), '<b><a href="' + Common.encodeQuotes(LEGAL) + '" target="_blank">' + Common._e("our terms of use") + '</a></b>') + '</p>';
|
||||
|
||||
code += '<form action="#" method="post">' +
|
||||
'<fieldset>' +
|
||||
'<legend>' + Common._e("Required") + '</legend>' +
|
||||
|
||||
'<label for="rnick">' + Common._e("Address") + '</label>' +
|
||||
'<input type="text" class="nick" id="rnick" ' + disable_form + ' pattern="[^@/]+" required="" placeholder="' + Common._e("Username") + '" /><span class="jid">@</span><input type="text" class="server" id="rserver" value="' + HOST_MAIN + '" ' + disable_form + lock_host + ' pattern="[^@/]+" required="" placeholder="' + Common._e("Server") + '" />' +
|
||||
'<label for="rpassword">' + Common._e("Password") + '</label>' +
|
||||
}
|
||||
|
||||
code += '<form action="#" method="post">' +
|
||||
'<fieldset>' +
|
||||
'<legend>' + Common._e("Required") + '</legend>' +
|
||||
|
||||
'<label for="rnick">' + Common._e("Address") + '</label>' +
|
||||
'<input type="text" class="nick" id="rnick" ' + disable_form + ' pattern="[^@/]+" required="" placeholder="' + Common._e("Username") + '" /><span class="jid">@</span><input type="text" class="server" id="rserver" value="' + HOST_MAIN + '" ' + disable_form + lock_host + ' pattern="[^@/]+" required="" list="server" placeholder="' + Common._e("Server") + '" />' +
|
||||
'<label for="rpassword">' + Common._e("Password") + '</label>' +
|
||||
'<input type="password" class="password" id="rpassword" ' + disable_form + ' required="" placeholder="' + Common._e("Enter password") + '" /><input type="password" class="spassword" id="spassword" ' + disable_form + ' required="" placeholder="' + Common._e("Once again...") + '" />';
|
||||
|
||||
if(REGISTER_API == 'on')
|
||||
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="" />' +
|
||||
|
||||
if(REGISTER_API == 'on') {
|
||||
code += '<div class="captcha_grp">' +
|
||||
'<label for="captcha">' + Common._e("Code") + '</label><input type="text" class="captcha" id="captcha" ' + disable_form + ' maxlength="6" pattern="[a-zA-Z0-9]{6}" required="" placeholder="' + Common._e("Security code") + '" /><img class="captcha_img" src="./server/captcha.php?id=' + genID() + '" alt="" />' +
|
||||
'</div>';
|
||||
|
||||
code += '</fieldset>' +
|
||||
|
||||
'<input type="submit" value="' + Common._e("Here we go!") + '" ' + disable_form + '/>' +
|
||||
}
|
||||
|
||||
code += '</fieldset>' +
|
||||
|
||||
'<input type="submit" value="' + Common._e("Here we go!") + '" ' + disable_form + '/>' +
|
||||
'</form>';
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Form disabled?
|
||||
if(disable_form)
|
||||
code += '<div class="info fail">' +
|
||||
Common._e("This tool has been disabled!") +
|
||||
if(disable_form) {
|
||||
code += '<div class="info fail">' +
|
||||
Common._e("This tool has been disabled!") +
|
||||
'</div>';
|
||||
|
||||
}
|
||||
|
||||
// Create this HTML code
|
||||
if(code && !Common.exists(current)) {
|
||||
// Append it!
|
||||
$(right + '.homediv.default').after('<div class="' + div + ' homediv">' + code + '</div>');
|
||||
|
||||
// Create the attached events
|
||||
switch(div) {
|
||||
// Login tool
|
||||
case 'loginer':
|
||||
$(current + ' a.to-anonymous').click(function() {
|
||||
return self.change('anonymouser');
|
||||
});
|
||||
|
||||
$(current + ' a.advanced').click(self.showAdvanced);
|
||||
$(current + ' form').submit(self.loginForm);
|
||||
|
||||
break;
|
||||
|
||||
// Anonymous login tool
|
||||
case 'anonymouser':
|
||||
$(current + ' a.to-home').click(function() {
|
||||
return self.change('loginer');
|
||||
});
|
||||
|
||||
$(current + ' form').submit(Connection.doAnonymous);
|
||||
|
||||
// Keyup event on anonymous join's room input
|
||||
$(current + ' input.room').keyup(function() {
|
||||
var value = $(this).val();
|
||||
var report = current + ' .report';
|
||||
var span = report + ' span';
|
||||
|
||||
if(!value) {
|
||||
$(report).hide();
|
||||
$(span).text('');
|
||||
}
|
||||
|
||||
else {
|
||||
$(report).show();
|
||||
$(span).text(JAPPIX_LOCATION + '?r=' + value);
|
||||
}
|
||||
});
|
||||
|
||||
break;
|
||||
|
||||
// Register tool
|
||||
case 'registerer':
|
||||
// Server input change
|
||||
$('#home input.server').keyup(function(e) {
|
||||
if($.trim($(this).val()) == HOST_MAIN) {
|
||||
$('#home .captcha_grp').show();
|
||||
$('#home input.captcha').removeAttr('disabled');
|
||||
} else {
|
||||
$('#home .captcha_grp').hide();
|
||||
$('#home input.captcha').attr('disabled', true);
|
||||
}
|
||||
});
|
||||
|
||||
// Register input placeholder
|
||||
// FIXME: breaks IE compatibility
|
||||
//$('#home input[placeholder]').placeholder();
|
||||
|
||||
// Register form submit
|
||||
$(current + ' form').submit(self.registerForm);
|
||||
|
||||
break;
|
||||
}
|
||||
$(right + '.homediv.default').after(
|
||||
'<div class="' + div + ' homediv">' + code + '</div>'
|
||||
);
|
||||
|
||||
self._eventsChange(
|
||||
$(current),
|
||||
div
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// We focus on the first input
|
||||
$(document).oneTime(10, function() {
|
||||
$(right + 'input:visible:first').focus();
|
||||
|
@ -267,7 +328,7 @@ var Home = (function () {
|
|||
try {
|
||||
// Hide the link
|
||||
$('#home a.advanced').hide();
|
||||
|
||||
|
||||
// Show the fieldset
|
||||
$('#home fieldset.advanced').show();
|
||||
} catch(e) {
|
||||
|
@ -288,27 +349,29 @@ var Home = (function () {
|
|||
|
||||
try {
|
||||
// We get the values
|
||||
var lPath = '#home .loginer ';
|
||||
var lServer = $(lPath + '.server').val();
|
||||
var lNick = Common.nodeprep($(lPath + '.nick').val());
|
||||
var lPass = $(lPath + '.password').val();
|
||||
var lResource = $(lPath + '.resource').val();
|
||||
var lPriority = $(lPath + '.priority').val();
|
||||
var lRemember = $(lPath + '.remember').filter(':checked').size();
|
||||
|
||||
var path_sel = $('#home .loginer');
|
||||
|
||||
var lServer = path_sel.find('.server').val();
|
||||
var lNick = Common.nodeprep(path_sel.find('.nick').val());
|
||||
var lPass = path_sel.find('.password').val();
|
||||
var lResource = path_sel.find('.resource').val();
|
||||
var lPriority = path_sel.find('.priority').val();
|
||||
var lRemember = path_sel.find('.remember').filter(':checked').size();
|
||||
|
||||
// Enough values?
|
||||
if(lServer && lNick && lPass && lResource && lPriority) {
|
||||
Connection.doLogin(lNick, lServer, lPass, lResource, lPriority, lRemember);
|
||||
} else {
|
||||
$(lPath + 'input[type="text"], ' + lPath + 'input[type="password"]').each(function() {
|
||||
var select = $(this);
|
||||
|
||||
if(!select.val())
|
||||
|
||||
if(!select.val()) {
|
||||
$(document).oneTime(10, function() {
|
||||
select.addClass('please-complete').focus();
|
||||
});
|
||||
else
|
||||
select.removeClass('please-complete');
|
||||
} else {
|
||||
select.removeClass('please-complete');
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch(e) {
|
||||
|
@ -328,38 +391,40 @@ var Home = (function () {
|
|||
self.registerForm = function() {
|
||||
|
||||
try {
|
||||
var rPath = '#home .registerer ';
|
||||
|
||||
var path = '#home .registerer';
|
||||
var path_sel = $(path);
|
||||
|
||||
// Remove the success info
|
||||
$(rPath + '.success').remove();
|
||||
|
||||
path_sel.find('.success').remove();
|
||||
|
||||
// Get the values
|
||||
var username = Common.nodeprep($(rPath + '.nick').val());
|
||||
var domain = $(rPath + '.server').val();
|
||||
var pass = $(rPath + '.password').val();
|
||||
var spass = $(rPath + '.spassword').val();
|
||||
var captcha = $(rPath + '.captcha').val();
|
||||
|
||||
var username = Common.nodeprep(path_sel.find('.nick').val());
|
||||
var domain = path_sel.find('.server').val();
|
||||
var pass = path_sel.find('.password').val();
|
||||
var spass = path_sel.find('.spassword').val();
|
||||
var captcha = path_sel.find('.captcha').val();
|
||||
|
||||
// Enough values?
|
||||
if(domain && username && pass && spass && (pass == spass) && !((REGISTER_API == 'on') && (domain == HOST_MAIN) && !captcha)) {
|
||||
// We remove the not completed class to avoid problems
|
||||
$('#home .registerer input').removeClass('please-complete');
|
||||
|
||||
|
||||
// Fire the register event!
|
||||
Connection.doRegister(username, domain, pass, captcha);
|
||||
}
|
||||
|
||||
|
||||
// Something is missing?
|
||||
else {
|
||||
$(rPath + 'input[type="text"], ' + rPath + 'input[type="password"]').each(function() {
|
||||
$(path + ' input[type="text"], ' + path + ' input[type="password"]').each(function() {
|
||||
var select = $(this);
|
||||
|
||||
if(!select.val() || (select.is('#spassword') && pass && (pass != spass)))
|
||||
|
||||
if(!select.val() || (select.is('#spassword') && pass && (pass != spass))) {
|
||||
$(document).oneTime(10, function() {
|
||||
select.addClass('please-complete').focus();
|
||||
});
|
||||
else
|
||||
select.removeClass('please-complete');
|
||||
} else {
|
||||
select.removeClass('please-complete');
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch(e) {
|
||||
|
@ -387,76 +452,61 @@ var Home = (function () {
|
|||
var corp = home + '.corporation';
|
||||
var aboutus = home + '.aboutus';
|
||||
var locale = home + '.locale';
|
||||
|
||||
|
||||
// Removes the <noscript /> elements to lighten the DOM
|
||||
$('noscript').remove();
|
||||
|
||||
|
||||
// Allows the user to switch the home page
|
||||
$(button).click(function() {
|
||||
// Login button
|
||||
if($(this).is('.login'))
|
||||
if($(this).is('.login')) {
|
||||
return self.change('loginer');
|
||||
|
||||
}
|
||||
|
||||
// Register button
|
||||
else
|
||||
else {
|
||||
return self.change('registerer');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Allows the user to view the corporation & about infobox
|
||||
$(corp + ', ' + aboutus).hover(function() {
|
||||
$(this).addClass('hovered');
|
||||
}, function() {
|
||||
$(this).removeClass('hovered');
|
||||
});
|
||||
|
||||
|
||||
// Allows the user to switch the language
|
||||
$(locale).hover(function() {
|
||||
// Initialize the HTML code
|
||||
var keepget = $(locale).attr('data-keepget');
|
||||
var html = '<div class="list">';
|
||||
|
||||
|
||||
// Generate each locale HTML code
|
||||
for(var i in LOCALES_AVAILABLE_ID) {
|
||||
html += '<a href="./?l=' + LOCALES_AVAILABLE_ID[i] + keepget + '">' + LOCALES_AVAILABLE_NAMES[i].htmlEnc() + '</a>';
|
||||
}
|
||||
|
||||
|
||||
html += '</div>';
|
||||
|
||||
|
||||
// Append the HTML code
|
||||
$(locale).append(html);
|
||||
}, function() {
|
||||
$(locale + ' .list').remove();
|
||||
});
|
||||
|
||||
|
||||
// Disables the browser HTTP-requests stopper
|
||||
$(document).keydown(function(e) {
|
||||
if((e.keyCode == 27) && !System.isDeveloper())
|
||||
if((e.keyCode == 27) && !System.isDeveloper()) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Warns for an obsolete browser
|
||||
if(Utils.isObsolete()) {
|
||||
// Add the code
|
||||
$(locale).after(
|
||||
'<div class="obsolete">' +
|
||||
'<p>' + Common._e("Your browser is out of date!") + '</p>' +
|
||||
|
||||
'<a class="firefox browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Mozilla Firefox') + '" href="http://www.mozilla.com/firefox/"></a>' +
|
||||
'<a class="chrome browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Google Chrome') + '" href="http://www.google.com/chrome"></a>' +
|
||||
'<a class="safari browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Safari') + '" href="http://www.apple.com/safari/"></a>' +
|
||||
'<a class="opera browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Opera') + '" href="http://www.opera.com/"></a>' +
|
||||
'<a class="ie browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Internet Explorer') + '" href="http://www.microsoft.com/hk/windows/internet-explorer/"></a>' +
|
||||
'</div>'
|
||||
);
|
||||
|
||||
// Display it later
|
||||
$(home + '.obsolete').oneTime('1s', function() {
|
||||
$(this).slideDown();
|
||||
});
|
||||
|
||||
Console.warn('Jappix does not support this browser!');
|
||||
self._obsolete();
|
||||
}
|
||||
|
||||
|
||||
Console.log('Welcome to Jappix! Happy coding in developer mode!');
|
||||
});
|
||||
} catch(e) {
|
||||
|
@ -473,4 +523,4 @@ var Home = (function () {
|
|||
|
||||
})();
|
||||
|
||||
Home.launch();
|
||||
Home.launch();
|
||||
|
|
|
@ -34,8 +34,6 @@ var HTTPAuth = (function () {
|
|||
try {
|
||||
// We add the login wait div
|
||||
Interface.showGeneralWait();
|
||||
|
||||
oArgs = {};
|
||||
|
||||
if(Common.hasWebSocket()) {
|
||||
// WebSocket supported & configured
|
||||
|
@ -47,60 +45,58 @@ var HTTPAuth = (function () {
|
|||
|
||||
// Check BOSH origin
|
||||
BOSH_SAME_ORIGIN = Origin.isSame(httpbase);
|
||||
|
||||
|
||||
// We create the new http-binding connection
|
||||
con = new JSJaCHttpBindingConnection({
|
||||
httpbase: httpbase
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// And we handle everything that happen
|
||||
Connection.setupCon(con);
|
||||
|
||||
|
||||
// Generate a resource
|
||||
var random_resource = DataStore.getDB(Connection.desktop_hash, 'session', 'resource');
|
||||
|
||||
|
||||
if(!random_resource) {
|
||||
random_resource = JAPPIX_RESOURCE + ' (' + (new Date()).getTime() + ')';
|
||||
}
|
||||
|
||||
|
||||
// Generate a priority
|
||||
lPriority = lPriority ? lPriority : 10;
|
||||
|
||||
// We retrieve what the user typed in the login inputs
|
||||
oArgs = {};
|
||||
oArgs.domain = $.trim(lServer);
|
||||
oArgs.username = $.trim(lNick);
|
||||
oArgs.resource = random_resource;
|
||||
oArgs.pass = lPass;
|
||||
oArgs.secure = true;
|
||||
oArgs.xmllang = XML_LANG;
|
||||
|
||||
// Store the resource (for reconnection)
|
||||
DataStore.setDB(Connection.desktop_hash, 'session', 'resource', random_resource);
|
||||
|
||||
|
||||
// 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>';
|
||||
|
||||
|
||||
// Save the session parameters (for reconnect if network issue)
|
||||
Connection.current_session = session_xml;
|
||||
|
||||
|
||||
// We store the infos of the user into the data-base
|
||||
DataStore.setDB(Connection.desktop_hash, 'priority', 1, 10);
|
||||
|
||||
|
||||
// We connect !
|
||||
con.connect(oArgs);
|
||||
|
||||
con.connect({
|
||||
'domain': $.trim(lServer),
|
||||
'username': $.trim(lNick),
|
||||
'resource': random_resource,
|
||||
'pass': lPass,
|
||||
'secure': true,
|
||||
'xmllang': XML_LANG
|
||||
});
|
||||
|
||||
// Change the page title
|
||||
Interface.title('wait');
|
||||
|
||||
|
||||
Console.info('Jappix is connecting...');
|
||||
} catch(e) {
|
||||
Console.error('HTTPAuth.go', e);
|
||||
|
||||
// Reset Jappix
|
||||
Talk.destroy();
|
||||
|
||||
|
||||
// Open an unknown error
|
||||
Board.openThisError(2);
|
||||
} finally {
|
||||
|
|
|
@ -37,23 +37,31 @@ var HTTPReply = (function () {
|
|||
var id = confirm.attr('id');
|
||||
var method = confirm.attr('method');
|
||||
var url = confirm.attr('url');
|
||||
|
||||
|
||||
// We generate the reply message
|
||||
var aMsg = new JSJaCMessage();
|
||||
aMsg.setTo(from);
|
||||
|
||||
|
||||
// If "no"
|
||||
if(value == 'no') {
|
||||
aMsg.setType('error');
|
||||
aMsg.appendNode('error', {'code': '401', 'type': 'auth'});
|
||||
aMsg.appendNode('error', {
|
||||
'code': '401',
|
||||
'type': 'auth'
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// We set the confirm node
|
||||
aMsg.appendNode('confirm', {'xmlns': xmlns, 'url': url, 'id': id, 'method': method});
|
||||
|
||||
aMsg.appendNode('confirm', {
|
||||
'xmlns': xmlns,
|
||||
'url': url,
|
||||
'id': id,
|
||||
'method': method
|
||||
});
|
||||
|
||||
// We send the message
|
||||
con.send(aMsg, Errors.handleReply);
|
||||
|
||||
|
||||
Console.info('Replying HTTP auth request: ' + from);
|
||||
} catch(e) {
|
||||
Console.error('HTTPReply.go', e);
|
||||
|
|
|
@ -29,69 +29,69 @@ var Inbox = (function () {
|
|||
|
||||
try {
|
||||
// Popup HTML content
|
||||
var html =
|
||||
'<div class="top">' + Common._e("Your inbox") + '</div>' +
|
||||
|
||||
'<div class="content">' +
|
||||
'<div class="head inbox-head">' +
|
||||
'<div class="head-text inbox-head-text">' + Common._e("Available actions") + '</div>' +
|
||||
|
||||
'<div class="head-actions inbox-head-actions">' +
|
||||
'<a href="#" class="a-delete-messages">' + Common._e("Clean") + '</a>' +
|
||||
'<a href="#" class="a-new-message">' + Common._e("New") + '</a>' +
|
||||
'<a href="#" class="a-show-messages">' + Common._e("Received") + '</a>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="inbox-results">' +
|
||||
'<p class="inbox-noresults">' + Common._e("Your inbox is empty.") + '</p>' +
|
||||
|
||||
'<div class="inbox"></div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="inbox-new">' +
|
||||
'<div class="inbox-new-to inbox-new-block search">' +
|
||||
'<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="" />' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="inbox-new-topic inbox-new-block">' +
|
||||
'<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="" />' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="inbox-new-body inbox-new-block">' +
|
||||
'<p class="inbox-new-text">' + Common._e("Content") + '</p>' +
|
||||
|
||||
'<textarea class="inbox-new-textarea" rows="8" cols="60" required=""></textarea>' +
|
||||
'</div>' +
|
||||
|
||||
'<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>' +
|
||||
|
||||
Interface.generateFileShare() +
|
||||
'</form>' +
|
||||
|
||||
'<div class="inbox-new-send inbox-new-block">' +
|
||||
'<a href="#" class="send one-button talk-images">' + Common._e("Send message") + '</a>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="bottom">' +
|
||||
'<div class="wait wait-medium"></div>' +
|
||||
|
||||
'<a href="#" class="finish">' + Common._e("Close") + '</a>' +
|
||||
var html =
|
||||
'<div class="top">' + Common._e("Your inbox") + '</div>' +
|
||||
|
||||
'<div class="content">' +
|
||||
'<div class="head inbox-head">' +
|
||||
'<div class="head-text inbox-head-text">' + Common._e("Available actions") + '</div>' +
|
||||
|
||||
'<div class="head-actions inbox-head-actions">' +
|
||||
'<a href="#" class="a-delete-messages">' + Common._e("Clean") + '</a>' +
|
||||
'<a href="#" class="a-new-message">' + Common._e("New") + '</a>' +
|
||||
'<a href="#" class="a-show-messages">' + Common._e("Received") + '</a>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="inbox-results">' +
|
||||
'<p class="inbox-noresults">' + Common._e("Your inbox is empty.") + '</p>' +
|
||||
|
||||
'<div class="inbox"></div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="inbox-new">' +
|
||||
'<div class="inbox-new-to inbox-new-block search">' +
|
||||
'<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="" />' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="inbox-new-topic inbox-new-block">' +
|
||||
'<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="" />' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="inbox-new-body inbox-new-block">' +
|
||||
'<p class="inbox-new-text">' + Common._e("Content") + '</p>' +
|
||||
|
||||
'<textarea class="inbox-new-textarea" rows="8" cols="60" required=""></textarea>' +
|
||||
'</div>' +
|
||||
|
||||
'<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>' +
|
||||
|
||||
Interface.generateFileShare() +
|
||||
'</form>' +
|
||||
|
||||
'<div class="inbox-new-send inbox-new-block">' +
|
||||
'<a href="#" class="send one-button talk-images">' + Common._e("Send message") + '</a>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="bottom">' +
|
||||
'<div class="wait wait-medium"></div>' +
|
||||
|
||||
'<a href="#" class="finish">' + Common._e("Close") + '</a>' +
|
||||
'</div>';
|
||||
|
||||
|
||||
// Create the popup
|
||||
Popup.create('inbox', html);
|
||||
|
||||
|
||||
// Associate the events
|
||||
self.instance();
|
||||
|
||||
|
||||
// Load the messages
|
||||
self.load();
|
||||
} catch(e) {
|
||||
|
@ -134,10 +134,10 @@ var Inbox = (function () {
|
|||
// Open things
|
||||
self.open();
|
||||
self.newMessage();
|
||||
|
||||
|
||||
// Apply XID
|
||||
$('#inbox .inbox-new-to-input').val(xid);
|
||||
|
||||
|
||||
// Focus to the next item
|
||||
$(document).oneTime(10, function() {
|
||||
$('#inbox .inbox-new-subject-input').focus();
|
||||
|
@ -163,33 +163,32 @@ var Inbox = (function () {
|
|||
iq.setType('set');
|
||||
var query = iq.setQuery(NS_PRIVATE);
|
||||
var storage = query.appendChild(iq.buildNode('storage', {'xmlns': NS_INBOX}));
|
||||
|
||||
|
||||
var db_regex = new RegExp(('^' + Connection.desktop_hash + '_') + 'inbox' + ('_(.+)'));
|
||||
|
||||
for(var i = 0; i < DataStore.storageDB.length; i++) {
|
||||
// Get the pointer values
|
||||
var current = DataStore.storageDB.key(i);
|
||||
|
||||
|
||||
// If the pointer is on a stored message
|
||||
if(current.match(db_regex)) {
|
||||
// Get the values
|
||||
var value = $(Common.XMLFromString(DataStore.storageDB.getItem(current)));
|
||||
|
||||
|
||||
// Create the storage node
|
||||
storage.appendChild(iq.buildNode('message', {
|
||||
'id': value.find('id').text().revertHtmlEnc(),
|
||||
'from': value.find('from').text().revertHtmlEnc(),
|
||||
'subject': value.find('subject').text().revertHtmlEnc(),
|
||||
'status': value.find('status').text().revertHtmlEnc(),
|
||||
'date': value.find('date').text().revertHtmlEnc(),
|
||||
'xmlns': NS_INBOX
|
||||
},
|
||||
|
||||
value.find('content').text().revertHtmlEnc()
|
||||
));
|
||||
storage.appendChild(
|
||||
iq.buildNode('message', {
|
||||
'id': value.find('id').text().revertHtmlEnc(),
|
||||
'from': value.find('from').text().revertHtmlEnc(),
|
||||
'subject': value.find('subject').text().revertHtmlEnc(),
|
||||
'status': value.find('status').text().revertHtmlEnc(),
|
||||
'date': value.find('date').text().revertHtmlEnc(),
|
||||
'xmlns': NS_INBOX
|
||||
}, value.find('content').text().revertHtmlEnc()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
con.send(iq);
|
||||
} catch(e) {
|
||||
Console.error('Inbox.store', e);
|
||||
|
@ -207,20 +206,20 @@ var Inbox = (function () {
|
|||
|
||||
try {
|
||||
// Init
|
||||
var mPath = '#inbox .';
|
||||
|
||||
var inbox_sel = $('#inbox');
|
||||
|
||||
// Reset the previous buddy search
|
||||
Search.resetBuddy('#inbox .inbox-new-to');
|
||||
|
||||
|
||||
// We switch the divs
|
||||
$(mPath + 'inbox-results, #inbox .a-new-message, #inbox .a-delete-messages').hide();
|
||||
$(mPath + 'inbox-new, #inbox .a-show-messages').show();
|
||||
|
||||
inbox_sel.find('.inbox-results, .a-new-message, .a-delete-messages').hide();
|
||||
inbox_sel.find('.inbox-new, .a-show-messages').show();
|
||||
|
||||
// We focus on the first input
|
||||
$(document).oneTime(10, function() {
|
||||
$(mPath + 'inbox-new-to-input').focus();
|
||||
inbox_sel.find('.inbox-new-to-input').focus();
|
||||
});
|
||||
|
||||
|
||||
// We reset some stuffs
|
||||
self.cleanNewMessage();
|
||||
} catch(e) {
|
||||
|
@ -230,7 +229,7 @@ var Inbox = (function () {
|
|||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Cleans the inbox
|
||||
|
@ -241,16 +240,16 @@ var Inbox = (function () {
|
|||
|
||||
try {
|
||||
// Init
|
||||
var mPath = '#inbox .';
|
||||
|
||||
var inbox_sel = $('#inbox');
|
||||
|
||||
// We reset the forms
|
||||
$(mPath + 'inbox-new-block:not(form) input, ' + mPath + 'inbox-new textarea').val('').removeClass('please-complete');
|
||||
$(mPath + 'inbox-new-file a').remove();
|
||||
$(mPath + 'inbox-new-file input').show();
|
||||
|
||||
inbox_sel.find('.inbox-new-block:not(form) input, .inbox-new textarea').val('').removeClass('please-complete');
|
||||
inbox_sel.find('.inbox-new-file a').remove();
|
||||
inbox_sel.find('.inbox-new-file input').show();
|
||||
|
||||
// We close an eventual opened message
|
||||
$(mPath + 'message-content').remove();
|
||||
$(mPath + 'one-message').removeClass('message-reading');
|
||||
inbox_sel.find('.message-content').remove();
|
||||
inbox_sel.find('.one-message').removeClass('message-reading');
|
||||
} catch(e) {
|
||||
Console.error('Inbox.cleanNewMessage', e);
|
||||
}
|
||||
|
@ -270,26 +269,26 @@ var Inbox = (function () {
|
|||
|
||||
try {
|
||||
// We send the message
|
||||
var mess = new JSJaCMessage();
|
||||
|
||||
var message = new JSJaCMessage();
|
||||
|
||||
// Main attributes
|
||||
mess.setTo(to);
|
||||
mess.setSubject(subject);
|
||||
mess.setType('normal');
|
||||
|
||||
message.setTo(to);
|
||||
message.setSubject(subject);
|
||||
message.setType('normal');
|
||||
|
||||
// Any file to attach?
|
||||
var attached = '#inbox .inbox-new-file a.file';
|
||||
|
||||
|
||||
if(Common.exists(attached)) {
|
||||
body += '\n' +
|
||||
'\n' +
|
||||
$(attached).attr('data-attachedtitle') + ' - ' + $(attached).attr('data-attachedhref');
|
||||
body += '\n' +
|
||||
'\n' +
|
||||
$(attached).attr('data-attachedtitle') + ' - ' + $(attached).attr('data-attachedhref');
|
||||
}
|
||||
|
||||
|
||||
// Set body
|
||||
mess.setBody(body);
|
||||
|
||||
con.send(mess, Errors.handleReply);
|
||||
message.setBody(body);
|
||||
|
||||
con.send(message, Errors.handleReply);
|
||||
} catch(e) {
|
||||
Console.error('Inbox.sendMessage', e);
|
||||
}
|
||||
|
@ -306,54 +305,54 @@ var Inbox = (function () {
|
|||
|
||||
try {
|
||||
// We get some informations
|
||||
var mPath = '#inbox ';
|
||||
var to = $(mPath + '.inbox-new-to-input').val();
|
||||
var body = $(mPath + '.inbox-new-textarea').val();
|
||||
var subject = $(mPath + '.inbox-new-subject-input').val();
|
||||
|
||||
var inbox_sel = $('#inbox');
|
||||
var to = inbox_sel.find('.inbox-new-to-input').val();
|
||||
var body = inbox_sel.find('.inbox-new-textarea').val();
|
||||
var subject = inbox_sel.find('.inbox-new-subject-input').val();
|
||||
|
||||
if(to && body && subject) {
|
||||
// New array of XID
|
||||
var xid = new Array(to);
|
||||
|
||||
|
||||
// More than one XID
|
||||
if(to.indexOf(',') != -1) {
|
||||
xid = to.split(',');
|
||||
}
|
||||
|
||||
|
||||
for(var i in xid) {
|
||||
var current = xid[i];
|
||||
|
||||
|
||||
// No current value?
|
||||
if(!current || current.match(/^(\s+)$/))
|
||||
continue;
|
||||
|
||||
|
||||
// Edit the XID if needed
|
||||
current = current.replace(/ /g, '');
|
||||
current = Common.generateXID(current, 'chat');
|
||||
|
||||
|
||||
// We send the message
|
||||
self.sendMessage(current, subject, body);
|
||||
|
||||
|
||||
// We clean the inputs
|
||||
self.cleanNewMessage();
|
||||
|
||||
|
||||
Console.info('Inbox message sent: ' + current);
|
||||
}
|
||||
|
||||
|
||||
// Close the inbox
|
||||
self.close();
|
||||
}
|
||||
|
||||
|
||||
else {
|
||||
$(mPath + 'input[type="text"], ' + mPath + 'textarea').each(function() {
|
||||
var current = this;
|
||||
|
||||
if(!$(current).val()) {
|
||||
inbox_sel.find('input[type="text"], textarea').each(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
if(!this_sel.val()) {
|
||||
$(document).oneTime(10, function() {
|
||||
$(current).addClass('please-complete').focus();
|
||||
this_sel.addClass('please-complete').focus();
|
||||
});
|
||||
} else {
|
||||
$(current).removeClass('please-complete');
|
||||
this_sel.removeClass('please-complete');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -374,18 +373,17 @@ var Inbox = (function () {
|
|||
self.showMessage = function() {
|
||||
|
||||
try {
|
||||
// Init
|
||||
var mPath = '#inbox .';
|
||||
|
||||
var inbox_sel = $('#inbox');
|
||||
|
||||
// We switch the divs
|
||||
$(mPath + 'inbox-new').hide();
|
||||
$(mPath + 'inbox-results').show();
|
||||
|
||||
inbox_sel.find('.inbox-new').hide();
|
||||
inbox_sel.find('.inbox-results').show();
|
||||
|
||||
// We show a new link in the menu
|
||||
$(mPath + 'a-show-messages').hide();
|
||||
$(mPath + 'a-delete-messages').show();
|
||||
$(mPath + 'a-new-message').show();
|
||||
|
||||
inbox_sel.find('.a-show-messages').hide();
|
||||
inbox_sel.find('.a-delete-messages').show();
|
||||
inbox_sel.find('.a-new-message').show();
|
||||
|
||||
// We reset some stuffs
|
||||
self.cleanNewMessage();
|
||||
} catch(e) {
|
||||
|
@ -414,50 +412,50 @@ var Inbox = (function () {
|
|||
// Generate some paths
|
||||
var inbox = '#inbox .';
|
||||
var one_message = inbox + 'one-message.' + id;
|
||||
|
||||
|
||||
// Message yet displayed!
|
||||
if(Common.exists(one_message)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Get the nearest element
|
||||
var stamp = DateUtils.extractStamp(Date.jab2date(date));
|
||||
var nearest = Search.sortElementByStamp(stamp, '#inbox .one-message');
|
||||
|
||||
|
||||
// Get the buddy name
|
||||
var name = Name.getBuddy(from).htmlEnc();
|
||||
|
||||
|
||||
// We generate the html code
|
||||
var nContent = '<div class="one-message message-' + status + ' ' + id + ' ' + hex_md5(from) + '" data-stamp="' + stamp + '">' +
|
||||
'<div class="message-head">' +
|
||||
'<div class="avatar-container">' +
|
||||
'<img class="avatar" src="' + './images/others/default-avatar.png' + '" alt="" />' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="message-jid">' + name + '</div>' +
|
||||
'<div class="message-subject">' + subject.htmlEnc() + '</div>' +
|
||||
|
||||
'<div class="message-truncated">' + Utils.truncate(Utils.noLines(content), 90).htmlEnc() + '</div>' +
|
||||
'</div>' +
|
||||
var nContent = '<div class="one-message message-' + status + ' ' + id + ' ' + hex_md5(from) + '" data-stamp="' + stamp + '">' +
|
||||
'<div class="message-head">' +
|
||||
'<div class="avatar-container">' +
|
||||
'<img class="avatar" src="' + './images/others/default-avatar.png' + '" alt="" />' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="message-jid">' + name + '</div>' +
|
||||
'<div class="message-subject">' + subject.htmlEnc() + '</div>' +
|
||||
|
||||
'<div class="message-truncated">' + Utils.truncate(Utils.noLines(content), 90).htmlEnc() + '</div>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
|
||||
|
||||
// Display the message
|
||||
if(nearest === 0) {
|
||||
$(inbox + 'inbox-results .inbox').append(nContent);
|
||||
} else {
|
||||
$('#inbox .one-message[data-stamp="' + nearest + '"]:first').before(nContent);
|
||||
}
|
||||
|
||||
|
||||
// Click events
|
||||
$(one_message + ' .message-head').click(function() {
|
||||
if(!Common.exists(one_message + ' .message-content'))
|
||||
self.revealMessage(id, from, subject, content, name, date, status);
|
||||
else
|
||||
self.hideMessage(id);
|
||||
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
// Get the user avatar
|
||||
Avatar.get(from, 'cache', 'true', 'forget');
|
||||
|
||||
|
@ -484,11 +482,15 @@ var Inbox = (function () {
|
|||
|
||||
try {
|
||||
// Initialize the XML data
|
||||
var xml = '<message><id>' + id.htmlEnc().htmlEnc() + '</id><date>' + date.htmlEnc().htmlEnc() + '</date><from>' + from.htmlEnc().htmlEnc() + '</from><subject>' + subject.htmlEnc().htmlEnc() + '</subject><status>' + status.htmlEnc().htmlEnc() + '</status><content>' + content.htmlEnc().htmlEnc() + '</content>';
|
||||
|
||||
// End the XML data
|
||||
xml += '</message>';
|
||||
|
||||
var xml = '<message>' +
|
||||
'<id>' + id.htmlEnc().htmlEnc() + '</id>' +
|
||||
'<date>' + date.htmlEnc().htmlEnc() + '</date>' +
|
||||
'<from>' + from.htmlEnc().htmlEnc() + '</from>' +
|
||||
'<subject>' + subject.htmlEnc().htmlEnc() + '</subject>' +
|
||||
'<status>' + status.htmlEnc().htmlEnc() + '</status>' +
|
||||
'<content>' + content.htmlEnc().htmlEnc() + '</content>' +
|
||||
'</message>';
|
||||
|
||||
// Store this message!
|
||||
DataStore.setDB(Connection.desktop_hash, 'inbox', id, xml);
|
||||
} catch(e) {
|
||||
|
@ -504,18 +506,18 @@ var Inbox = (function () {
|
|||
* @param {string} id
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.deleteMessage = function() {
|
||||
self.deleteMessage = function(id) {
|
||||
|
||||
try {
|
||||
// Remove the message from the inbox
|
||||
$('#inbox .one-message.' + id).remove();
|
||||
|
||||
|
||||
// Remove the message from the database
|
||||
DataStore.removeDB(Connection.desktop_hash, 'inbox', id);
|
||||
|
||||
|
||||
// Check the unread messages
|
||||
self.checkMessages();
|
||||
|
||||
|
||||
// Store the new inbox
|
||||
self.store();
|
||||
} catch(e) {
|
||||
|
@ -541,21 +543,21 @@ var Inbox = (function () {
|
|||
for(var i = 0; i < DataStore.storageDB.length; i++) {
|
||||
// Get the pointer values
|
||||
var current = DataStore.storageDB.key(i);
|
||||
|
||||
|
||||
// If the pointer is on a stored message
|
||||
if(current.match(db_regex)) {
|
||||
DataStore.removeDB(Connection.desktop_hash, 'inbox', RegExp.$1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Prevent the database lag
|
||||
$(document).oneTime(100, function() {
|
||||
// Store the new inbox
|
||||
self.store();
|
||||
|
||||
|
||||
// Remove all the messages from the inbox
|
||||
$('#inbox .one-message').remove();
|
||||
|
||||
|
||||
// Reload the inbox
|
||||
self.load();
|
||||
});
|
||||
|
@ -579,56 +581,56 @@ var Inbox = (function () {
|
|||
// Selectors
|
||||
var inbox_link = '#top-content a.inbox-hidable';
|
||||
var no_results = '#inbox .inbox-noresults';
|
||||
|
||||
|
||||
// Marker
|
||||
var has_messages = false;
|
||||
|
||||
|
||||
// Read the number of unread messages
|
||||
var unread = 0;
|
||||
|
||||
|
||||
// Read the local inbox database
|
||||
var db_regex = new RegExp(('^' + Connection.desktop_hash + '_') + 'inbox' + ('_(.+)'));
|
||||
|
||||
for(var i = 0; i < DataStore.storageDB.length; i++) {
|
||||
// Database pointer
|
||||
var current = DataStore.storageDB.key(i);
|
||||
|
||||
|
||||
// Check inbox messages
|
||||
if(current.match(db_regex)) {
|
||||
// Read the current status
|
||||
var status = $(Common.XMLFromString(DataStore.storageDB.getItem(current))).find('status').text();
|
||||
|
||||
|
||||
// Found an unread message
|
||||
if(status == 'unread') {
|
||||
unread++;
|
||||
}
|
||||
|
||||
|
||||
// Update the marker
|
||||
has_messages = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// No message?
|
||||
if(!has_messages) {
|
||||
$(no_results).show();
|
||||
} else {
|
||||
$(no_results).hide();
|
||||
}
|
||||
|
||||
|
||||
// Reset notifications
|
||||
$(inbox_link + ' .notify').remove();
|
||||
|
||||
|
||||
// Any unread message?
|
||||
if(unread) {
|
||||
// Notify the user
|
||||
$(inbox_link).prepend('<div class="notify one-counter" data-counter="' + unread + '">' + unread + '</div>');
|
||||
|
||||
|
||||
// Update the title
|
||||
Interface.updateTitle();
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Anyway, update the title
|
||||
Interface.updateTitle();
|
||||
} catch(e) {
|
||||
|
@ -659,53 +661,53 @@ var Inbox = (function () {
|
|||
var all_message = '#inbox .one-message';
|
||||
var one_message = all_message + '.' + id;
|
||||
var one_content = one_message + ' .message-content';
|
||||
|
||||
|
||||
// We reset all the other messages
|
||||
$(all_message + ' .message-content').remove();
|
||||
$(all_message).removeClass('message-reading');
|
||||
|
||||
|
||||
// Message content
|
||||
var html =
|
||||
'<div class="message-content">' +
|
||||
'<div class="message-body">' + Filter.message(content, name, true) + '</div>' +
|
||||
|
||||
'<div class="message-meta">' +
|
||||
'<span class="date">' + DateUtils.parse(date) + '</span>' +
|
||||
|
||||
'<a href="#" class="reply one-button talk-images">' + Common._e("Reply") + '</a>' +
|
||||
'<a href="#" class="remove one-button talk-images">' + Common._e("Delete") + '</a>' +
|
||||
|
||||
'<div class="clear">' +
|
||||
'</div>' +
|
||||
var html =
|
||||
'<div class="message-content">' +
|
||||
'<div class="message-body">' + Filter.message(content, name, true) + '</div>' +
|
||||
|
||||
'<div class="message-meta">' +
|
||||
'<span class="date">' + DateUtils.parse(date) + '</span>' +
|
||||
|
||||
'<a href="#" class="reply one-button talk-images">' + Common._e("Reply") + '</a>' +
|
||||
'<a href="#" class="remove one-button talk-images">' + Common._e("Delete") + '</a>' +
|
||||
|
||||
'<div class="clear">' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
|
||||
|
||||
// Message content
|
||||
html += '</div>';
|
||||
|
||||
|
||||
$(one_message).append(html).addClass('message-reading');
|
||||
|
||||
|
||||
// Click events
|
||||
$(one_content + ' a.reply').click(function() {
|
||||
return self.replyMessage(id, from, subject, content);
|
||||
});
|
||||
|
||||
|
||||
$(one_content + ' a.remove').click(function() {
|
||||
return self.deleteMessage(id);
|
||||
});
|
||||
|
||||
|
||||
// Unread message
|
||||
if(status == 'unread') {
|
||||
// Update our database
|
||||
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);
|
||||
|
||||
|
||||
// Remove the unread class
|
||||
$(one_message).removeClass('message-unread');
|
||||
|
||||
|
||||
// Send it to the server!
|
||||
self.store();
|
||||
}
|
||||
|
||||
|
||||
// Check the unread messages
|
||||
self.checkMessages();
|
||||
} catch(e) {
|
||||
|
@ -727,7 +729,7 @@ var Inbox = (function () {
|
|||
// Define the paths
|
||||
var inbox = '#inbox .';
|
||||
var one_message = inbox + 'one-message.' + id;
|
||||
|
||||
|
||||
// Reset this message
|
||||
$(one_message).removeClass('message-reading');
|
||||
$(one_message + ' .message-content').remove();
|
||||
|
@ -749,17 +751,17 @@ var Inbox = (function () {
|
|||
try {
|
||||
// We switch to the writing div
|
||||
self.newMessage();
|
||||
|
||||
|
||||
// Inbox path
|
||||
var inbox = '#inbox .';
|
||||
|
||||
|
||||
// Generate the body
|
||||
body = '\n' + '____________' + '\n\n' + Utils.truncate(body, 120);
|
||||
|
||||
|
||||
// We apply the generated values to the form
|
||||
$(inbox + 'inbox-new-to-input').val(from);
|
||||
$(inbox + 'inbox-new-subject-input').val(subject);
|
||||
|
||||
|
||||
$(document).oneTime(10, function() {
|
||||
$(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++) {
|
||||
// Get the pointer values
|
||||
var current = DataStore.storageDB.key(i);
|
||||
|
||||
|
||||
// If the pointer is on a stored message
|
||||
if(current.match(db_regex)) {
|
||||
// Get the current value
|
||||
var value = $(Common.XMLFromString(DataStore.storageDB.getItem(current)));
|
||||
|
||||
|
||||
// Display the current message
|
||||
self.displayMessage(
|
||||
value.find('from').text().revertHtmlEnc(),
|
||||
value.find('subject').text().revertHtmlEnc(),
|
||||
value.find('content').text().revertHtmlEnc(),
|
||||
value.find('status').text().revertHtmlEnc(),
|
||||
value.find('id').text().revertHtmlEnc(),
|
||||
value.find('date').text().revertHtmlEnc()
|
||||
);
|
||||
value.find('from').text().revertHtmlEnc(),
|
||||
value.find('subject').text().revertHtmlEnc(),
|
||||
value.find('content').text().revertHtmlEnc(),
|
||||
value.find('status').text().revertHtmlEnc(),
|
||||
value.find('id').text().revertHtmlEnc(),
|
||||
value.find('date').text().revertHtmlEnc()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Check new messages
|
||||
self.checkMessages();
|
||||
} catch(e) {
|
||||
|
@ -840,37 +842,51 @@ var Inbox = (function () {
|
|||
try {
|
||||
// Data selector
|
||||
var dData = $(responseXML).find('jappix');
|
||||
|
||||
|
||||
// Process the returned data
|
||||
if(dData.find('error').size()) {
|
||||
Board.openThisError(4);
|
||||
|
||||
|
||||
Console.error('Error while attaching the file', dData.find('error').text());
|
||||
} else {
|
||||
// Get the file values
|
||||
var fName = dData.find('title').text();
|
||||
var fType = dData.find('type').text();
|
||||
var fURL = dData.find('href').text();
|
||||
|
||||
|
||||
// Hide the attach link, show the unattach one
|
||||
$('#inbox .inbox-new-file input').hide();
|
||||
$('#inbox .inbox-new-file').append('<a class="file ' + Common.encodeQuotes(Utils.fileCategory(Common.explodeThis('/', fType, 1))) + ' talk-images" href="' + Common.encodeQuotes(fURL) + '" target="_blank">' + fName.htmlEnc() + '</a><a href="#" class="remove one-button talk-images">' + Common._e("Remove") + '</a>');
|
||||
|
||||
$('#inbox .inbox-new-file').append(
|
||||
'<a class="file ' + Common.encodeQuotes(Utils.fileCategory(Common.explodeThis('/', fType, 1))) + ' talk-images" ' +
|
||||
'href="' + Common.encodeQuotes(fURL) + '" ' +
|
||||
'target="_blank">' +
|
||||
fName.htmlEnc() +
|
||||
'</a>' +
|
||||
|
||||
'<a href="#" class="remove one-button talk-images">' +
|
||||
Common._e("Remove") +
|
||||
'</a>'
|
||||
);
|
||||
|
||||
// Set values to the file link
|
||||
$('#inbox .inbox-new-file a.file').attr('data-attachedtitle', fName)
|
||||
.attr('data-attachedhref', fURL);
|
||||
|
||||
var inbox_file_sel = $('#inbox .inbox-new-file a.file');
|
||||
|
||||
inbox_file_sel.attr('data-attachedtitle', fName);
|
||||
inbox_file_sel.attr('data-attachedhref', fURL);
|
||||
|
||||
// Click events
|
||||
$('#inbox .inbox-new-file a.remove').click(function() {
|
||||
$('#inbox .inbox-new-file a').remove();
|
||||
$('#inbox .inbox-new-file input').show();
|
||||
|
||||
var inbox_new_file_sel = $('#inbox .inbox-new-file');
|
||||
|
||||
inbox_new_file_sel.find('a.remove').click(function() {
|
||||
inbox_new_file_sel.find('a').remove();
|
||||
inbox_new_file_sel.find('input').show();
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
Console.info('File attached.');
|
||||
}
|
||||
|
||||
|
||||
// Reset the attach bubble
|
||||
$('#inbox .inbox-new-file input[type="file"]').val('');
|
||||
$('#inbox .wait').hide();
|
||||
|
@ -891,21 +907,22 @@ var Inbox = (function () {
|
|||
try {
|
||||
// Define the pats
|
||||
var inbox = '#inbox .';
|
||||
|
||||
|
||||
// Define the buddy search vars
|
||||
var destination = inbox + 'inbox-new-to';
|
||||
var dHovered = destination + ' ul li.hovered:first';
|
||||
|
||||
|
||||
// Send the message when enter pressend
|
||||
$(inbox + 'inbox-new input').keyup(function(e) {
|
||||
if(e.keyCode == 13) {
|
||||
if(Common.exists(dHovered))
|
||||
if(Common.exists(dHovered)) {
|
||||
Search.addBuddy(destination, $(dHovered).attr('data-xid'));
|
||||
else
|
||||
} else {
|
||||
self.checkMessage();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Buddy search
|
||||
$(inbox + 'inbox-new-to-input').keyup(function(e) {
|
||||
if(e.keyCode != 13) {
|
||||
|
@ -913,61 +930,61 @@ var Inbox = (function () {
|
|||
if((e.keyCode != 40) && (e.keyCode != 38)) {
|
||||
Search.createBuddy(destination);
|
||||
}
|
||||
|
||||
|
||||
// Navigating with keyboard in the results
|
||||
Search.arrowsBuddy(e, destination);
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
// Buddy search lost focus
|
||||
.blur(function() {
|
||||
if(!$(destination + ' ul').attr('mouse-hover')) {
|
||||
Search.resetBuddy(destination);
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
// Buddy search got focus
|
||||
.focus(function() {
|
||||
var value = $(this).val();
|
||||
|
||||
|
||||
// Add a comma at the end
|
||||
if(value && !value.match(/^(.+)((,)(\s)?)$/)) {
|
||||
$(this).val(value + ', ');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Click events
|
||||
$(inbox + 'a-delete-messages').click(self.purge);
|
||||
$(inbox + 'a-new-message').click(self.newMessage);
|
||||
$(inbox + 'a-show-messages').click(self.showMessage);
|
||||
$(inbox + 'inbox-new-send a').click(self.checkMessage);
|
||||
|
||||
|
||||
$(inbox + 'bottom .finish').click(function() {
|
||||
return self.close();
|
||||
});
|
||||
|
||||
|
||||
// File upload
|
||||
var attach_options = {
|
||||
dataType: 'xml',
|
||||
dataType: 'xml',
|
||||
beforeSubmit: self.waitAttach,
|
||||
success: self.handleAttach
|
||||
};
|
||||
|
||||
|
||||
// Upload form submit event
|
||||
$('#inbox .inbox-new-file').submit(function() {
|
||||
if($('#inbox .wait').is(':hidden') && $('#inbox .inbox-new-file input[type="file"]').val()) {
|
||||
$(this).ajaxSubmit(attach_options);
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
// Upload input change event
|
||||
$('#inbox .inbox-new-file input[type="file"]').change(function() {
|
||||
if($('#inbox .wait').is(':hidden') && $(this).val()) {
|
||||
$('#inbox .inbox-new-file').ajaxSubmit(attach_options);
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
});
|
||||
} catch(e) {
|
||||
|
|
|
@ -29,22 +29,22 @@ var IntegrateBox = (function () {
|
|||
|
||||
try {
|
||||
// Popup HTML content
|
||||
var html =
|
||||
'<div class="top">' + Common._e("Media viewer") + '</div>' +
|
||||
|
||||
'<div class="content"></div>' +
|
||||
|
||||
'<div class="bottom">' +
|
||||
'<div class="wait wait-medium"></div>' +
|
||||
|
||||
'<a href="#" class="finish close">' + Common._e("Close") + '</a>' +
|
||||
'<a href="#" class="finish next disabled" title="' + Common._e("Next") + '">></a>' +
|
||||
'<a href="#" class="finish previous disabled" title="' + Common._e("Previous") + '"><</a>' +
|
||||
var html =
|
||||
'<div class="top">' + Common._e("Media viewer") + '</div>' +
|
||||
|
||||
'<div class="content"></div>' +
|
||||
|
||||
'<div class="bottom">' +
|
||||
'<div class="wait wait-medium"></div>' +
|
||||
|
||||
'<a href="#" class="finish close">' + Common._e("Close") + '</a>' +
|
||||
'<a href="#" class="finish next disabled" title="' + Common._e("Next") + '">></a>' +
|
||||
'<a href="#" class="finish previous disabled" title="' + Common._e("Previous") + '"><</a>' +
|
||||
'</div>';
|
||||
|
||||
|
||||
// Create the popup
|
||||
Popup.create('integratebox', html);
|
||||
|
||||
|
||||
// Associate the events
|
||||
self.instance();
|
||||
} catch(e) {
|
||||
|
@ -84,17 +84,17 @@ var IntegrateBox = (function () {
|
|||
|
||||
try {
|
||||
var code = '';
|
||||
|
||||
|
||||
// Protocol to use
|
||||
var protocol = Utils.isHTTPS() ? 'https' : 'http';
|
||||
|
||||
|
||||
// Legacy browser
|
||||
var legacy = false;
|
||||
|
||||
|
||||
if((BrowserDetect.browser == 'Explorer') && (BrowserDetect.version < 9)) {
|
||||
legacy = true;
|
||||
}
|
||||
|
||||
|
||||
// Switch to get the good DOM code
|
||||
switch(serv) {
|
||||
case 'youtube':
|
||||
|
@ -103,37 +103,37 @@ var IntegrateBox = (function () {
|
|||
} 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>';
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case 'dailymotion':
|
||||
code = '<object width="640" height="385"><param name="movie" value="http://www.dailymotion.com/swf/video/' + url + '&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) + '&autoplay=1" width="640" height="385" allowfullscreen="true" allowscriptaccess="always"></embed></object>';
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
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) + '&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1&autoplay=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=' + Common.encodeQuotes(url) + '&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1&autoplay=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="640" height="385"></embed></object>';
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case 'theora':
|
||||
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>';
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case 'vorbis':
|
||||
case 'audio':
|
||||
code = '<audio src="' + Common.encodeQuotes(url) + '" controls autoplay><a href="' + Common.encodeQuotes(url) + '" target="_blank">' + Common.encodeQuotes(url) + '</a></audio>';
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case 'image':
|
||||
code = '<a href="' + Common.encodeQuotes(url) + '" target="_blank"><img alt="" src="' + Common.encodeQuotes(url) + '" /></a>';
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return code;
|
||||
} catch(e) {
|
||||
Console.error('IntegrateBox.code', e);
|
||||
|
@ -159,64 +159,65 @@ var IntegrateBox = (function () {
|
|||
try {
|
||||
// Close the integratebox
|
||||
self.close();
|
||||
|
||||
|
||||
// Media integration not wanted?
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'integratemedias') == '0')
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'integratemedias') == '0') {
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
// Apply the HTML code
|
||||
var dom_code = self.code(service, url);
|
||||
|
||||
|
||||
// Any code: apply it!
|
||||
if(dom_code) {
|
||||
// We show the integratebox
|
||||
self.open();
|
||||
|
||||
|
||||
// We add the code to the DOM
|
||||
$('#integratebox .content').prepend('<div class="one-media">' + dom_code + '</div>');
|
||||
|
||||
|
||||
// Image waiting icon
|
||||
if(service == 'image') {
|
||||
var waitItem = $('#integratebox .wait');
|
||||
|
||||
|
||||
// Show it while it is loading
|
||||
waitItem.show();
|
||||
|
||||
|
||||
// Hide it when it is loaded
|
||||
$('#integratebox img').load(function() {
|
||||
waitItem.hide();
|
||||
|
||||
|
||||
// Center the image vertically
|
||||
$(this).oneTime(10, function() {
|
||||
$(this).css('margin-top', (($('#integratebox .content').height() - $(this).height()) / 2));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Large style?
|
||||
var comments_id = genID();
|
||||
|
||||
|
||||
if(width_style == 'large') {
|
||||
// Make the popup large
|
||||
$('#integratebox .popup').addClass('large');
|
||||
|
||||
|
||||
// Add the right content
|
||||
$('#integratebox .content').after(
|
||||
'<div class="comments" data-id="' + Common.encodeQuotes(comments_id) + '">' +
|
||||
'<div class="comments-content">' +
|
||||
'<div class="one-comment loading"><span class="icon talk-images"></span>' + Common._e("Loading comments...") + '</div>' +
|
||||
'</div>' +
|
||||
'<div class="comments" data-id="' + Common.encodeQuotes(comments_id) + '">' +
|
||||
'<div class="comments-content">' +
|
||||
'<div class="one-comment loading"><span class="icon talk-images"></span>' + Common._e("Loading comments...") + '</div>' +
|
||||
'</div>' +
|
||||
'</div>'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Previous and next items?
|
||||
var url_array = Utils.stringToArray(url_list);
|
||||
var services_array = Utils.stringToArray(services_list);
|
||||
var comments_e_array = Utils.stringToArray(comments_e_list);
|
||||
var comments_n_array = Utils.stringToArray(comments_n_list);
|
||||
var index = Utils.indexArrayValue(url_array, url);
|
||||
|
||||
|
||||
// Any comments?
|
||||
if(Common.exists('#integratebox .comments')) {
|
||||
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>');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Get the previous values
|
||||
var previous_url = url_array[index - 1];
|
||||
var previous_services = services_array[index - 1];
|
||||
|
||||
|
||||
// Get the next values
|
||||
var next_url = url_array[index + 1];
|
||||
var next_services = services_array[index + 1];
|
||||
|
||||
|
||||
// Enable/disable buttons
|
||||
if(previous_url && previous_services) {
|
||||
$('#integratebox .bottom .finish.previous').removeClass('disabled');
|
||||
} else {
|
||||
$('#integratebox .bottom .finish.previous').addClass('disabled');
|
||||
}
|
||||
|
||||
|
||||
if(next_url && next_services) {
|
||||
$('#integratebox .bottom .finish.next').removeClass('disabled');
|
||||
} else {
|
||||
$('#integratebox .bottom .finish.next').addClass('disabled');
|
||||
}
|
||||
|
||||
|
||||
// Click events
|
||||
$('#integratebox .bottom .finish.previous, #integratebox .bottom .finish.next').click(function() {
|
||||
// Not acceptable?
|
||||
if($(this).is('.disabled')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Apply the event!
|
||||
if($(this).is('.previous')) {
|
||||
self.apply(previous_url, previous_services, url_list, services_list, comments_e_list, comments_n_list, width_style);
|
||||
} else {
|
||||
self.apply(next_url, next_services, url_list, services_list, comments_e_list, comments_n_list, width_style);
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
if(width_style == 'large')
|
||||
$('#integratebox .content a:has(img)').click(function() {
|
||||
if(next_url && next_services) {
|
||||
self.apply(next_url, next_services, url_list, services_list, comments_e_list, comments_n_list, width_style);
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Nothing: return true to be able to open the URL in a new tab
|
||||
return true;
|
||||
} catch(e) {
|
||||
|
@ -320,90 +321,90 @@ var IntegrateBox = (function () {
|
|||
try {
|
||||
// Encapsulates the string into two <div /> elements
|
||||
var xml = $('<div><div>' + data + '</div></div>').contents();
|
||||
|
||||
|
||||
// Loop the <a /> elements
|
||||
$(xml).find('a').each(function() {
|
||||
// Initialize this element
|
||||
var href = $(this).attr('href');
|
||||
var to, url, service, event;
|
||||
|
||||
|
||||
// XMPP ID
|
||||
if(href.match(/^xmpp:(.+)/i)) {
|
||||
to = RegExp.$1;
|
||||
}
|
||||
|
||||
|
||||
// YouTube video box
|
||||
else if(href.match(/(\w{3,5})(:)(\S+)((\.youtube\.com\/watch(\?v|\?\S+v|\#\!v|\#\!\S+v)\=)|(youtu\.be\/))([^& ]+)((&\S)|(&\S)|\s|$)/gim)) {
|
||||
url = RegExp.$8;
|
||||
service = 'youtube';
|
||||
}
|
||||
|
||||
|
||||
// Dailymotion video box
|
||||
else if(href.match(/(\w{3,5})(:)(\S+)\.dailymotion\.com\/video\/([\w\-]+)((\#[\w\-]+)|\s|$)/gim)) {
|
||||
url = RegExp.$4;
|
||||
service = 'dailymotion';
|
||||
}
|
||||
|
||||
|
||||
// Vimeo video box
|
||||
else if(href.match(/((\w{3,5})(:)(\S+)(vimeo|www\.vimeo)\.com\/([\w\-]+))/gim)) {
|
||||
url = RegExp.$6;
|
||||
service = 'vimeo';
|
||||
}
|
||||
|
||||
|
||||
// Theora video box
|
||||
else if(href.match(/((\w{3,5})(:)(\S+)(\.)(ogv|ogg))/gim)) {
|
||||
url = RegExp.$1;
|
||||
service = 'theora';
|
||||
}
|
||||
|
||||
|
||||
// Vorbis audio box
|
||||
else if(href.match(/((\w{3,5})(:)(\S+)(\.oga))/gim)) {
|
||||
url = RegExp.$1;
|
||||
service = 'vorbis';
|
||||
}
|
||||
|
||||
|
||||
// Image box
|
||||
else if(href.match(/((\w{3,5})(:)(\S+)(\.)(jpg|jpeg|png|gif|tif|bmp))/gim)) {
|
||||
url = RegExp.$1;
|
||||
service = 'image';
|
||||
}
|
||||
|
||||
|
||||
// Define the good event
|
||||
if(to) {
|
||||
event = 'XMPPLinks.go(\'' + Utils.encodeOnclick(to) + '\')';
|
||||
} else if(url && service) {
|
||||
event = 'IntegrateBox.apply(\'' + Utils.encodeOnclick(url) + '\', \'' + Utils.encodeOnclick(service) + '\')';
|
||||
}
|
||||
|
||||
|
||||
// Any click event to apply?
|
||||
if(event) {
|
||||
// Regenerate the link element (for onclick)
|
||||
var new_a = '<a';
|
||||
var element_a = (this);
|
||||
|
||||
|
||||
// Attributes
|
||||
$(element_a.attributes).each(function(index) {
|
||||
// Read the current attribute
|
||||
var current_attr = element_a.attributes[index];
|
||||
|
||||
|
||||
// Apply the current attribute
|
||||
new_a += ' ' + Common.encodeQuotes(current_attr.name) + '="' + Common.encodeQuotes(current_attr.value) + '"';
|
||||
});
|
||||
|
||||
|
||||
// Add onclick attribute
|
||||
new_a += ' onclick="return ' + event + ';"';
|
||||
|
||||
|
||||
// Value
|
||||
new_a += '>' + $(this).html() + '</a>';
|
||||
|
||||
|
||||
// Replace it!
|
||||
$(this).replaceWith(new_a);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Regenerate the HTML code (include string into a div to be readable)
|
||||
var string = $(xml).html();
|
||||
|
||||
|
||||
return string;
|
||||
} catch(e) {
|
||||
Console.error('IntegrateBox.filter', e);
|
||||
|
@ -441,14 +442,14 @@ var IntegrateBox = (function () {
|
|||
// Previous item?
|
||||
if((Common.exists('#integratebox .bottom .finish.previous:not(.disabled)')) && (e.keyCode == 37)) {
|
||||
$('#integratebox .bottom .finish.previous').click();
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Next item?
|
||||
if((Common.exists('#integratebox .bottom .finish.next:not(.disabled)')) && (e.keyCode == 39)) {
|
||||
$('#integratebox .bottom .finish.next').click();
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -35,25 +35,25 @@ var Interface = (function () {
|
|||
try {
|
||||
// Anonymous mode?
|
||||
var head_name = Name.get();
|
||||
|
||||
|
||||
if(Utils.isAnonymous()) {
|
||||
head_name = ANONYMOUS_ROOM + ' (' + Common._e("anonymous mode") + ')';
|
||||
}
|
||||
|
||||
|
||||
// We change the title to give essential informations
|
||||
switch(title_type) {
|
||||
case 'home':
|
||||
document.title = SERVICE_NAME + ' • ' + SERVICE_DESC;
|
||||
break;
|
||||
|
||||
|
||||
case 'talk':
|
||||
document.title = SERVICE_NAME + ' • ' + head_name;
|
||||
break;
|
||||
|
||||
|
||||
case 'new':
|
||||
document.title = '[' + self.pendingEvents() + '] ' + SERVICE_NAME + ' • ' + head_name;
|
||||
break;
|
||||
|
||||
|
||||
case 'wait':
|
||||
document.title = SERVICE_NAME + ' • ' + Common._e("Please wait...");
|
||||
break;
|
||||
|
@ -74,18 +74,19 @@ var Interface = (function () {
|
|||
|
||||
try {
|
||||
// Item exists?
|
||||
if(Common.exists('#general-wait'))
|
||||
if(Common.exists('#general-wait')) {
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
// Generate the HTML code
|
||||
var html =
|
||||
'<div id="general-wait" class="removable">' +
|
||||
'<div class="general-wait-content wait-big"></div>' +
|
||||
var html =
|
||||
'<div id="general-wait" class="removable">' +
|
||||
'<div class="general-wait-content wait-big"></div>' +
|
||||
'</div>';
|
||||
|
||||
|
||||
// Append the HTML code
|
||||
$('body').append(html);
|
||||
|
||||
|
||||
return true;
|
||||
} catch(e) {
|
||||
Console.error('Interface.showGeneralWait', e);
|
||||
|
@ -118,11 +119,11 @@ var Interface = (function () {
|
|||
self.generateFileShare = function() {
|
||||
|
||||
try {
|
||||
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="location" value="' + Common.encodeQuotes(Utils.generateURL(JAPPIX_LOCATION)) + '" />' +
|
||||
'<input type="hidden" name="id" value="' + (new Date()).getTime() + '" />' +
|
||||
'<input type="file" name="file" required="" />' +
|
||||
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="location" value="' + Common.encodeQuotes(Utils.generateURL(JAPPIX_LOCATION)) + '" />' +
|
||||
'<input type="hidden" name="id" value="' + (new Date()).getTime() + '" />' +
|
||||
'<input type="file" name="file" required="" />' +
|
||||
'<input type="submit" value="' + Common._e("Send") + '" />';
|
||||
} catch(e) {
|
||||
Console.error('Interface.generateFileShare', e);
|
||||
|
@ -144,16 +145,16 @@ var Interface = (function () {
|
|||
// We show the page-engine content
|
||||
$('.page-engine-chan').hide();
|
||||
$('#' + id).show();
|
||||
|
||||
|
||||
// We edit the tab switcher
|
||||
$('#page-switch .switcher').removeClass('activechan').addClass('chan');
|
||||
$('#page-switch .' + id).addClass('activechan').removeClass('chan');
|
||||
|
||||
|
||||
// Scroll down to the last message
|
||||
if(id != 'channel') {
|
||||
self.autoScroll(id);
|
||||
}
|
||||
|
||||
|
||||
// Manage input focus
|
||||
self.inputFocus();
|
||||
}
|
||||
|
@ -176,18 +177,19 @@ var Interface = (function () {
|
|||
try {
|
||||
// Path
|
||||
var more_content = '#page-switch .more-content';
|
||||
|
||||
|
||||
// Yet displayed?
|
||||
if(Common.exists(more_content))
|
||||
if(Common.exists(more_content)) {
|
||||
return Bubble.close();
|
||||
|
||||
}
|
||||
|
||||
// Add the bubble
|
||||
Bubble.show(more_content);
|
||||
|
||||
|
||||
// Append the content
|
||||
$('#page-switch .more').append(
|
||||
'<div class="more-content bubble removable">' +
|
||||
$('#page-switch .chans').html() +
|
||||
'<div class="more-content bubble removable">' +
|
||||
$('#page-switch .chans').html() +
|
||||
'</div>'
|
||||
);
|
||||
} catch(e) {
|
||||
|
@ -210,18 +212,18 @@ var Interface = (function () {
|
|||
// Path
|
||||
var join_content = '#page-switch .join-content';
|
||||
var join_sel = $('#page-switch .join');
|
||||
|
||||
|
||||
// Yet displayed?
|
||||
if(Common.exists(join_content))
|
||||
return Bubble.close();
|
||||
|
||||
|
||||
// Add the bubble
|
||||
Bubble.show(join_content);
|
||||
|
||||
|
||||
// Append the content
|
||||
join_sel.append(
|
||||
'<div class="join-content bubble removable">' +
|
||||
'<input type="text" class="join-groupchat-xid" required="" placeholder="' + Common._e("Groupchat name") + '" />' +
|
||||
'<div class="join-content bubble removable">' +
|
||||
'<input type="text" class="join-groupchat-xid" required="" placeholder="' + Common._e("Groupchat name") + '" />' +
|
||||
'</div>'
|
||||
);
|
||||
|
||||
|
@ -232,11 +234,11 @@ var Interface = (function () {
|
|||
if(e.keyCode == 13) {
|
||||
var this_sel = $(this);
|
||||
var xid = $.trim(this_sel.val());
|
||||
|
||||
|
||||
if(xid) {
|
||||
// Generate a correct XID
|
||||
xid = Common.generateXID(xid, 'groupchat');
|
||||
|
||||
|
||||
Bubble.close();
|
||||
Chat.checkCreate(xid, 'groupchat');
|
||||
} else {
|
||||
|
@ -272,14 +274,14 @@ var Interface = (function () {
|
|||
// We define the variables
|
||||
var selector = $('#' + hash + ' .message-area');
|
||||
var oValue = selector.val();
|
||||
|
||||
|
||||
// Any old value?
|
||||
if(oValue && !oValue.match(/^(.+)(\s)+$/)) {
|
||||
oValue += ' ';
|
||||
}
|
||||
|
||||
|
||||
var nValue = oValue + smiley + ' ';
|
||||
|
||||
|
||||
// Put the new value and focus on it
|
||||
$(document).oneTime(10, function() {
|
||||
selector.val(nValue).focus();
|
||||
|
@ -322,7 +324,7 @@ var Interface = (function () {
|
|||
if(type == 'groupchat') {
|
||||
// Send our unavailable presence
|
||||
Presence.send(xid + '/' + Name.getMUCNick(hash), 'unavailable');
|
||||
|
||||
|
||||
// Remove all presence database entries for this groupchat
|
||||
var db_regex = new RegExp(('^' + Connection.desktop_hash + '_') + 'presence' + ('_(.+)'));
|
||||
|
||||
|
@ -332,15 +334,15 @@ var Interface = (function () {
|
|||
|
||||
if(current.match(db_regex)) {
|
||||
var cXID = RegExp.$1;
|
||||
|
||||
|
||||
// If the pointer is on a presence from this groupchat
|
||||
if(Common.bareXID(cXID) == xid) {
|
||||
// Generate the hash for the current XID
|
||||
var cHash = hex_md5(cXID);
|
||||
|
||||
|
||||
// Disable the message textarea
|
||||
$('#' + cHash + ' .message-area').attr('disabled', true);
|
||||
|
||||
|
||||
// Remove the presence for this XID
|
||||
DataStore.removeDB(Connection.desktop_hash, 'presence-stanza', cXID);
|
||||
DataStore.removeDB(Connection.desktop_hash, 'presence-resources', cXID);
|
||||
|
@ -356,18 +358,18 @@ var Interface = (function () {
|
|||
if(xid in MAM.map_states) {
|
||||
delete MAM.map_states[xid];
|
||||
}
|
||||
|
||||
|
||||
// Get the chat ID which is before
|
||||
var previous = $('#' + hash).prev().attr('id');
|
||||
|
||||
|
||||
// Remove the chat
|
||||
self.deleteThisChat(hash);
|
||||
|
||||
|
||||
// Reset the switcher
|
||||
if(!Common.exists('#page-switch .switcher.activechan')) {
|
||||
self.switchChan(previous);
|
||||
}
|
||||
|
||||
|
||||
// Reset the notifications
|
||||
self.chanCleanNotify(hash);
|
||||
} catch(e) {
|
||||
|
@ -397,32 +399,48 @@ var Interface = (function () {
|
|||
var date = DateUtils.getXMPPTime('local');
|
||||
var type = $('#' + hash).attr('data-type');
|
||||
var direction = $('html').attr('dir') || 'ltr';
|
||||
|
||||
|
||||
var content_sel = $(content);
|
||||
|
||||
// Filter the content smileys
|
||||
$(content).find('img.emoticon').each(function() {
|
||||
content_sel.find('img.emoticon').each(function() {
|
||||
$(this).replaceWith($(this).attr('alt'));
|
||||
});
|
||||
|
||||
|
||||
// Remove the useless attributes
|
||||
$(content).removeAttr('data-type').removeAttr('data-stamp');
|
||||
|
||||
content_sel.removeAttr('data-type').removeAttr('data-stamp');
|
||||
|
||||
// Remove the content avatars
|
||||
$(content).find('.avatar-container').remove();
|
||||
|
||||
content_sel.find('.avatar-container').remove();
|
||||
|
||||
// Remove the content info
|
||||
content_sel.find('.correction-edit, .message-marker, .corrected-info, .correction-label').remove();
|
||||
|
||||
// Remove the content click events
|
||||
$(content).find('a').removeAttr('onclick');
|
||||
|
||||
content_sel.find('a').removeAttr('onclick');
|
||||
|
||||
// Extract the content HTML code
|
||||
content = $(content).parent().html();
|
||||
|
||||
content = content_sel.parent().html();
|
||||
|
||||
// No avatar?
|
||||
if(!avatar || !avatar.match(/data:/))
|
||||
if(!avatar || !avatar.match(/data:/)) {
|
||||
avatar = 'none';
|
||||
|
||||
}
|
||||
|
||||
// POST the values to the server
|
||||
$.post('./server/generate-chat.php', { 'content': content, 'xid': xid, 'nick': nick, 'avatar': avatar, 'date': date, 'type': type, 'direction': direction }, function(data) {
|
||||
$.post('./server/generate-chat.php', {
|
||||
'content': content,
|
||||
'xid': xid,
|
||||
'nick': nick,
|
||||
'avatar': avatar,
|
||||
'date': date,
|
||||
'type': type,
|
||||
'direction': direction
|
||||
}, function(data) {
|
||||
// Handled!
|
||||
$(path + 'tooltip-waitlog').replaceWith('<a class="tooltip-actionlog" href="./server/download-chat.php?id=' + data + '" target="_blank">' + Common._e("Download file!") + '</a>');
|
||||
$(path + 'tooltip-waitlog').replaceWith(
|
||||
'<a class="tooltip-actionlog" href="./server/download-chat.php?id=' + data + '" target="_blank">' + Common._e("Download file!") + '</a>'
|
||||
);
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Interface.generateChatLog', e);
|
||||
|
@ -433,6 +451,31 @@ var Interface = (function () {
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether chan has focus or not
|
||||
* @public
|
||||
* @param {string} hash
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.hasChanFocus = function(hash) {
|
||||
|
||||
var has_focus = true;
|
||||
|
||||
try {
|
||||
if(!$('#page-switch .' + hash).hasClass('activechan') ||
|
||||
!Common.isFocused() ||
|
||||
(self.chat_focus_hash != hash)) {
|
||||
has_focus = false;
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Interface.hasChanFocus', e);
|
||||
} finally {
|
||||
return has_focus;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Notifies the user from a new incoming message
|
||||
* @public
|
||||
|
@ -447,9 +490,9 @@ var Interface = (function () {
|
|||
var chat_switch = '#page-switch .';
|
||||
var tested = chat_switch + hash;
|
||||
var active = $(tested).hasClass('activechan');
|
||||
|
||||
|
||||
// We notify the user if he has not the focus on the chat
|
||||
if(!active || !Common.isFocused() || (self.chat_focus_hash != hash)) {
|
||||
if(self.hasChanFocus(hash) === false) {
|
||||
if(!active) {
|
||||
if(type == 'personal') {
|
||||
$(tested + ', ' + chat_switch + 'more-button').addClass('chan-newmessage');
|
||||
|
@ -457,17 +500,17 @@ var Interface = (function () {
|
|||
$(tested).addClass('chan-unread');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Count the number of pending messages
|
||||
var pending = 1;
|
||||
|
||||
|
||||
if(Common.exists('#' + hash + '[data-counter]')) {
|
||||
pending = parseInt($('#' + hash).attr('data-counter')) + 1;
|
||||
}
|
||||
|
||||
|
||||
$('#' + hash).attr('data-counter', pending);
|
||||
}
|
||||
|
||||
|
||||
// Update the page title
|
||||
self.updateTitle();
|
||||
} catch(e) {
|
||||
|
@ -487,11 +530,11 @@ var Interface = (function () {
|
|||
try {
|
||||
// Count the number of notifications
|
||||
var number = 0;
|
||||
|
||||
|
||||
$('.one-counter[data-counter]').each(function() {
|
||||
number = number + parseInt($(this).attr('data-counter'));
|
||||
});
|
||||
|
||||
|
||||
return number;
|
||||
} catch(e) {
|
||||
Console.error('Interface.pendingEvents', e);
|
||||
|
@ -509,10 +552,11 @@ var Interface = (function () {
|
|||
|
||||
try {
|
||||
// Any pending events?
|
||||
if(Common.exists('.one-counter[data-counter]'))
|
||||
if(Common.exists('.one-counter[data-counter]')) {
|
||||
self.title('new');
|
||||
else
|
||||
} else {
|
||||
self.title('talk');
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Interface.updateTitle', e);
|
||||
}
|
||||
|
@ -532,14 +576,15 @@ var Interface = (function () {
|
|||
// We remove the class that tell the user of a new message
|
||||
var chat_switch = '#page-switch .';
|
||||
$(chat_switch + hash).removeClass('chan-newmessage chan-unread');
|
||||
|
||||
|
||||
// We reset the global notifications if no more unread messages
|
||||
if(!$(chat_switch + 'chans .chan-newmessage').size())
|
||||
if(!$(chat_switch + 'chans .chan-newmessage').size()) {
|
||||
$(chat_switch + 'more-button').removeClass('chan-newmessage');
|
||||
|
||||
}
|
||||
|
||||
// We reset the chat counter
|
||||
$('#' + hash).removeAttr('data-counter');
|
||||
|
||||
|
||||
// Update the page title
|
||||
self.updateTitle();
|
||||
} catch(e) {
|
||||
|
@ -561,7 +606,7 @@ var Interface = (function () {
|
|||
// Avoid a JS error
|
||||
if(Common.exists('#' + hash)) {
|
||||
var container = document.getElementById('chat-content-' + hash);
|
||||
|
||||
|
||||
// Scroll down!
|
||||
container.scrollTop = container.scrollHeight;
|
||||
}
|
||||
|
@ -583,24 +628,25 @@ var Interface = (function () {
|
|||
try {
|
||||
// Put a marker
|
||||
Roster.blist_all = true;
|
||||
|
||||
|
||||
// We switch the two modes
|
||||
$('.buddy-conf-more-display-unavailable').hide();
|
||||
$('.buddy-conf-more-display-available').show();
|
||||
|
||||
|
||||
// Security: reset all the groups toggle event
|
||||
$('#roster .group-buddies').show();
|
||||
$('#roster .group span').text('-');
|
||||
|
||||
|
||||
// We show the disconnected buddies
|
||||
$('.hidden-buddy').show();
|
||||
|
||||
|
||||
// We show all the groups
|
||||
$('#roster .one-group').show();
|
||||
|
||||
if(Search.search_filtered)
|
||||
|
||||
if(Search.search_filtered) {
|
||||
Search.funnelFilterBuddy();
|
||||
|
||||
}
|
||||
|
||||
// Store this in the options
|
||||
if((from == 'roster') && Options.loaded()) {
|
||||
DataStore.setDB(Connection.desktop_hash, 'options', 'roster-showall', '1');
|
||||
|
@ -624,25 +670,25 @@ var Interface = (function () {
|
|||
try {
|
||||
// Remove the marker
|
||||
Roster.blist_all = false;
|
||||
|
||||
|
||||
// We switch the two modes
|
||||
$('.buddy-conf-more-display-available').hide();
|
||||
$('.buddy-conf-more-display-unavailable').show();
|
||||
|
||||
|
||||
// Security: reset all the groups toggle event
|
||||
$('#roster .group-buddies').show();
|
||||
$('#roster .group span').text('-');
|
||||
|
||||
|
||||
// We hide the disconnected buddies
|
||||
$('.hidden-buddy').hide();
|
||||
|
||||
|
||||
// We check the groups to hide
|
||||
Roster.updateGroups();
|
||||
|
||||
|
||||
if(Search.search_filtered) {
|
||||
Search.funnelFilterBuddy();
|
||||
}
|
||||
|
||||
|
||||
// Store this in the options
|
||||
if((from == 'roster') && Options.loaded()) {
|
||||
DataStore.setDB(Connection.desktop_hash, 'options', 'roster-showall', '0');
|
||||
|
@ -687,6 +733,39 @@ var Interface = (function () {
|
|||
$(document).ready(function() {
|
||||
// Focus on the first visible input
|
||||
$(window).focus(self.inputFocus);
|
||||
|
||||
// Re-focus to visible chat/groupchat input if typing when input blurred
|
||||
$(document).keypress(function(evt) {
|
||||
try {
|
||||
// Don't trigger if not connected or popup opened
|
||||
if(Common.isConnected() && !Common.exists('div.lock')) {
|
||||
// Cannot work if an input/textarea is already focused or chat is not opened
|
||||
var target_input_sel = $('.page-engine-chan .message-area:visible');
|
||||
|
||||
if(!target_input_sel.size() || $('input, textarea').is(':focus')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get key value
|
||||
var key_value = $.trim(String.fromCharCode(evt.which));
|
||||
|
||||
// Re-focus on opened chat?
|
||||
if(key_value) {
|
||||
// Get input values
|
||||
value_input = target_input_sel.val();
|
||||
|
||||
// Append pressed key value
|
||||
target_input_sel.val(value_input + key_value);
|
||||
target_input_sel.focus();
|
||||
|
||||
// Put cursor at the end of input
|
||||
target_input_sel[0].selectionStart = target_input_sel[0].selectionEnd = value_input.length + 1;
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Interface.launch[autofocus]', e);
|
||||
}
|
||||
});
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Interface.launch', e);
|
||||
|
|
|
@ -140,7 +140,7 @@ var addToHome = (function (w) {
|
|||
options.message = '';
|
||||
}
|
||||
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 ) {
|
||||
|
|
|
@ -20,6 +20,352 @@ var IQ = (function () {
|
|||
var self = {};
|
||||
|
||||
|
||||
/**
|
||||
* Handles OOB request
|
||||
* @private
|
||||
* @param {string} iqType
|
||||
* @param {string} iqID
|
||||
* @param {object} iqNode
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._handleOOBRequest = function(iqFrom, iqID, iqNode) {
|
||||
|
||||
try {
|
||||
/* REF: http://xmpp.org/extensions/xep-0066.html */
|
||||
|
||||
OOB.handle(iqFrom, iqID, 'iq', iqNode);
|
||||
|
||||
Console.log('Received IQ OOB request: ' + iqFrom);
|
||||
} catch(e) {
|
||||
Console.error('IQ._handleOOBRequest', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles OOB reply
|
||||
* @private
|
||||
* @param {object} iqResponse
|
||||
* @param {string} iqFrom
|
||||
* @param {string} iqType
|
||||
* @param {string} iqID
|
||||
* @param {object} iqNode
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._handleOOBReply = function(iqResponse, iqFrom, iqType, iqID, iqNode) {
|
||||
|
||||
try {
|
||||
// Get the values
|
||||
var oob_url = DataStore.getDB(Connection.desktop_hash, 'send/url', iqID);
|
||||
var oob_desc = DataStore.getDB(Connection.desktop_hash, 'send/desc', iqID);
|
||||
var notif_id = hex_md5(oob_url + oob_desc + iqType + iqFrom + iqID);
|
||||
|
||||
if($(iqNode).find('error').size()) {
|
||||
// Error?
|
||||
if($(iqNode).find('error not-acceptable').size()) {
|
||||
// Rejected?
|
||||
Notification.create('send_reject', iqFrom, [iqFrom, oob_url, 'iq', iqID, iqNode], oob_desc, notif_id);
|
||||
} else {
|
||||
// Failed?
|
||||
Notification.create('send_fail', iqFrom, [iqFrom, oob_url, 'iq', iqID, iqNode], oob_desc, notif_id);
|
||||
}
|
||||
|
||||
// Remove the file
|
||||
$.get(oob_url + '&action=remove');
|
||||
} else if(iqType == 'result') {
|
||||
// Success?
|
||||
Notification.create('send_accept', iqFrom, [iqFrom, oob_url, 'iq', iqID, iqNode], oob_desc, notif_id);
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('IQ._handleOOBReply', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles Software Version
|
||||
* @private
|
||||
* @param {object} iqResponse
|
||||
* @param {string} iqFrom
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._handleSoftwareVersion = function(iqResponse, iqFrom) {
|
||||
|
||||
try {
|
||||
/* REF: http://xmpp.org/extensions/xep-0092.html */
|
||||
|
||||
iqQuery = iqResponse.setQuery(NS_VERSION);
|
||||
|
||||
iqQuery.appendChild(iqResponse.buildNode('name', {'xmlns': NS_VERSION}, Caps.disco_infos.identity.name));
|
||||
iqQuery.appendChild(iqResponse.buildNode('version', {'xmlns': NS_VERSION}, JAPPIX_VERSION));
|
||||
iqQuery.appendChild(iqResponse.buildNode('os', {'xmlns': NS_VERSION}, BrowserDetect.OS));
|
||||
|
||||
con.send(iqResponse);
|
||||
|
||||
Console.log('Received software version query: ' + iqFrom);
|
||||
} catch(e) {
|
||||
Console.error('IQ._handleSoftwareVersion', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles Last Activity
|
||||
* @private
|
||||
* @param {object} iqResponse
|
||||
* @param {string} iqFrom
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._handleLastActivity = function(iqResponse, iqFrom) {
|
||||
|
||||
try {
|
||||
/* REF: http://xmpp.org/extensions/xep-0012.html */
|
||||
|
||||
iqQuery = iqResponse.setQuery(NS_LAST);
|
||||
iqQuery.setAttribute('seconds', DateUtils.getLastActivity());
|
||||
|
||||
con.send(iqResponse);
|
||||
|
||||
Console.log('Received last activity query: ' + iqFrom);
|
||||
} catch(e) {
|
||||
Console.error('IQ._handleLastActivity', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles Privacy Lists
|
||||
* @private
|
||||
* @param {object} iqResponse
|
||||
* @param {string} iqFrom
|
||||
* @param {string} iqQuery
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._handlePrivacyLists = function(iqResponse, iqFrom, iqQuery) {
|
||||
|
||||
try {
|
||||
// REF : http://xmpp.org/extensions/xep-0016.html
|
||||
|
||||
// Roster push
|
||||
con.send(iqResponse);
|
||||
|
||||
// Get the lists
|
||||
$(iqQuery).find('list').each(function() {
|
||||
Privacy.get($(this).attr('name'));
|
||||
});
|
||||
|
||||
Console.log('Received privacy lists push: ' + iqFrom);
|
||||
} catch(e) {
|
||||
Console.error('IQ._handlePrivacyLists', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles Roster Push
|
||||
* @private
|
||||
* @param {object} iqResponse
|
||||
* @param {string} iqFrom
|
||||
* @param {string} iqQuery
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._handleRosterPush = function(iqResponse, iqFrom, iqQuery) {
|
||||
|
||||
try {
|
||||
// REF : http://xmpp.org/extensions/xep-0092.html
|
||||
|
||||
// Roster push
|
||||
con.send(iqResponse);
|
||||
|
||||
// Get the values
|
||||
$(iqQuery).find('item').each(function() {
|
||||
Roster.parse($(this), 'presence');
|
||||
});
|
||||
|
||||
Console.log('Received roster push: ' + iqFrom);
|
||||
} catch(e) {
|
||||
Console.error('IQ._handleRosterPush', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles Roster Item Exchange
|
||||
* @private
|
||||
* @param {object} iqNode
|
||||
* @param {string} iqFrom
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._handleRosterItemExchange = function(iqNode, iqFrom) {
|
||||
|
||||
try {
|
||||
// Open a new notification
|
||||
Notification.create('rosterx', iqFrom, [iqNode], '');
|
||||
|
||||
Console.log('Roster Item Exchange from: ' + iqFrom);
|
||||
} catch(e) {
|
||||
Console.error('IQ._handleRosterItemExchange', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles Disco Info
|
||||
* @private
|
||||
* @param {object} iqResponse
|
||||
* @param {string} iqFrom
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._handleDiscoInfo = function(iqResponse, iqFrom) {
|
||||
|
||||
try {
|
||||
/* REF: http://xmpp.org/extensions/xep-0030.html */
|
||||
|
||||
iqQuery = iqResponse.setQuery(NS_DISCO_INFO);
|
||||
|
||||
// We set the name of the client
|
||||
iqQuery.appendChild(iqResponse.buildNode('identity', {
|
||||
'category': Caps.disco_infos.identity.category,
|
||||
'type': Caps.disco_infos.identity.type,
|
||||
'name': Caps.disco_infos.identity.name,
|
||||
'xmlns': NS_DISCO_INFO
|
||||
}));
|
||||
|
||||
// We set all the supported features
|
||||
var disco_infos = Caps.myDiscoInfos();
|
||||
|
||||
$.each(disco_infos, function(i, disco_info) {
|
||||
iqQuery.appendChild(iqResponse.buildNode('feature', {'var': disco_info, 'xmlns': NS_DISCO_INFO}));
|
||||
});
|
||||
|
||||
con.send(iqResponse);
|
||||
|
||||
Console.log('Received disco#infos query: ' + iqFrom);
|
||||
} catch(e) {
|
||||
Console.error('IQ._handleDiscoInfo', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles User Time
|
||||
* @private
|
||||
* @param {object} iqResponse
|
||||
* @param {string} iqFrom
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._handleUserTime = function(iqResponse, iqFrom) {
|
||||
|
||||
try {
|
||||
/* REF: http://xmpp.org/extensions/xep-0202.html */
|
||||
|
||||
var iqTime = iqResponse.appendNode('time', {
|
||||
'xmlns': NS_URN_TIME
|
||||
});
|
||||
|
||||
iqTime.appendChild(iqResponse.buildNode('tzo', {
|
||||
'xmlns': NS_URN_TIME
|
||||
}, DateUtils.getTZO()));
|
||||
|
||||
iqTime.appendChild(iqResponse.buildNode('utc', {
|
||||
'xmlns': NS_URN_TIME
|
||||
}, DateUtils.getXMPPTime('utc')));
|
||||
|
||||
con.send(iqResponse);
|
||||
|
||||
Console.log('Received local time query: ' + iqFrom);
|
||||
} catch(e) {
|
||||
Console.error('IQ._handleUserTime', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles Ping
|
||||
* @private
|
||||
* @param {object} iqResponse
|
||||
* @param {string} iqFrom
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._handlePing = function(iqResponse, iqFrom) {
|
||||
|
||||
try {
|
||||
/* REF: http://xmpp.org/extensions/xep-0199.html */
|
||||
|
||||
con.send(iqResponse);
|
||||
|
||||
Console.log('Received a ping: ' + iqFrom);
|
||||
} catch(e) {
|
||||
Console.error('IQ._handlePing', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles Jingle
|
||||
* @private
|
||||
* @param {string} iqFrom
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._handleJingle = function(iqFrom) {
|
||||
|
||||
try {
|
||||
/* REF: http://xmpp.org/extensions/xep-0166.html */
|
||||
|
||||
// Handled via JSJaCJingle.route() (see above)
|
||||
|
||||
Console.log('Received a Jingle packet: ' + iqFrom);
|
||||
} catch(e) {
|
||||
Console.error('IQ._handleJingle', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Raises a not implemented error
|
||||
* @private
|
||||
* @param {object} iqResponse
|
||||
* @param {object} iqNode
|
||||
* @param {string} iqFrom
|
||||
* @return {undefined}
|
||||
*/
|
||||
self._raiseNotImplemented = function(iqResponse, iqNode, iqFrom) {
|
||||
|
||||
try {
|
||||
// Change IQ type
|
||||
iqResponse.setType('error');
|
||||
|
||||
// Append stanza content
|
||||
for(var c = 0; c < iqNode.childNodes.length; c++) {
|
||||
iqResponse.getNode().appendChild(iqNode.childNodes.item(c).cloneNode(true));
|
||||
}
|
||||
|
||||
// Append error content
|
||||
var iqError = iqResponse.appendNode('error', {'xmlns': NS_CLIENT, 'code': '501', 'type': 'cancel'});
|
||||
iqError.appendChild(iqResponse.buildNode('feature-not-implemented', {'xmlns': NS_STANZAS}));
|
||||
iqError.appendChild(iqResponse.buildNode('text', {'xmlns': NS_STANZAS}, Common._e("The feature requested is not implemented by the recipient or server and therefore cannot be processed.")));
|
||||
|
||||
con.send(iqResponse);
|
||||
|
||||
Console.log('Received an unsupported IQ query from: ' + iqFrom);
|
||||
} catch(e) {
|
||||
Console.error('IQ._raiseNotImplemented', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles an incoming IQ packet
|
||||
* @public
|
||||
|
@ -37,190 +383,71 @@ var IQ = (function () {
|
|||
var iqQuery = iq.getQuery();
|
||||
var iqType = iq.getType();
|
||||
|
||||
// Handle Jingle packet?
|
||||
JSJaCJingle_route(iq);
|
||||
|
||||
// Build the response
|
||||
var iqResponse = new JSJaCIQ();
|
||||
|
||||
|
||||
iqResponse.setID(iqID);
|
||||
iqResponse.setTo(iqFrom);
|
||||
iqResponse.setType('result');
|
||||
|
||||
|
||||
// OOB request
|
||||
if((iqQueryXMLNS == NS_IQOOB) && (iqType == 'set')) {
|
||||
/* REF: http://xmpp.org/extensions/xep-0066.html */
|
||||
|
||||
OOB.handle(iqFrom, iqID, 'iq', iqNode);
|
||||
|
||||
Console.log('Received IQ OOB request: ' + iqFrom);
|
||||
self._handleOOBRequest(iqFrom, iqID, iqNode);
|
||||
}
|
||||
|
||||
|
||||
// OOB reply
|
||||
else if(DataStore.getDB(Connection.desktop_hash, 'send/url', iqID)) {
|
||||
// Get the values
|
||||
var oob_url = DataStore.getDB(Connection.desktop_hash, 'send/url', iqID);
|
||||
var oob_desc = DataStore.getDB(Connection.desktop_hash, 'send/desc', iqID);
|
||||
var notif_id = hex_md5(oob_url + oob_desc + iqType + iqFrom + iqID);
|
||||
|
||||
if($(iqNode).find('error').size()) {
|
||||
// Error?
|
||||
if($(iqNode).find('error not-acceptable').size()) {
|
||||
// Rejected?
|
||||
Notification.create('send_reject', iqFrom, [iqFrom, oob_url, 'iq', iqID, iqNode], oob_desc, notif_id);
|
||||
} else {
|
||||
// Failed?
|
||||
Notification.create('send_fail', iqFrom, [iqFrom, oob_url, 'iq', iqID, iqNode], oob_desc, notif_id);
|
||||
}
|
||||
|
||||
// Remove the file
|
||||
$.get(oob_url + '&action=remove');
|
||||
} else if(iqType == 'result') {
|
||||
// Success?
|
||||
Notification.create('send_accept', iqFrom, [iqFrom, oob_url, 'iq', iqID, iqNode], oob_desc, notif_id);
|
||||
}
|
||||
self._handleOOBReply(iqResponse, iqFrom, iqType, iqID, iqNode);
|
||||
}
|
||||
|
||||
|
||||
// Software version query
|
||||
else if((iqQueryXMLNS == NS_VERSION) && (iqType == 'get')) {
|
||||
/* REF: http://xmpp.org/extensions/xep-0092.html */
|
||||
|
||||
iqQuery = iqResponse.setQuery(NS_VERSION);
|
||||
|
||||
iqQuery.appendChild(iqResponse.buildNode('name', {'xmlns': NS_VERSION}, 'Jappix'));
|
||||
iqQuery.appendChild(iqResponse.buildNode('version', {'xmlns': NS_VERSION}, JAPPIX_VERSION));
|
||||
iqQuery.appendChild(iqResponse.buildNode('os', {'xmlns': NS_VERSION}, BrowserDetect.OS));
|
||||
|
||||
con.send(iqResponse);
|
||||
|
||||
Console.log('Received software version query: ' + iqFrom);
|
||||
self._handleSoftwareVersion(iqResponse, iqFrom);
|
||||
}
|
||||
|
||||
|
||||
// Last activity query
|
||||
else if((iqQueryXMLNS == NS_LAST) && (iqType == 'get')) {
|
||||
/* REF: http://xmpp.org/extensions/xep-0012.html */
|
||||
|
||||
iqQuery = iqResponse.setQuery(NS_LAST);
|
||||
iqQuery.setAttribute('seconds', DateUtils.getLastActivity());
|
||||
|
||||
con.send(iqResponse);
|
||||
|
||||
Console.log('Received last activity query: ' + iqFrom);
|
||||
self._handleLastActivity(iqResponse, iqFrom);
|
||||
}
|
||||
|
||||
|
||||
// Privacy lists push
|
||||
else if((iqQueryXMLNS == NS_PRIVACY) && (iqType == 'set') && Common.isSafeStanza(iq)) {
|
||||
// REF : http://xmpp.org/extensions/xep-0016.html
|
||||
|
||||
// Roster push
|
||||
con.send(iqResponse);
|
||||
|
||||
// Get the lists
|
||||
$(iqQuery).find('list').each(function() {
|
||||
Privacy.get($(this).attr('name'));
|
||||
});
|
||||
|
||||
Console.log('Received privacy lists push: ' + iqFrom);
|
||||
self._handlePrivacyLists(iqResponse, iqFrom, iqQuery);
|
||||
}
|
||||
|
||||
|
||||
// Roster push
|
||||
else if((iqQueryXMLNS == NS_ROSTER) && (iqType == 'set') && Common.isSafeStanza(iq)) {
|
||||
// REF : http://xmpp.org/extensions/xep-0092.html
|
||||
|
||||
// Roster push
|
||||
con.send(iqResponse);
|
||||
|
||||
// Get the values
|
||||
$(iqQuery).find('item').each(function() {
|
||||
Roster.parse($(this), 'presence');
|
||||
});
|
||||
|
||||
Console.log('Received roster push: ' + iqFrom);
|
||||
self._handleRosterPush(iqResponse, iqFrom, iqQuery);
|
||||
}
|
||||
|
||||
|
||||
// Roster Item Exchange query
|
||||
else if($(iqNode).find('x[xmlns="' + NS_ROSTERX + '"]').size()) {
|
||||
// Open a new notification
|
||||
Notification.create('rosterx', iqFrom, [iqNode], '');
|
||||
|
||||
Console.log('Roster Item Exchange from: ' + iqFrom);
|
||||
self._handleRosterItemExchange(iqNode, iqFrom);
|
||||
}
|
||||
|
||||
|
||||
// Disco info query
|
||||
else if((iqQueryXMLNS == NS_DISCO_INFO) && (iqType == 'get')) {
|
||||
/* REF: http://xmpp.org/extensions/xep-0030.html */
|
||||
|
||||
iqQuery = iqResponse.setQuery(NS_DISCO_INFO);
|
||||
|
||||
// We set the name of the client
|
||||
iqQuery.appendChild(iqResponse.buildNode('identity', {
|
||||
'category': 'client',
|
||||
'type': 'web',
|
||||
'name': 'Jappix',
|
||||
'xmlns': NS_DISCO_INFO
|
||||
}));
|
||||
|
||||
// We set all the supported features
|
||||
var disco_infos = Caps.myDiscoInfos();
|
||||
|
||||
$.each(disco_infos, function(i, disco_info) {
|
||||
iqQuery.appendChild(iqResponse.buildNode('feature', {'var': disco_info, 'xmlns': NS_DISCO_INFO}));
|
||||
});
|
||||
|
||||
con.send(iqResponse);
|
||||
|
||||
Console.log('Received disco#infos query: ' + iqFrom);
|
||||
self._handleDiscoInfo(iqResponse, iqFrom);
|
||||
}
|
||||
|
||||
|
||||
// User time query
|
||||
else if($(iqNode).find('time').size() && (iqType == 'get')) {
|
||||
/* REF: http://xmpp.org/extensions/xep-0202.html */
|
||||
|
||||
var iqTime = iqResponse.appendNode('time', {'xmlns': NS_URN_TIME});
|
||||
iqTime.appendChild(iqResponse.buildNode('tzo', {'xmlns': NS_URN_TIME}, DateUtils.getTZO()));
|
||||
iqTime.appendChild(iqResponse.buildNode('utc', {'xmlns': NS_URN_TIME}, DateUtils.getXMPPTime('utc')));
|
||||
|
||||
con.send(iqResponse);
|
||||
|
||||
Console.log('Received local time query: ' + iqFrom);
|
||||
self._handleUserTime(iqResponse, iqFrom);
|
||||
}
|
||||
|
||||
|
||||
// Ping
|
||||
else if($(iqNode).find('ping').size() && (iqType == 'get')) {
|
||||
/* REF: http://xmpp.org/extensions/xep-0199.html */
|
||||
|
||||
con.send(iqResponse);
|
||||
|
||||
Console.log('Received a ping: ' + iqFrom);
|
||||
self._handlePing(iqResponse, iqFrom);
|
||||
}
|
||||
|
||||
// Jingle
|
||||
else if($(iqNode).find('jingle').size()) {
|
||||
/* REF: http://xmpp.org/extensions/xep-0166.html */
|
||||
|
||||
// Handled via JSJaCJingle_route() (see above)
|
||||
|
||||
Console.log('Received a Jingle packet: ' + iqFrom);
|
||||
self._handleJingle(iqFrom);
|
||||
}
|
||||
|
||||
|
||||
// Not implemented
|
||||
else if(!$(iqNode).find('error').size() && ((iqType == 'get') || (iqType == 'set'))) {
|
||||
// Change IQ type
|
||||
iqResponse.setType('error');
|
||||
|
||||
// Append stanza content
|
||||
for(var c = 0; c < iqNode.childNodes.length; c++) {
|
||||
iqResponse.getNode().appendChild(iqNode.childNodes.item(c).cloneNode(true));
|
||||
}
|
||||
|
||||
// Append error content
|
||||
var iqError = iqResponse.appendNode('error', {'xmlns': NS_CLIENT, 'code': '501', 'type': 'cancel'});
|
||||
iqError.appendChild(iqResponse.buildNode('feature-not-implemented', {'xmlns': NS_STANZAS}));
|
||||
iqError.appendChild(iqResponse.buildNode('text', {'xmlns': NS_STANZAS}, Common._e("The feature requested is not implemented by the recipient or server and therefore cannot be processed.")));
|
||||
|
||||
con.send(iqResponse);
|
||||
|
||||
Console.log('Received an unsupported IQ query from: ' + iqFrom);
|
||||
self._raiseNotImplemented(iqResponse, iqNode, iqFrom);
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('IQ.handle', e);
|
||||
|
|
|
@ -72,7 +72,7 @@ feature.formdata = window.FormData !== undefined;
|
|||
var hasProp = !!$.fn.prop;
|
||||
|
||||
// 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
|
||||
// cases "prop" returns the element
|
||||
$.fn.attr2 = function() {
|
||||
|
@ -461,7 +461,7 @@ $.fn.ajaxSubmit = function(options) {
|
|||
|
||||
var CLIENT_TIMEOUT_ABORT = 1;
|
||||
var SERVER_ABORT = 2;
|
||||
|
||||
|
||||
function getDoc(frame) {
|
||||
/* it looks like contentWindow or contentDocument do not
|
||||
* 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?
|
||||
* "Same origin policy" http://en.wikipedia.org/wiki/Same_origin_policy
|
||||
*/
|
||||
|
||||
|
||||
var doc = null;
|
||||
|
||||
|
||||
// IE8 cascading access check
|
||||
try {
|
||||
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
|
||||
function doSubmit() {
|
||||
// make sure form attrs are set
|
||||
var t = $form.attr2('target'),
|
||||
a = $form.attr2('action'),
|
||||
var t = $form.attr2('target'),
|
||||
a = $form.attr2('action'),
|
||||
mp = 'multipart/form-data',
|
||||
et = $form.attr('enctype') || $form.attr('encoding') || mp;
|
||||
|
||||
|
@ -619,7 +619,7 @@ $.fn.ajaxSubmit = function(options) {
|
|||
if (xhr.aborted || callbackProcessed) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
doc = getDoc(io);
|
||||
if(!doc) {
|
||||
log('cannot access response document');
|
||||
|
|
16221
source/app/javascripts/jquery.js
vendored
|
@ -1,138 +1,138 @@
|
|||
/**
|
||||
* jQuery.timers - Timer abstractions for jQuery
|
||||
* Written by Blair Mitchelmore (blair DOT mitchelmore AT gmail DOT com)
|
||||
* Licensed under the WTFPL (http://sam.zoy.org/wtfpl/).
|
||||
* Date: 2009/10/16
|
||||
*
|
||||
* @author Blair Mitchelmore
|
||||
* @version 1.2
|
||||
*
|
||||
**/
|
||||
|
||||
jQuery.fn.extend({
|
||||
everyTime: function(interval, label, fn, times) {
|
||||
return this.each(function() {
|
||||
jQuery.timer.add(this, interval, label, fn, times);
|
||||
});
|
||||
},
|
||||
oneTime: function(interval, label, fn) {
|
||||
return this.each(function() {
|
||||
jQuery.timer.add(this, interval, label, fn, 1);
|
||||
});
|
||||
},
|
||||
stopTime: function(label, fn) {
|
||||
return this.each(function() {
|
||||
jQuery.timer.remove(this, label, fn);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
jQuery.extend({
|
||||
timer: {
|
||||
global: [],
|
||||
guid: 1,
|
||||
dataKey: "jQuery.timer",
|
||||
regex: /^([0-9]+(?:\.[0-9]*)?)\s*(.*s)?$/,
|
||||
powers: {
|
||||
// Yeah this is major overkill...
|
||||
'ms': 1,
|
||||
'cs': 10,
|
||||
'ds': 100,
|
||||
's': 1000,
|
||||
'das': 10000,
|
||||
'hs': 100000,
|
||||
'ks': 1000000
|
||||
},
|
||||
timeParse: function(value) {
|
||||
if (value == undefined || value == null)
|
||||
return null;
|
||||
var result = this.regex.exec(jQuery.trim(value.toString()));
|
||||
if (result[2]) {
|
||||
var num = parseFloat(result[1]);
|
||||
var mult = this.powers[result[2]] || 1;
|
||||
return num * mult;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
},
|
||||
add: function(element, interval, label, fn, times) {
|
||||
var counter = 0;
|
||||
|
||||
if (jQuery.isFunction(label)) {
|
||||
if (!times)
|
||||
times = fn;
|
||||
fn = label;
|
||||
label = interval;
|
||||
}
|
||||
|
||||
interval = jQuery.timer.timeParse(interval);
|
||||
|
||||
if (typeof interval != 'number' || isNaN(interval) || interval < 0)
|
||||
return;
|
||||
|
||||
if (typeof times != 'number' || isNaN(times) || times < 0)
|
||||
times = 0;
|
||||
|
||||
times = times || 0;
|
||||
|
||||
var timers = jQuery.data(element, this.dataKey) || jQuery.data(element, this.dataKey, {});
|
||||
|
||||
if (!timers[label])
|
||||
timers[label] = {};
|
||||
|
||||
fn.timerID = fn.timerID || this.guid++;
|
||||
|
||||
var handler = function() {
|
||||
if ((++counter > times && times !== 0) || fn.call(element, counter) === false)
|
||||
jQuery.timer.remove(element, label, fn);
|
||||
};
|
||||
|
||||
handler.timerID = fn.timerID;
|
||||
|
||||
if (!timers[label][fn.timerID])
|
||||
timers[label][fn.timerID] = window.setInterval(handler,interval);
|
||||
|
||||
this.global.push( element );
|
||||
|
||||
},
|
||||
remove: function(element, label, fn) {
|
||||
var timers = jQuery.data(element, this.dataKey), ret;
|
||||
|
||||
if ( timers ) {
|
||||
|
||||
if (!label) {
|
||||
for ( label in timers )
|
||||
this.remove(element, label, fn);
|
||||
} else if ( timers[label] ) {
|
||||
if ( fn ) {
|
||||
if ( fn.timerID ) {
|
||||
window.clearInterval(timers[label][fn.timerID]);
|
||||
delete timers[label][fn.timerID];
|
||||
}
|
||||
} else {
|
||||
for ( var fn in timers[label] ) {
|
||||
window.clearInterval(timers[label][fn]);
|
||||
delete timers[label][fn];
|
||||
}
|
||||
}
|
||||
|
||||
for ( ret in timers[label] ) break;
|
||||
if ( !ret ) {
|
||||
ret = null;
|
||||
delete timers[label];
|
||||
}
|
||||
}
|
||||
|
||||
for ( ret in timers ) break;
|
||||
if ( !ret )
|
||||
jQuery.removeData(element, this.dataKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
jQuery(window).bind("unload", function() {
|
||||
jQuery.each(jQuery.timer.global, function(index, item) {
|
||||
jQuery.timer.remove(item);
|
||||
});
|
||||
});
|
||||
/**
|
||||
* jQuery.timers - Timer abstractions for jQuery
|
||||
* Written by Blair Mitchelmore (blair DOT mitchelmore AT gmail DOT com)
|
||||
* Licensed under the WTFPL (http://sam.zoy.org/wtfpl/).
|
||||
* Date: 2009/10/16
|
||||
*
|
||||
* @author Blair Mitchelmore
|
||||
* @version 1.2
|
||||
*
|
||||
**/
|
||||
|
||||
jQuery.fn.extend({
|
||||
everyTime: function(interval, label, fn, times) {
|
||||
return this.each(function() {
|
||||
jQuery.timer.add(this, interval, label, fn, times);
|
||||
});
|
||||
},
|
||||
oneTime: function(interval, label, fn) {
|
||||
return this.each(function() {
|
||||
jQuery.timer.add(this, interval, label, fn, 1);
|
||||
});
|
||||
},
|
||||
stopTime: function(label, fn) {
|
||||
return this.each(function() {
|
||||
jQuery.timer.remove(this, label, fn);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
jQuery.extend({
|
||||
timer: {
|
||||
global: [],
|
||||
guid: 1,
|
||||
dataKey: "jQuery.timer",
|
||||
regex: /^([0-9]+(?:\.[0-9]*)?)\s*(.*s)?$/,
|
||||
powers: {
|
||||
// Yeah this is major overkill...
|
||||
'ms': 1,
|
||||
'cs': 10,
|
||||
'ds': 100,
|
||||
's': 1000,
|
||||
'das': 10000,
|
||||
'hs': 100000,
|
||||
'ks': 1000000
|
||||
},
|
||||
timeParse: function(value) {
|
||||
if (value == undefined || value == null)
|
||||
return null;
|
||||
var result = this.regex.exec(jQuery.trim(value.toString()));
|
||||
if (result[2]) {
|
||||
var num = parseFloat(result[1]);
|
||||
var mult = this.powers[result[2]] || 1;
|
||||
return num * mult;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
},
|
||||
add: function(element, interval, label, fn, times) {
|
||||
var counter = 0;
|
||||
|
||||
if (jQuery.isFunction(label)) {
|
||||
if (!times)
|
||||
times = fn;
|
||||
fn = label;
|
||||
label = interval;
|
||||
}
|
||||
|
||||
interval = jQuery.timer.timeParse(interval);
|
||||
|
||||
if (typeof interval != 'number' || isNaN(interval) || interval < 0)
|
||||
return;
|
||||
|
||||
if (typeof times != 'number' || isNaN(times) || times < 0)
|
||||
times = 0;
|
||||
|
||||
times = times || 0;
|
||||
|
||||
var timers = jQuery.data(element, this.dataKey) || jQuery.data(element, this.dataKey, {});
|
||||
|
||||
if (!timers[label])
|
||||
timers[label] = {};
|
||||
|
||||
fn.timerID = fn.timerID || this.guid++;
|
||||
|
||||
var handler = function() {
|
||||
if ((++counter > times && times !== 0) || fn.call(element, counter) === false)
|
||||
jQuery.timer.remove(element, label, fn);
|
||||
};
|
||||
|
||||
handler.timerID = fn.timerID;
|
||||
|
||||
if (!timers[label][fn.timerID])
|
||||
timers[label][fn.timerID] = window.setInterval(handler,interval);
|
||||
|
||||
this.global.push( element );
|
||||
|
||||
},
|
||||
remove: function(element, label, fn) {
|
||||
var timers = jQuery.data(element, this.dataKey), ret;
|
||||
|
||||
if ( timers ) {
|
||||
|
||||
if (!label) {
|
||||
for ( label in timers )
|
||||
this.remove(element, label, fn);
|
||||
} else if ( timers[label] ) {
|
||||
if ( fn ) {
|
||||
if ( fn.timerID ) {
|
||||
window.clearInterval(timers[label][fn.timerID]);
|
||||
delete timers[label][fn.timerID];
|
||||
}
|
||||
} else {
|
||||
for ( var fn in timers[label] ) {
|
||||
window.clearInterval(timers[label][fn]);
|
||||
delete timers[label][fn];
|
||||
}
|
||||
}
|
||||
|
||||
for ( ret in timers[label] ) break;
|
||||
if ( !ret ) {
|
||||
ret = null;
|
||||
delete timers[label];
|
||||
}
|
||||
}
|
||||
|
||||
for ( ret in timers ) break;
|
||||
if ( !ret )
|
||||
jQuery.removeData(element, this.dataKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
jQuery(window).bind("unload", function() {
|
||||
jQuery.each(jQuery.timer.global, function(index, item) {
|
||||
jQuery.timer.remove(item);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -13,12 +13,12 @@ Authors: Stefan Strigler, Valérian Saliou, Zash, Maranda
|
|||
/**
|
||||
* @fileoverview Magic dependency loading. Taken from script.aculo.us
|
||||
* and modified to break it.
|
||||
* @author Stefan Strigler steve@zeank.in-berlin.de
|
||||
* @version $Revision$
|
||||
* @author Stefan Strigler steve@zeank.in-berlin.de
|
||||
* @version 1.3
|
||||
*/
|
||||
|
||||
var JSJaC = {
|
||||
Version: '$Rev$',
|
||||
Version: '1.3',
|
||||
bind: function(fn, obj, optArg) {
|
||||
return function(arg) {
|
||||
return fn.apply(obj, [arg, optArg]);
|
||||
|
@ -26,9 +26,6 @@ var JSJaC = {
|
|||
}
|
||||
};
|
||||
|
||||
if (typeof JSJaCConnection == 'undefined')
|
||||
JSJaC.load();
|
||||
|
||||
|
||||
|
||||
/* Copyright 2006 Erik Arvidsson
|
||||
|
@ -52,7 +49,7 @@ if (typeof JSJaCConnection == 'undefined')
|
|||
* this code is taken from
|
||||
* http://webfx.eae.net/dhtml/xmlextras/xmlextras.html
|
||||
* @author Stefan Strigler steve@zeank.in-berlin.de
|
||||
* @version $Revision$
|
||||
* @version 1.3
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -71,18 +68,18 @@ XmlHttp.create = function () {
|
|||
// Able to use CORS?
|
||||
if (window.XMLHttpRequest) {
|
||||
var req = new XMLHttpRequest();
|
||||
|
||||
|
||||
if (req.withCredentials !== undefined)
|
||||
return req;
|
||||
}
|
||||
|
||||
|
||||
// Fallback on JSONP
|
||||
return new jXHR();
|
||||
}
|
||||
// Might be local-domain?
|
||||
if (window.XMLHttpRequest) {
|
||||
var req = new XMLHttpRequest();
|
||||
|
||||
|
||||
// some versions of Moz do not support the readyState property
|
||||
// and the onreadystate event so we patch it!
|
||||
if (req.readyState == null) {
|
||||
|
@ -93,7 +90,7 @@ XmlHttp.create = function () {
|
|||
req.onreadystatechange();
|
||||
}, false);
|
||||
}
|
||||
|
||||
|
||||
return req;
|
||||
}
|
||||
if (window.ActiveXObject) {
|
||||
|
@ -112,7 +109,7 @@ XmlHttp.create = function () {
|
|||
XmlHttp.getPrefix = function() {
|
||||
if (XmlHttp.prefix) // I know what you did last summer
|
||||
return XmlHttp.prefix;
|
||||
|
||||
|
||||
var prefixes = ["MSXML2", "Microsoft", "MSXML", "MSXML3"];
|
||||
var o;
|
||||
for (var i = 0; i < prefixes.length; i++) {
|
||||
|
@ -123,7 +120,7 @@ XmlHttp.getPrefix = function() {
|
|||
}
|
||||
catch (ex) {};
|
||||
}
|
||||
|
||||
|
||||
throw new Error("Could not find an installed XML parser");
|
||||
};
|
||||
|
||||
|
@ -156,7 +153,7 @@ XmlDocument.create = function (name,ns) {
|
|||
} else if (window.ActiveXObject) {
|
||||
doc = new ActiveXObject(XmlDocument.getPrefix() + ".DomDocument");
|
||||
}
|
||||
|
||||
|
||||
if (!doc.documentElement || doc.documentElement.tagName != name ||
|
||||
(doc.documentElement.namespaceURI &&
|
||||
doc.documentElement.namespaceURI != ns)) {
|
||||
|
@ -168,7 +165,7 @@ XmlDocument.create = function (name,ns) {
|
|||
doc.appendChild(doc.createElement(name));
|
||||
} catch (dex) {
|
||||
doc = document.implementation.createDocument(ns,name,null);
|
||||
|
||||
|
||||
if (doc.documentElement == null)
|
||||
doc.appendChild(doc.createElement(name));
|
||||
|
||||
|
@ -179,7 +176,7 @@ XmlDocument.create = function (name,ns) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return doc;
|
||||
}
|
||||
catch (ex) { }
|
||||
|
@ -204,7 +201,7 @@ XmlDocument.getPrefix = function() {
|
|||
}
|
||||
catch (ex) {};
|
||||
}
|
||||
|
||||
|
||||
throw new Error("Could not find an installed XML parser");
|
||||
};
|
||||
|
||||
|
@ -218,14 +215,14 @@ if (typeof(Document) != 'undefined' && window.DOMParser) {
|
|||
* @private
|
||||
*/
|
||||
Document.prototype.loadXML = function (s) {
|
||||
|
||||
|
||||
// parse the string to a new doc
|
||||
var doc2 = (new DOMParser()).parseFromString(s, "text/xml");
|
||||
|
||||
|
||||
// remove all initial children
|
||||
while (this.hasChildNodes())
|
||||
this.removeChild(this.lastChild);
|
||||
|
||||
|
||||
// insert and import nodes
|
||||
for (var i = 0; i < doc2.childNodes.length; i++) {
|
||||
this.appendChild(this.importNode(doc2.childNodes[i], true));
|
||||
|
@ -282,7 +279,7 @@ if (window.XMLSerializer &&
|
|||
/**
|
||||
* @fileoverview Collection of functions to make live easier
|
||||
* @author Stefan Strigler
|
||||
* @version $Revision$
|
||||
* @version 1.3
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -334,10 +331,10 @@ Date.jab2date = function(ts) {
|
|||
// Timestamp
|
||||
if(!isNaN(ts))
|
||||
return new Date(ts * 1000);
|
||||
|
||||
|
||||
// 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)));
|
||||
|
||||
|
||||
if (ts.substr(ts.length-6,1) != 'Z') { // there's an offset
|
||||
var date_offset = date.getTimezoneOffset() * 60 * 1000;
|
||||
var offset = new Date();
|
||||
|
@ -370,7 +367,7 @@ Date.hrTime = function(ts) {
|
|||
if (!Date.now) {
|
||||
Date.now = function() { return new Date().getTime(); }
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* somewhat opposit to {@link #hrTime}
|
||||
* expects a javascript Date object as parameter and returns a jabber
|
||||
|
@ -1088,7 +1085,7 @@ function utf8t2d(t)
|
|||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
// returns plaintext from an array of bytesrepresenting dezimal numbers, which
|
||||
// represent an UTF-8 encoded text; browser which does not understand unicode
|
||||
// like NN401 will show "?"-signs instead
|
||||
|
@ -1206,7 +1203,7 @@ function cnonce(size) {
|
|||
JSJAC_HAVEKEYS = true; // whether to use keys
|
||||
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
|
||||
JSJAC_ERR_COUNT = 10; // number of retries in case of connection
|
||||
// errors
|
||||
|
@ -1230,7 +1227,7 @@ JSJAC_REGID_TIMEOUT = 20000; // time in msec until registered
|
|||
JSJACHBC_MAX_HOLD = 1; // default for number of connctions
|
||||
// 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
|
||||
// connection manager
|
||||
|
||||
|
@ -1293,7 +1290,7 @@ JSJaCJSON.toString = function (obj) {
|
|||
a[a.length] = v;
|
||||
b = true;
|
||||
}
|
||||
} catch(e) {
|
||||
} catch(e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1334,7 +1331,7 @@ JSJaCJSON.toString = function (obj) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
a[a.length] = '}';
|
||||
return a.join('');
|
||||
}
|
||||
|
@ -1362,7 +1359,7 @@ switch (typeof(obj)) {
|
|||
return s.object(obj);
|
||||
case 'array':
|
||||
return s.array(obj);
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1381,7 +1378,7 @@ JSJaCJSON.parse = function (str) {
|
|||
* @fileoverview This file contains all things that make life easier when
|
||||
* dealing with JIDs
|
||||
* @author Stefan Strigler
|
||||
* @version $Revision$
|
||||
* @version 1.3
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -1714,7 +1711,7 @@ var JSJaCBuilder = {
|
|||
/**
|
||||
* @fileoverview Contains all Jabber/XMPP packet related classes.
|
||||
* @author Stefan Strigler steve@zeank.in-berlin.de
|
||||
* @version $Revision$
|
||||
* @version 1.3
|
||||
*/
|
||||
|
||||
var JSJACPACKET_USE_XMLNS = true;
|
||||
|
@ -2502,7 +2499,7 @@ function JSJaCError(code,type,condition) {
|
|||
* @constructor
|
||||
* @param {Function} func The hash function to be used for creating the keys
|
||||
* @param {Debugger} oDbg Reference to debugger implementation [optional]
|
||||
*/
|
||||
*/
|
||||
function JSJaCKeys(func,oDbg) {
|
||||
var seed = Math.random();
|
||||
|
||||
|
@ -2567,7 +2564,7 @@ function JSJaCKeys(func,oDbg) {
|
|||
* @fileoverview Contains all things in common for all subtypes of connections
|
||||
* supported.
|
||||
* @author Stefan Strigler steve@zeank.in-berlin.de
|
||||
* @version $Revision$
|
||||
* @version 1.3
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -2751,30 +2748,30 @@ JSJaCConnection.prototype.connected = function() { return this._connected; };
|
|||
*/
|
||||
JSJaCConnection.prototype.disconnect = function() {
|
||||
this._setStatus('disconnecting');
|
||||
|
||||
|
||||
if (!this.connected())
|
||||
return;
|
||||
this._connected = false;
|
||||
|
||||
|
||||
clearInterval(this._interval);
|
||||
clearInterval(this._inQto);
|
||||
|
||||
|
||||
if (this._timeout)
|
||||
clearTimeout(this._timeout); // remove timer
|
||||
|
||||
|
||||
var slot = this._getFreeSlot();
|
||||
// Intentionally synchronous
|
||||
this._req[slot] = this._setupRequest(false);
|
||||
|
||||
|
||||
request = this._getRequestString(false, true);
|
||||
|
||||
|
||||
this.oDbg.log("Disconnecting: " + request,4);
|
||||
this._req[slot].r.send(request);
|
||||
|
||||
|
||||
try {
|
||||
DataStore.removeDB(MINI_HASH, 'jsjac', 'state');
|
||||
} catch (e) {}
|
||||
|
||||
|
||||
this.oDbg.log("Disconnected: "+this._req[slot].r.responseText,2);
|
||||
this._handleEvent('ondisconnect');
|
||||
};
|
||||
|
@ -3119,7 +3116,7 @@ JSJaCConnection.prototype.status = function() { return this._status; };
|
|||
*/
|
||||
JSJaCConnection.prototype.suspend = function(has_pause) {
|
||||
var data = this.suspendToData(has_pause);
|
||||
|
||||
|
||||
try {
|
||||
var c = DataStore.setDB(MINI_HASH, 'jsjac', 'state', JSJaCJSON.toString(data));
|
||||
return c;
|
||||
|
@ -3136,7 +3133,7 @@ JSJaCConnection.prototype.suspend = function(has_pause) {
|
|||
* @type Object
|
||||
*/
|
||||
JSJaCConnection.prototype.suspendToData = function(has_pause) {
|
||||
|
||||
|
||||
// remove timers
|
||||
if(has_pause) {
|
||||
clearTimeout(this._timeout);
|
||||
|
@ -3145,7 +3142,7 @@ JSJaCConnection.prototype.suspendToData = function(has_pause) {
|
|||
|
||||
this._suspend();
|
||||
}
|
||||
|
||||
|
||||
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());
|
||||
var s = new Object();
|
||||
|
@ -3162,12 +3159,12 @@ JSJaCConnection.prototype.suspendToData = function(has_pause) {
|
|||
|
||||
s[u[i]] = o;
|
||||
}
|
||||
|
||||
|
||||
if(has_pause) {
|
||||
this._connected = false;
|
||||
this._setStatus('suspending');
|
||||
}
|
||||
|
||||
|
||||
return s;
|
||||
};
|
||||
|
||||
|
@ -3601,10 +3598,6 @@ JSJaCConnection.prototype._handlePID = function(packet) {
|
|||
if (!packet.getID())
|
||||
return false;
|
||||
|
||||
if (packet.pType() != 'iq' ||
|
||||
(packet.getType() != 'error' && packet.getType() != 'result'))
|
||||
return false;
|
||||
|
||||
var jid = packet.getFrom() || this.jid;
|
||||
|
||||
if (packet.getFrom() == this.domain)
|
||||
|
@ -3687,7 +3680,7 @@ JSJaCConnection.prototype._parseStreamFeatures = function(doc) {
|
|||
this._handleEvent('ondisconnect');
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
this.mechs = new Object();
|
||||
var lMec1 = doc.getElementsByTagName("mechanisms");
|
||||
this.has_sasl = false;
|
||||
|
@ -3706,7 +3699,7 @@ JSJaCConnection.prototype._parseStreamFeatures = function(doc) {
|
|||
this.oDbg.log("No support for SASL detected",2);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Get the server CAPS (if available)
|
||||
this.server_caps=null;
|
||||
var sCaps = doc.getElementsByTagName("c");
|
||||
|
@ -3714,7 +3707,7 @@ JSJaCConnection.prototype._parseStreamFeatures = function(doc) {
|
|||
var c_sCaps=sCaps.item(i);
|
||||
var x_sCaps=c_sCaps.getAttribute("xmlns");
|
||||
var v_sCaps=c_sCaps.getAttribute("ver");
|
||||
|
||||
|
||||
if ((x_sCaps == NS_CAPS) && v_sCaps) {
|
||||
this.server_caps=v_sCaps;
|
||||
break;
|
||||
|
@ -3723,10 +3716,10 @@ JSJaCConnection.prototype._parseStreamFeatures = function(doc) {
|
|||
|
||||
// Get legacy session capability if available
|
||||
this.legacy_sessions=null;
|
||||
if (doc.getElementsByTagName("session")[0]) {
|
||||
if (doc.getElementsByTagName("session")) {
|
||||
this.legacy_sessions=true;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
|
@ -3955,7 +3948,7 @@ JSJaCConnection.prototype._setStatus = function(status) {
|
|||
/**
|
||||
* @fileoverview All stuff related to HTTP Binding
|
||||
* @author Stefan Strigler steve@zeank.in-berlin.de
|
||||
* @version $Revision$
|
||||
* @version 1.3
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -4169,13 +4162,13 @@ JSJaCHttpBindingConnection.prototype._getStreamID = function(req) {
|
|||
return;
|
||||
}
|
||||
var body = req.responseXML.documentElement;
|
||||
|
||||
|
||||
// any session error?
|
||||
if(body.getAttribute('type') == 'terminate') {
|
||||
this._handleEvent('onerror',JSJaCError('503','cancel','service-unavailable'));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// extract stream id used for non-SASL authentication
|
||||
if (body.getAttribute('authid')) {
|
||||
this.streamid = body.getAttribute('authid');
|
||||
|
@ -4451,7 +4444,7 @@ JSJaCHttpBindingConnection.prototype._reInitStreamWait = function(req, cb) {
|
|||
var featuresNL = doc.getElementsByTagName('stream:features');
|
||||
for (var i=0, l=featuresNL.length; i<l; i++) {
|
||||
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') {
|
||||
var features = featuresNL.item(i);
|
||||
break;
|
||||
|
@ -4461,7 +4454,7 @@ JSJaCHttpBindingConnection.prototype._reInitStreamWait = function(req, cb) {
|
|||
var bind = features.getElementsByTagName('bind');
|
||||
for (var i=0, l=bind.length; i<l; i++) {
|
||||
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') {
|
||||
bind = bind.item(i);
|
||||
break;
|
||||
|
@ -4471,7 +4464,7 @@ JSJaCHttpBindingConnection.prototype._reInitStreamWait = function(req, cb) {
|
|||
}
|
||||
this.oDbg.log(features);
|
||||
this.oDbg.log(bind);
|
||||
|
||||
|
||||
if (features) {
|
||||
if (bind) {
|
||||
cb();
|
||||
|
@ -4865,7 +4858,26 @@ JSJaCWebSocketConnection.prototype._parseXml = function(s) {
|
|||
this.oDbg.log('Parsing: ' + s, 4);
|
||||
try {
|
||||
doc = XmlDocument.create('stream', NS_STREAM);
|
||||
if(s.indexOf('<stream:stream') === -1) {
|
||||
if(s.trim() == '</stream:stream>') {
|
||||
// Consider session as closed
|
||||
this.oDbg.log("session terminated", 1);
|
||||
|
||||
clearTimeout(this._timeout); // remove timer
|
||||
clearInterval(this._interval);
|
||||
clearInterval(this._inQto);
|
||||
|
||||
try {
|
||||
DataStore.removeDB(MINI_HASH, 'jsjac', 'state');
|
||||
} catch (e) {}
|
||||
|
||||
this._connected = false;
|
||||
this._handleEvent('onerror',JSJaCError('503','cancel','session-terminate'));
|
||||
|
||||
this.oDbg.log("Disconnected.",1);
|
||||
this._handleEvent('ondisconnect');
|
||||
|
||||
return null;
|
||||
} else if(s.indexOf('<stream:stream') === -1) {
|
||||
// Wrap every stanza into stream element, so that XML namespaces work properly.
|
||||
doc.loadXML("<stream:stream xmlns:stream='" + NS_STREAM + "' xmlns='jabber:client'>" + s + "</stream:stream>");
|
||||
return doc.documentElement.firstChild;
|
||||
|
@ -5018,3 +5030,61 @@ JSJaCWebSocketConnection.prototype._sendRaw = function(xml, cb, arg) {
|
|||
return true;
|
||||
};
|
||||
|
||||
/*exported JSJaCUtils */
|
||||
|
||||
/**
|
||||
* Various utilities put together so that they don't pollute global
|
||||
* name space.
|
||||
* @namespace
|
||||
*/
|
||||
var JSJaCUtils = {
|
||||
/**
|
||||
* XOR two strings of equal length.
|
||||
* @param {string} s1 first string to XOR.
|
||||
* @param {string} s2 second string to XOR.
|
||||
* @return {string} s1 ^ s2.
|
||||
*/
|
||||
xor: function(s1, s2) {
|
||||
/*jshint bitwise: false */
|
||||
if(!s1) {
|
||||
return s2;
|
||||
}
|
||||
if(!s2) {
|
||||
return s1;
|
||||
}
|
||||
|
||||
var result = '';
|
||||
for(var i = 0; i < s1.length; i++) {
|
||||
result += String.fromCharCode(s1.charCodeAt(i) ^ s2.charCodeAt(i));
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
* Create nonce value of given size.
|
||||
* @param {int} size size of the nonce that should be generated.
|
||||
* @return {string} generated nonce.
|
||||
*/
|
||||
cnonce: function(size) {
|
||||
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
var cnonce = '';
|
||||
for (var i = 0; i < size; i++) {
|
||||
cnonce += tab.charAt(Math.round(Math.random(new Date().getTime()) * (tab.length - 1)));
|
||||
}
|
||||
return cnonce;
|
||||
},
|
||||
|
||||
/**
|
||||
* Current timestamp.
|
||||
* @return Seconds since 1.1.1970.
|
||||
* @type int
|
||||
*/
|
||||
now: function() {
|
||||
if (Date.now && typeof Date.now == 'function') {
|
||||
return Date.now();
|
||||
} else {
|
||||
return new Date().getTime();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -1,116 +1,116 @@
|
|||
// jXHR.js (JSON-P XHR)
|
||||
// v0.1 (c) Kyle Simpson
|
||||
// License: MIT
|
||||
// modified by gueron Jonathan to work with strophe lib
|
||||
// for http://www.iadvize.com
|
||||
|
||||
(function(global){
|
||||
var SETTIMEOUT = global.setTimeout, // for better compression
|
||||
doc = global.document,
|
||||
callback_counter = 0;
|
||||
|
||||
global.jXHR = function() {
|
||||
var script_url,
|
||||
script_loaded,
|
||||
jsonp_callback,
|
||||
scriptElem,
|
||||
publicAPI = null;
|
||||
|
||||
function removeScript() { try { scriptElem.parentNode.removeChild(scriptElem); } catch (err) { } }
|
||||
|
||||
function reset() {
|
||||
script_loaded = false;
|
||||
script_url = "";
|
||||
removeScript();
|
||||
scriptElem = null;
|
||||
fireReadyStateChange(0);
|
||||
}
|
||||
|
||||
function ThrowError(msg) {
|
||||
try {
|
||||
publicAPI.onerror.call(publicAPI,msg,script_url);
|
||||
} catch (err) {
|
||||
//throw new Error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
function handleScriptLoad() {
|
||||
if ((this.readyState && this.readyState!=="complete" && this.readyState!=="loaded") || script_loaded) { return; }
|
||||
this.onload = this.onreadystatechange = null; // prevent memory leak
|
||||
script_loaded = true;
|
||||
if (publicAPI.readyState !== 4) ThrowError("handleScriptLoad: Script failed to load ["+script_url+"].");
|
||||
removeScript();
|
||||
}
|
||||
|
||||
function parseXMLString(xmlStr) {
|
||||
var xmlDoc = null;
|
||||
if(window.DOMParser) {
|
||||
var parser = new DOMParser();
|
||||
xmlDoc = parser.parseFromString(xmlStr,"text/xml");
|
||||
}
|
||||
else {
|
||||
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
|
||||
xmlDoc.async="false";
|
||||
xmlDoc.loadXML(xmlStr);
|
||||
}
|
||||
return xmlDoc;
|
||||
}
|
||||
|
||||
function fireReadyStateChange(rs,args) {
|
||||
|
||||
args = args || [];
|
||||
publicAPI.readyState = rs;
|
||||
if (rs == 4) {
|
||||
publicAPI.responseText = args[0].reply;
|
||||
publicAPI.responseXML = parseXMLString(args[0].reply);
|
||||
}
|
||||
if (typeof publicAPI.onreadystatechange === "function") publicAPI.onreadystatechange.apply(publicAPI,args);
|
||||
}
|
||||
|
||||
publicAPI = {
|
||||
onerror:null,
|
||||
onreadystatechange:null,
|
||||
readyState:0,
|
||||
status:200,
|
||||
responseBody: null,
|
||||
responseText: null,
|
||||
responseXML: null,
|
||||
open:function(method,url){
|
||||
reset();
|
||||
var internal_callback = "cb"+(callback_counter++);
|
||||
(function(icb){
|
||||
global.jXHR[icb] = function() {
|
||||
try { fireReadyStateChange.call(publicAPI,4,arguments); }
|
||||
catch(err) {
|
||||
publicAPI.readyState = -1;
|
||||
ThrowError("Script failed to run ["+script_url+"].");
|
||||
}
|
||||
global.jXHR[icb] = null;
|
||||
};
|
||||
})(internal_callback);
|
||||
script_url = url + '?callback=?jXHR&data=';
|
||||
script_url = script_url.replace(/=\?jXHR/,"=jXHR."+internal_callback);
|
||||
fireReadyStateChange(1);
|
||||
},
|
||||
send:function(data){
|
||||
script_url = script_url + encodeURIComponent(data);
|
||||
SETTIMEOUT(function(){
|
||||
scriptElem = doc.createElement("script");
|
||||
scriptElem.setAttribute("type","text/javascript");
|
||||
scriptElem.onload = scriptElem.onreadystatechange = function(){handleScriptLoad.call(scriptElem);};
|
||||
scriptElem.setAttribute("src",script_url);
|
||||
doc.getElementsByTagName("head")[0].appendChild(scriptElem);
|
||||
},0);
|
||||
fireReadyStateChange(2);
|
||||
},
|
||||
abort:function(){},
|
||||
setRequestHeader:function(){}, // noop
|
||||
getResponseHeader:function(){return "";}, // basically noop
|
||||
getAllResponseHeaders:function(){return [];} // ditto
|
||||
};
|
||||
|
||||
reset();
|
||||
|
||||
return publicAPI;
|
||||
};
|
||||
})(window);
|
||||
// jXHR.js (JSON-P XHR)
|
||||
// v0.1 (c) Kyle Simpson
|
||||
// License: MIT
|
||||
// modified by gueron Jonathan to work with strophe lib
|
||||
// for http://www.iadvize.com
|
||||
|
||||
(function(global){
|
||||
var SETTIMEOUT = global.setTimeout, // for better compression
|
||||
doc = global.document,
|
||||
callback_counter = 0;
|
||||
|
||||
global.jXHR = function() {
|
||||
var script_url,
|
||||
script_loaded,
|
||||
jsonp_callback,
|
||||
scriptElem,
|
||||
publicAPI = null;
|
||||
|
||||
function removeScript() { try { scriptElem.parentNode.removeChild(scriptElem); } catch (err) { } }
|
||||
|
||||
function reset() {
|
||||
script_loaded = false;
|
||||
script_url = "";
|
||||
removeScript();
|
||||
scriptElem = null;
|
||||
fireReadyStateChange(0);
|
||||
}
|
||||
|
||||
function ThrowError(msg) {
|
||||
try {
|
||||
publicAPI.onerror.call(publicAPI,msg,script_url);
|
||||
} catch (err) {
|
||||
//throw new Error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
function handleScriptLoad() {
|
||||
if ((this.readyState && this.readyState!=="complete" && this.readyState!=="loaded") || script_loaded) { return; }
|
||||
this.onload = this.onreadystatechange = null; // prevent memory leak
|
||||
script_loaded = true;
|
||||
if (publicAPI.readyState !== 4) ThrowError("handleScriptLoad: Script failed to load ["+script_url+"].");
|
||||
removeScript();
|
||||
}
|
||||
|
||||
function parseXMLString(xmlStr) {
|
||||
var xmlDoc = null;
|
||||
if(window.DOMParser) {
|
||||
var parser = new DOMParser();
|
||||
xmlDoc = parser.parseFromString(xmlStr,"text/xml");
|
||||
}
|
||||
else {
|
||||
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
|
||||
xmlDoc.async="false";
|
||||
xmlDoc.loadXML(xmlStr);
|
||||
}
|
||||
return xmlDoc;
|
||||
}
|
||||
|
||||
function fireReadyStateChange(rs,args) {
|
||||
|
||||
args = args || [];
|
||||
publicAPI.readyState = rs;
|
||||
if (rs == 4) {
|
||||
publicAPI.responseText = args[0].reply;
|
||||
publicAPI.responseXML = parseXMLString(args[0].reply);
|
||||
}
|
||||
if (typeof publicAPI.onreadystatechange === "function") publicAPI.onreadystatechange.apply(publicAPI,args);
|
||||
}
|
||||
|
||||
publicAPI = {
|
||||
onerror:null,
|
||||
onreadystatechange:null,
|
||||
readyState:0,
|
||||
status:200,
|
||||
responseBody: null,
|
||||
responseText: null,
|
||||
responseXML: null,
|
||||
open:function(method,url){
|
||||
reset();
|
||||
var internal_callback = "cb"+(callback_counter++);
|
||||
(function(icb){
|
||||
global.jXHR[icb] = function() {
|
||||
try { fireReadyStateChange.call(publicAPI,4,arguments); }
|
||||
catch(err) {
|
||||
publicAPI.readyState = -1;
|
||||
ThrowError("Script failed to run ["+script_url+"].");
|
||||
}
|
||||
global.jXHR[icb] = null;
|
||||
};
|
||||
})(internal_callback);
|
||||
script_url = url + '?callback=?jXHR&data=';
|
||||
script_url = script_url.replace(/=\?jXHR/,"=jXHR."+internal_callback);
|
||||
fireReadyStateChange(1);
|
||||
},
|
||||
send:function(data){
|
||||
script_url = script_url + encodeURIComponent(data);
|
||||
SETTIMEOUT(function(){
|
||||
scriptElem = doc.createElement("script");
|
||||
scriptElem.setAttribute("type","text/javascript");
|
||||
scriptElem.onload = scriptElem.onreadystatechange = function(){handleScriptLoad.call(scriptElem);};
|
||||
scriptElem.setAttribute("src",script_url);
|
||||
doc.getElementsByTagName("head")[0].appendChild(scriptElem);
|
||||
},0);
|
||||
fireReadyStateChange(2);
|
||||
},
|
||||
abort:function(){},
|
||||
setRequestHeader:function(){}, // noop
|
||||
getResponseHeader:function(){return "";}, // basically noop
|
||||
getAllResponseHeaders:function(){return [];} // ditto
|
||||
};
|
||||
|
||||
reset();
|
||||
|
||||
return publicAPI;
|
||||
};
|
||||
})(window);
|
||||
|
|
|
@ -32,25 +32,33 @@ var Links = (function () {
|
|||
|
||||
try {
|
||||
var target;
|
||||
|
||||
|
||||
// Links style
|
||||
if(!style)
|
||||
if(!style) {
|
||||
style = '';
|
||||
else
|
||||
} else {
|
||||
style = ' style="' + style + '"';
|
||||
|
||||
}
|
||||
|
||||
// Open in new tabs
|
||||
if(mode != 'xhtml-im')
|
||||
if(mode != 'xhtml-im') {
|
||||
target = ' target="_blank"';
|
||||
else
|
||||
} else {
|
||||
target = '';
|
||||
|
||||
}
|
||||
|
||||
// XMPP address
|
||||
string = string.replace(/(\s|<br \/>|^)(([a-zA-Z0-9\._-]+)@([a-zA-Z0-9\.\/_-]+))(,|\s|$)/gi, '$1<a href="xmpp:$2" target="_blank"' + style + '>$2</a>$5');
|
||||
|
||||
string = string.replace(
|
||||
/(\s|<br \/>|^)(([a-zA-Z0-9\._-]+)@([a-zA-Z0-9\.\/_-]+))(,|\s|$)/gi,
|
||||
'$1<a href="xmpp:$2" target="_blank"' + style + '>$2</a>$5'
|
||||
);
|
||||
|
||||
// Simple link
|
||||
string = string.replace(/(\s|<br \/>|^|\()((https?|ftp|file|xmpp|irc|mailto|vnc|webcal|ssh|ldap|smb|magnet|spotify)(:)([^<>'"\s\)]+))/gim, '$1<a href="$2"' + target + style + '>$2</a>');
|
||||
|
||||
string = string.replace(
|
||||
/(\s|<br \/>|^|\()((https?|ftp|file|xmpp|irc|mailto|vnc|webcal|ssh|ldap|smb|magnet|spotify)(:)([^<>'"\s\)]+))/gim,
|
||||
'$1<a href="$2"' + target + style + '>$2</a>'
|
||||
);
|
||||
|
||||
return string;
|
||||
} catch(e) {
|
||||
Console.error('Links.apply', e);
|
||||
|
|
|
@ -35,6 +35,7 @@ var MAM = (function () {
|
|||
self.map_reqs = {};
|
||||
self.map_pending = {};
|
||||
self.map_states = {};
|
||||
self.map_messages = {};
|
||||
self.msg_queue = {};
|
||||
|
||||
|
||||
|
@ -48,7 +49,7 @@ var MAM = (function () {
|
|||
try {
|
||||
// Lock the archiving options
|
||||
$('#archiving').attr('disabled', true);
|
||||
|
||||
|
||||
// Get the archiving configuration
|
||||
var iq = new JSJaCIQ();
|
||||
iq.setType('get');
|
||||
|
@ -145,7 +146,7 @@ var MAM = (function () {
|
|||
for(var c in args) {
|
||||
if(args[c]) purge.appendChild(iq.buildNode(c, {'xmlns': NS_METRONOME_MAM_PURGE}, args[c]));
|
||||
}
|
||||
|
||||
|
||||
con.send(iq, function(iq) {
|
||||
if(iq.getType() == 'result') {
|
||||
Console.info('Archives purged (MAM).');
|
||||
|
@ -252,7 +253,7 @@ var MAM = (function () {
|
|||
|
||||
// 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_content_sel = $('#' + hex_md5(res_with) + ' .content');
|
||||
var target_wait_sel = target_content_sel.find('.wait-mam');
|
||||
|
||||
|
@ -311,11 +312,16 @@ var MAM = (function () {
|
|||
if(c_message[0]) {
|
||||
// Re-build a proper JSJaC message stanza
|
||||
var message = JSJaCPacket.wrapNode(c_message[0]);
|
||||
var message_node = message.getNode();
|
||||
|
||||
// Check message type
|
||||
var type = message.getType() || 'chat';
|
||||
|
||||
if(type == 'chat') {
|
||||
// Display function
|
||||
var c_display_fn;
|
||||
var c_display_msg_bool = false;
|
||||
|
||||
// Read message data
|
||||
var xid = Common.bareXID(Common.getStanzaFrom(message));
|
||||
var id = message.getID();
|
||||
|
@ -331,50 +337,100 @@ var MAM = (function () {
|
|||
var hash = hex_md5(xid);
|
||||
var body = message.getBody();
|
||||
|
||||
// Read delay (required since we deal w/ a past message!)
|
||||
var time, stamp;
|
||||
var delay = c_delay.attr('stamp');
|
||||
// Content message?
|
||||
if(body) {
|
||||
// Read delay (required since we deal w/ a past message!)
|
||||
var time, stamp;
|
||||
var delay = c_delay.attr('stamp');
|
||||
|
||||
if(delay) {
|
||||
time = DateUtils.relative(delay);
|
||||
stamp = DateUtils.extractStamp(Date.jab2date(delay));
|
||||
}
|
||||
|
||||
// Last-minute checks before display
|
||||
if(time && stamp && body) {
|
||||
var mam_chunk_path = '#' + hash + ' .mam-chunk';
|
||||
|
||||
// No chat auto-scroll?
|
||||
var no_scroll = Common.exists(mam_chunk_path);
|
||||
|
||||
// Select the custom target
|
||||
var c_target_sel = function() {
|
||||
return $(mam_chunk_path).filter(function() {
|
||||
return $(this).attr('data-start') <= stamp && $(this).attr('data-end') >= stamp;
|
||||
}).filter(':first');
|
||||
};
|
||||
|
||||
// Display the message in that target
|
||||
var c_msg_display = function() {
|
||||
Message.display(type, from_xid, hash, b_name.htmlEnc(), body, time, stamp, 'old-message', true, null, mode, null, c_target_sel(), no_scroll);
|
||||
};
|
||||
|
||||
// Hack: do not display the message in case we would duplicate it w/ current session messages
|
||||
// only used when initiating a new chat, avoids collisions
|
||||
if(!(xid in self.map_states) && $('#' + hash).find('.one-line.user-message:last').text() == body) {
|
||||
return;
|
||||
if(delay) {
|
||||
time = DateUtils.relative(delay);
|
||||
stamp = DateUtils.extractStamp(Date.jab2date(delay));
|
||||
}
|
||||
|
||||
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
|
||||
c_msg_display();
|
||||
c_display_fn = function() {
|
||||
// Display message
|
||||
Message.display(
|
||||
type,
|
||||
from_xid,
|
||||
hash,
|
||||
b_name.htmlEnc(),
|
||||
body,
|
||||
time,
|
||||
stamp,
|
||||
'old-message',
|
||||
true,
|
||||
null,
|
||||
mode,
|
||||
id + '-mam',
|
||||
c_target_sel(),
|
||||
no_scroll,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
is_markable
|
||||
);
|
||||
|
||||
self.map_messages[id] = 1;
|
||||
};
|
||||
|
||||
c_display_msg_bool = c_target_sel().size() ? true : false;
|
||||
|
||||
// Hack: do not display the message in case we would duplicate it w/ current session messages
|
||||
// only used when initiating a new chat, avoids collisions
|
||||
if(!(xid in self.map_states) && $('#' + hash).find('.one-line.user-message:last').text() == body) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if(Markers.hasResponseMarker(message_node)) {
|
||||
// Marked message? (by other party)
|
||||
if(mode == 'him') {
|
||||
var marked_message_id = Markers.getMessageID(message_node);
|
||||
|
||||
c_display_fn = function() {
|
||||
var is_mam_marker = true;
|
||||
|
||||
Markers.handle(
|
||||
from_xid,
|
||||
message_node,
|
||||
is_mam_marker
|
||||
);
|
||||
};
|
||||
|
||||
c_display_msg_bool = (self.map_messages[marked_message_id] === 1) ? true : false;
|
||||
}
|
||||
}
|
||||
|
||||
// Display message?
|
||||
if(typeof c_display_fn == 'function') {
|
||||
if(c_display_msg_bool === true) {
|
||||
// Display message now
|
||||
c_display_fn();
|
||||
} else {
|
||||
// Delay display (we may not have received the MAM reply ATM)
|
||||
if(typeof self.msg_queue[xid] != 'object') {
|
||||
self.msg_queue[xid] = [];
|
||||
}
|
||||
|
||||
self.msg_queue[xid].push(c_msg_display);
|
||||
self.msg_queue[xid].push(c_display_fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
428
source/app/javascripts/markers.js
Normal file
|
@ -0,0 +1,428 @@
|
|||
/*
|
||||
|
||||
Jappix - An open social platform
|
||||
Implementation of XEP-0333: Chat Markers
|
||||
|
||||
-------------------------------------------------
|
||||
|
||||
License: AGPL
|
||||
Author: Valérian Saliou
|
||||
|
||||
*/
|
||||
|
||||
// Bundle
|
||||
var Markers = (function () {
|
||||
|
||||
/**
|
||||
* Alias of this
|
||||
* @private
|
||||
*/
|
||||
var self = {};
|
||||
|
||||
|
||||
/* Constants */
|
||||
self.MARK_TYPE_MARKABLE = 'markable';
|
||||
self.MARK_TYPE_RECEIVED = 'received';
|
||||
self.MARK_TYPE_DISPLAYED = 'displayed';
|
||||
self.MARK_TYPE_ACKNOWLEDGED = 'acknowledged';
|
||||
|
||||
self.MARK_TYPES = {};
|
||||
self.MARK_TYPES[self.MARK_TYPE_MARKABLE] = 1;
|
||||
self.MARK_TYPES[self.MARK_TYPE_RECEIVED] = 1;
|
||||
self.MARK_TYPES[self.MARK_TYPE_DISPLAYED] = 1;
|
||||
self.MARK_TYPES[self.MARK_TYPE_ACKNOWLEDGED] = 1;
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether entity supports message markers
|
||||
* @public
|
||||
* @param {string} xid
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.hasSupport = function(xid) {
|
||||
|
||||
var has_support = false;
|
||||
|
||||
try {
|
||||
has_support = true ? $('#' + hex_md5(xid)).attr('data-markers') == 'true' : false;
|
||||
} catch(e) {
|
||||
Console.error('Markers.hasSupport', e);
|
||||
} finally {
|
||||
return has_support;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether request message is marked or not
|
||||
* @public
|
||||
* @param {object} message
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.hasRequestMarker = function(message) {
|
||||
|
||||
var has_request_marker = false;
|
||||
|
||||
try {
|
||||
has_request_marker = ($(message).find('markable[xmlns="' + NS_URN_MARKERS + '"]').size() ? true : false);
|
||||
} catch(e) {
|
||||
Console.error('Markers.hasRequestMarker', e);
|
||||
} finally {
|
||||
return has_request_marker;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether response message is marked or not
|
||||
* @public
|
||||
* @param {object} message
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.hasResponseMarker = function(message) {
|
||||
|
||||
var has_response_marker = false;
|
||||
|
||||
try {
|
||||
var marker_sel = $(message).find('[xmlns="' + NS_URN_MARKERS + '"]');
|
||||
|
||||
if(marker_sel.size()) {
|
||||
var mark_type = marker_sel.prop('tagName').toLowerCase();
|
||||
|
||||
switch(mark_type) {
|
||||
case self.MARK_TYPE_RECEIVED:
|
||||
case self.MARK_TYPE_DISPLAYED:
|
||||
case self.MARK_TYPE_ACKNOWLEDGED:
|
||||
has_response_marker = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Markers.hasResponseMarker', e);
|
||||
} finally {
|
||||
return has_response_marker;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the marked message ID
|
||||
* @public
|
||||
* @param {object} message
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.getMessageID = function(message) {
|
||||
|
||||
var message_id = null;
|
||||
|
||||
try {
|
||||
message_id = $(message).find('[xmlns="' + NS_URN_MARKERS + '"]').attr('id');
|
||||
} catch(e) {
|
||||
Console.error('Markers.getMessageID', e);
|
||||
} finally {
|
||||
return message_id;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Marks a message
|
||||
* @public
|
||||
* @param {object} message
|
||||
* @return {undefined}
|
||||
*/
|
||||
self.mark = function(message) {
|
||||
|
||||
try {
|
||||
message.appendNode('markable', {
|
||||
'xmlns': NS_URN_MARKERS
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('Markers.mark', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Changes received message status (once received or read)
|
||||
* @public
|
||||
* @param {string} mark_type
|
||||
* @param {object} message_id
|
||||
* @return {undefined}
|
||||
*/
|
||||
self.change = function(to, mark_type, message_id, message_sel) {
|
||||
|
||||
try {
|
||||
if(!(mark_type in self.MARK_TYPES)) {
|
||||
throw 'Marker type (' + mark_type + ') not supported, aborting.';
|
||||
}
|
||||
|
||||
// Store mark state
|
||||
message_sel.attr('data-mark', mark_type);
|
||||
|
||||
var message = new JSJaCMessage();
|
||||
|
||||
message.setType('chat');
|
||||
message.setTo(to);
|
||||
|
||||
message.appendNode(mark_type, {
|
||||
'xmlns': NS_URN_MARKERS,
|
||||
'id': message_id
|
||||
});
|
||||
|
||||
con.send(message);
|
||||
|
||||
Console.debug('Markers.change', 'Changed marker to: ' + mark_type + ' for message with ID: ' + message_id + ' from: ' + to);
|
||||
} catch(e) {
|
||||
Console.error('Markers.change', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles marker change coming from Carbons
|
||||
* @public
|
||||
* @param {string} message
|
||||
* @return {undefined}
|
||||
*/
|
||||
self.handleCarbonChange = function(message) {
|
||||
|
||||
try {
|
||||
// Check the marker element is existing
|
||||
var marker_sel = $(message).find('[xmlns="' + NS_URN_MARKERS + '"]');
|
||||
|
||||
if(marker_sel.size()) {
|
||||
var xid = Common.bareXID(message.getTo());
|
||||
|
||||
var mark_type = marker_sel.prop('tagName').toLowerCase();
|
||||
var mark_handle = false;
|
||||
|
||||
// Filter allowed markers
|
||||
switch(mark_type) {
|
||||
case self.MARK_TYPE_RECEIVED:
|
||||
case self.MARK_TYPE_DISPLAYED:
|
||||
case self.MARK_TYPE_ACKNOWLEDGED:
|
||||
mark_handle = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if(mark_handle === true) {
|
||||
var mark_message_id = marker_sel.attr('id');
|
||||
|
||||
var message_sel = $('#' + hex_md5(xid) + ' .content .one-line[data-mode="him"][data-markable="true"]').filter(function() {
|
||||
return ($(this).attr('data-id') + '') === (mark_message_id + '');
|
||||
}).filter(':last');
|
||||
|
||||
if(!message_sel.size()) {
|
||||
Console.warn('Markers.handleCarbonChange', 'Unknown message marker to keep in sync with Carbons for: ' + xid);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Store mark state
|
||||
message_sel.attr('data-mark', mark_type);
|
||||
|
||||
Console.debug('Markers.handleCarbonChange', 'Received Carbons chat marker (' + mark_type + ') from another resource for: ' + from);
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Markers.handleCarbonChange', e);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles a marked message
|
||||
* @public
|
||||
* @param {string} from
|
||||
* @param {object} message
|
||||
* @param {boolean} is_mam_marker
|
||||
* @return {undefined}
|
||||
*/
|
||||
self.handle = function(from, message, is_mam_marker, 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;
|
||||
|
||||
})();
|
|
@ -18,7 +18,7 @@ var Me = (function () {
|
|||
* @private
|
||||
*/
|
||||
var self = {};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Opens the Me tools
|
||||
|
@ -29,32 +29,32 @@ var Me = (function () {
|
|||
|
||||
try {
|
||||
// Popup HTML content
|
||||
var html =
|
||||
'<div class="top">' + Common._e("Public profile") + '</div>' +
|
||||
|
||||
'<div class="content">' +
|
||||
'<a class="me-images logo" href="https://me.jappix.com/" target="_blank"></a>' +
|
||||
|
||||
'<div class="infos">' +
|
||||
'<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._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>' +
|
||||
'</div>' +
|
||||
|
||||
'<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 class="bottom">' +
|
||||
'<a href="#" class="finish">' + Common._e("Close") + '</a>' +
|
||||
var html =
|
||||
'<div class="top">' + Common._e("Public profile") + '</div>' +
|
||||
|
||||
'<div class="content">' +
|
||||
'<a class="me-images logo" href="https://me.jappix.com/" target="_blank"></a>' +
|
||||
|
||||
'<div class="infos">' +
|
||||
'<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._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>' +
|
||||
'</div>' +
|
||||
|
||||
'<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 class="bottom">' +
|
||||
'<a href="#" class="finish">' + Common._e("Close") + '</a>' +
|
||||
'</div>';
|
||||
|
||||
|
||||
// Create the popup
|
||||
Popup.create('me', html);
|
||||
|
||||
|
||||
// Associate the events
|
||||
self.instance();
|
||||
|
||||
|
||||
Console.log('Public profile tool opened.');
|
||||
} catch(e) {
|
||||
Console.error('Me.open', e);
|
||||
|
@ -73,7 +73,7 @@ var Me = (function () {
|
|||
try {
|
||||
// Destroy the popup
|
||||
Popup.destroy('me');
|
||||
|
||||
|
||||
// We finished
|
||||
Welcome.is_done = false;
|
||||
} catch(e) {
|
||||
|
@ -93,12 +93,14 @@ var Me = (function () {
|
|||
self.instance = function() {
|
||||
|
||||
try {
|
||||
var me_sel = $('#me');
|
||||
|
||||
// Click events
|
||||
$('#me .content a.go').click(function() {
|
||||
me_sel.find('.content a.go').click(function() {
|
||||
self.close();
|
||||
});
|
||||
|
||||
$('#me .bottom .finish').click(self.close);
|
||||
|
||||
me_sel.find('.bottom .finish').click(self.close);
|
||||
} catch(e) {
|
||||
Console.error('Me.instance', e);
|
||||
}
|
||||
|
|
|
@ -31,41 +31,40 @@ var Mobile = (function () {
|
|||
try {
|
||||
// Reset the panels
|
||||
self.resetPanel();
|
||||
|
||||
|
||||
// Get the values
|
||||
var xid = aForm.xid.value;
|
||||
var username, domain;
|
||||
|
||||
|
||||
// A domain is specified
|
||||
if(xid.indexOf('@') != -1) {
|
||||
username = self.getXIDNick(xid);
|
||||
domain = self.getXIDHost(xid);
|
||||
|
||||
|
||||
// Domain is locked and not the same
|
||||
if((LOCK_HOST == 'on') && (domain != HOST_MAIN)) {
|
||||
self.showThis('error');
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// No "@" in the XID, we should add the default domain
|
||||
else {
|
||||
} else {
|
||||
// No "@" in the XID, we should add the default domain
|
||||
username = xid;
|
||||
domain = HOST_MAIN;
|
||||
}
|
||||
|
||||
|
||||
var pwd = aForm.pwd.value;
|
||||
var reg = false;
|
||||
|
||||
if(aForm.reg)
|
||||
|
||||
if(aForm.reg) {
|
||||
reg = aForm.reg.checked;
|
||||
|
||||
}
|
||||
|
||||
// Enough parameters
|
||||
if(username && domain && pwd) {
|
||||
// Show the info notification
|
||||
self.showThis('info');
|
||||
|
||||
|
||||
if(HOST_WEBSOCKET && typeof window.WebSocket != 'undefined') {
|
||||
// WebSocket supported & configured
|
||||
con = new JSJaCWebSocketConnection({
|
||||
|
@ -73,16 +72,16 @@ var Mobile = (function () {
|
|||
});
|
||||
} 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
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// And we handle everything that happen
|
||||
con.registerHandler('message', self.handleMessage);
|
||||
con.registerHandler('presence', self.handlePresence);
|
||||
|
@ -90,7 +89,7 @@ var Mobile = (function () {
|
|||
con.registerHandler('onconnect', self.handleConnected);
|
||||
con.registerHandler('onerror', self.handleError);
|
||||
con.registerHandler('ondisconnect', self.handleDisconnected);
|
||||
|
||||
|
||||
// We retrieve what the user typed in the login inputs
|
||||
oArgs = {};
|
||||
oArgs.username = username;
|
||||
|
@ -104,11 +103,11 @@ var Mobile = (function () {
|
|||
if(reg) {
|
||||
oArgs.register = true;
|
||||
}
|
||||
|
||||
|
||||
// We connect !
|
||||
con.connect(oArgs);
|
||||
}
|
||||
|
||||
|
||||
// Not enough parameters
|
||||
else {
|
||||
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
|
||||
* @public
|
||||
|
@ -195,7 +218,7 @@ var Mobile = (function () {
|
|||
// Hide the opened panels
|
||||
self.hideThis('info');
|
||||
self.hideThis('error');
|
||||
|
||||
|
||||
//Show the target panel
|
||||
if(id) {
|
||||
self.showThis(id);
|
||||
|
@ -217,7 +240,7 @@ var Mobile = (function () {
|
|||
try {
|
||||
// Reset the "secret" input values
|
||||
document.getElementById('pwd').value = '';
|
||||
|
||||
|
||||
// Remove the useless DOM elements
|
||||
var body = document.getElementsByTagName('body')[0];
|
||||
body.removeChild(document.getElementById('talk'));
|
||||
|
@ -296,24 +319,25 @@ var Mobile = (function () {
|
|||
|
||||
try {
|
||||
var type = msg.getType();
|
||||
|
||||
|
||||
if(type == 'chat' || type == 'normal') {
|
||||
// Get the body
|
||||
var body = msg.getBody();
|
||||
|
||||
|
||||
if(body) {
|
||||
// Get the values
|
||||
var xid = self.cutResource(msg.getFrom());
|
||||
var hash = hex_md5(xid);
|
||||
var nick = self.getNick(xid, hash);
|
||||
|
||||
|
||||
// No nickname?
|
||||
if(!nick)
|
||||
if(!nick) {
|
||||
nick = xid;
|
||||
|
||||
}
|
||||
|
||||
// Create the chat if it does not exist
|
||||
self.chat(xid, nick);
|
||||
|
||||
|
||||
// Display the message
|
||||
self.displayMessage(xid, body, nick, hash);
|
||||
}
|
||||
|
@ -339,35 +363,31 @@ var Mobile = (function () {
|
|||
var hash = hex_md5(xid);
|
||||
var type = pre.getType();
|
||||
var show = pre.getShow();
|
||||
|
||||
// Online buddy: show it!
|
||||
|
||||
// Online buddy
|
||||
if(!type) {
|
||||
self.showThis('buddy-' + hash);
|
||||
|
||||
// Display the correct presence
|
||||
switch(show) {
|
||||
case 'chat':
|
||||
self.displayPresence(hash, show);
|
||||
break;
|
||||
|
||||
|
||||
case 'away':
|
||||
self.displayPresence(hash, show);
|
||||
break;
|
||||
|
||||
|
||||
case 'xa':
|
||||
self.displayPresence(hash, show);
|
||||
break;
|
||||
|
||||
|
||||
case 'dnd':
|
||||
self.displayPresence(hash, show);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
self.displayPresence(hash, 'available');
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
self.hideThis('buddy-' + hash);
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Mobile.handlePresence', e);
|
||||
|
@ -391,7 +411,7 @@ var Mobile = (function () {
|
|||
var iqQueryXMLNS = iq.getQueryXMLNS();
|
||||
var iqType = iq.getType();
|
||||
var iqQuery;
|
||||
|
||||
|
||||
// Create the response
|
||||
var iqResponse = new JSJaCIQ();
|
||||
|
||||
|
@ -400,43 +420,43 @@ var Mobile = (function () {
|
|||
iqResponse.setTo(iqFrom);
|
||||
iqResponse.setType('result');
|
||||
}
|
||||
|
||||
|
||||
// Disco#infos query
|
||||
if((iqQueryXMLNS == NS_DISCO_INFO) && (iqType == 'get')) {
|
||||
/* REF: http://xmpp.org/extensions/xep-0030.html */
|
||||
|
||||
|
||||
iqQuery = iqResponse.setQuery(NS_DISCO_INFO);
|
||||
|
||||
|
||||
// We set the name of the client
|
||||
iqQuery.appendChild(iq.appendNode('identity', {
|
||||
'category': 'client',
|
||||
'type': 'mobile',
|
||||
'name': 'Jappix Mobile'
|
||||
}));
|
||||
|
||||
|
||||
// We set all the supported features
|
||||
var fArray = new Array(
|
||||
NS_DISCO_INFO,
|
||||
NS_VERSION
|
||||
);
|
||||
|
||||
|
||||
for(var i in fArray) {
|
||||
iqQuery.appendChild(iq.buildNode('feature', {'var': fArray[i]}));
|
||||
}
|
||||
|
||||
|
||||
con.send(iqResponse);
|
||||
}
|
||||
|
||||
|
||||
// Software version query
|
||||
else if((iqQueryXMLNS == NS_VERSION) && (iqType == 'get')) {
|
||||
/* REF: http://xmpp.org/extensions/xep-0092.html */
|
||||
|
||||
|
||||
iqQuery = iqResponse.setQuery(NS_VERSION);
|
||||
|
||||
|
||||
iqQuery.appendChild(iq.buildNode('name', 'Jappix Mobile'));
|
||||
iqQuery.appendChild(iq.buildNode('version', JAPPIX_VERSION));
|
||||
iqQuery.appendChild(iq.buildNode('os', BrowserDetect.OS));
|
||||
|
||||
|
||||
con.send(iqResponse);
|
||||
}
|
||||
} catch(e) {
|
||||
|
@ -457,27 +477,27 @@ var Mobile = (function () {
|
|||
// Reset the elements
|
||||
self.hideThis('home');
|
||||
self.resetPanel();
|
||||
|
||||
|
||||
// Create the talk page
|
||||
document.getElementsByTagName('body')[0].innerHTML +=
|
||||
'<div id="talk">' +
|
||||
'<div class="header">' +
|
||||
'<div class="mobile-images"></div>' +
|
||||
'<button onclick="Mobile.doLogout();">' + self._e("Disconnect") + '</button>' +
|
||||
'</div>' +
|
||||
|
||||
'<div id="roster"></div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div id="chat">' +
|
||||
'<div class="header">' +
|
||||
'<div class="mobile-images"></div>' +
|
||||
'<button onclick="Mobile.returnToRoster();">' + self._e("Previous") + '</button>' +
|
||||
'</div>' +
|
||||
|
||||
'<div id="chans"></div>' +
|
||||
'<div id="talk">' +
|
||||
'<div class="header">' +
|
||||
'<div class="mobile-images"></div>' +
|
||||
'<button onclick="Mobile.doLogout();">' + self._e("Disconnect") + '</button>' +
|
||||
'</div>' +
|
||||
|
||||
'<div id="roster"></div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div id="chat">' +
|
||||
'<div class="header">' +
|
||||
'<div class="mobile-images"></div>' +
|
||||
'<button onclick="Mobile.returnToRoster();">' + self._e("Previous") + '</button>' +
|
||||
'</div>' +
|
||||
|
||||
'<div id="chans"></div>' +
|
||||
'</div>';
|
||||
|
||||
|
||||
// Get the roster items
|
||||
self.getRoster();
|
||||
} catch(e) {
|
||||
|
@ -514,7 +534,7 @@ var Mobile = (function () {
|
|||
try {
|
||||
// Reset the elements
|
||||
self.resetDOM();
|
||||
|
||||
|
||||
// Show the home page
|
||||
self.showThis('home');
|
||||
} catch(e) {
|
||||
|
@ -536,15 +556,17 @@ var Mobile = (function () {
|
|||
// Error: send presence anyway
|
||||
if(!iq || (iq.getType() != 'result'))
|
||||
return self.sendPresence('', 'available', 1);
|
||||
|
||||
|
||||
// Define some pre-vars
|
||||
var current, xid, nick, oneBuddy, oneID, hash;
|
||||
var current, xid, nick, oneBuddy, oneID, hash, cur_buddy;
|
||||
var roster_buddies = [];
|
||||
|
||||
var roster = document.getElementById('roster');
|
||||
|
||||
|
||||
// Get roster items
|
||||
var iqNode = iq.getNode();
|
||||
var bItems = iqNode.getElementsByTagName('item');
|
||||
|
||||
|
||||
// Display each elements from the roster
|
||||
for(var i = 0; i < bItems.length; i++) {
|
||||
// Get the values
|
||||
|
@ -552,22 +574,34 @@ var Mobile = (function () {
|
|||
xid = current.getAttribute('jid').htmlEnc();
|
||||
nick = current.getAttribute('name');
|
||||
hash = hex_md5(xid);
|
||||
|
||||
|
||||
// No defined nick?
|
||||
if(!nick)
|
||||
if(!nick) {
|
||||
nick = self.getDirectNick(xid);
|
||||
|
||||
// Display the values
|
||||
oneBuddy = document.createElement('a');
|
||||
oneID = 'buddy-' + hash;
|
||||
oneBuddy.setAttribute('href', '#');
|
||||
oneBuddy.setAttribute('id', oneID);
|
||||
oneBuddy.setAttribute('class', 'one-buddy');
|
||||
oneBuddy.setAttribute('onclick', 'return Mobile.chat(\'' + self.encodeOnclick(xid) + '\', \'' + self.encodeOnclick(nick) + '\');');
|
||||
oneBuddy.innerHTML = nick.htmlEnc();
|
||||
roster.appendChild(oneBuddy);
|
||||
}
|
||||
|
||||
roster_buddies.push({
|
||||
'xid': xid,
|
||||
'hash': hash,
|
||||
'nick': nick
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Sort the values
|
||||
self.sortRoster(roster_buddies);
|
||||
|
||||
// Display the values
|
||||
for(var j = 0; j < roster_buddies.length; j++) {
|
||||
cur_buddy = roster_buddies[j];
|
||||
|
||||
self.displayRoster(
|
||||
roster,
|
||||
cur_buddy.xid,
|
||||
cur_buddy.hash,
|
||||
cur_buddy.nick
|
||||
);
|
||||
}
|
||||
|
||||
// Start handling buddies presence
|
||||
self.sendPresence('', 'available', 1);
|
||||
} catch(e) {
|
||||
|
@ -589,7 +623,7 @@ var Mobile = (function () {
|
|||
var body = aForm.body.value;
|
||||
var xid = aForm.xid.value;
|
||||
var hash = hex_md5(xid);
|
||||
|
||||
|
||||
if(body && xid) {
|
||||
// Send the message
|
||||
var aMsg = new JSJaCMessage();
|
||||
|
@ -597,10 +631,10 @@ var Mobile = (function () {
|
|||
aMsg.setType('chat');
|
||||
aMsg.setBody(body);
|
||||
con.send(aMsg);
|
||||
|
||||
|
||||
// Clear our input
|
||||
aForm.body.value = '';
|
||||
|
||||
|
||||
// Display the message we sent
|
||||
self.displayMessage(xid, body, 'me', hash);
|
||||
}
|
||||
|
@ -626,7 +660,7 @@ var Mobile = (function () {
|
|||
|
||||
try {
|
||||
var presence = new JSJaCPresence();
|
||||
|
||||
|
||||
if(type)
|
||||
presence.setType(type);
|
||||
if(show)
|
||||
|
@ -635,7 +669,7 @@ var Mobile = (function () {
|
|||
presence.setPriority(priority);
|
||||
if(status)
|
||||
presence.setStatus(status);
|
||||
|
||||
|
||||
con.send(presence);
|
||||
} catch(e) {
|
||||
Console.error('Mobile.sendPresence', e);
|
||||
|
@ -655,7 +689,7 @@ var Mobile = (function () {
|
|||
iq = new JSJaCIQ();
|
||||
iq.setType('get');
|
||||
iq.setQuery(NS_ROSTER);
|
||||
|
||||
|
||||
con.send(iq, self.handleRoster);
|
||||
} catch(e) {
|
||||
Console.error('Mobile.getRoster', e);
|
||||
|
@ -692,7 +726,7 @@ var Mobile = (function () {
|
|||
|
||||
try {
|
||||
var path = 'buddy-' + hash;
|
||||
|
||||
|
||||
if(self.exists(path)) {
|
||||
return document.getElementById(path).innerHTML;
|
||||
} else {
|
||||
|
@ -718,15 +752,16 @@ var Mobile = (function () {
|
|||
try {
|
||||
// Get the index of our char to explode
|
||||
var index = toStr.indexOf(toEx);
|
||||
|
||||
|
||||
// We split if necessary the string
|
||||
if(index !== -1) {
|
||||
if(i === 0)
|
||||
if(i === 0) {
|
||||
toStr = toStr.substr(0, index);
|
||||
else
|
||||
} else {
|
||||
toStr = toStr.substr(index + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// We return the value
|
||||
return toStr;
|
||||
} catch(e) {
|
||||
|
@ -798,13 +833,13 @@ var Mobile = (function () {
|
|||
try {
|
||||
// Encode in HTML
|
||||
msg = msg.htmlEnc();
|
||||
|
||||
|
||||
// Highlighted text
|
||||
msg = msg.replace(/(\s|^)\*(.+)\*(\s|$)/gi,'$1<em>$2</em>$3');
|
||||
|
||||
|
||||
// Links
|
||||
msg = Links.apply(msg, 'mini');
|
||||
|
||||
|
||||
return msg;
|
||||
} catch(e) {
|
||||
Console.error('Mobile.filter', e);
|
||||
|
@ -827,19 +862,20 @@ var Mobile = (function () {
|
|||
try {
|
||||
// Get the path
|
||||
var path = 'content-' + hash;
|
||||
|
||||
|
||||
// Display the message
|
||||
html = '<span><b';
|
||||
|
||||
if(nick == 'me')
|
||||
|
||||
if(nick == 'me') {
|
||||
html += ' class="me">' + self._e("You");
|
||||
else
|
||||
} else {
|
||||
html += ' class="him">' + nick;
|
||||
|
||||
}
|
||||
|
||||
html += '</b> ' + self.filter(body) + '</span>';
|
||||
|
||||
|
||||
document.getElementById(path).innerHTML += html;
|
||||
|
||||
|
||||
// Scroll to the last element
|
||||
document.getElementById(path).lastChild.scrollIntoView();
|
||||
} 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
|
||||
* @public
|
||||
|
@ -859,7 +950,7 @@ var Mobile = (function () {
|
|||
try {
|
||||
// Hide the chats
|
||||
self.hideThis('chat');
|
||||
|
||||
|
||||
// Show the roster
|
||||
self.showThis('talk');
|
||||
} catch(e) {
|
||||
|
@ -880,15 +971,16 @@ var Mobile = (function () {
|
|||
try {
|
||||
// Hide the roster page
|
||||
self.hideThis('talk');
|
||||
|
||||
|
||||
// Hide the other chats
|
||||
var divs = document.getElementsByTagName('div');
|
||||
|
||||
|
||||
for(var i = 0; i < divs.length; i++) {
|
||||
if(divs.item(i).getAttribute('class') == 'one-chat')
|
||||
if(divs.item(i).getAttribute('class') == 'one-chat') {
|
||||
divs.item(i).style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Show the chat
|
||||
self.showThis('chat');
|
||||
self.showThis(hash);
|
||||
|
@ -913,7 +1005,7 @@ var Mobile = (function () {
|
|||
// Define the variables
|
||||
var chat = document.getElementById('chans');
|
||||
var oneChat = document.createElement('div');
|
||||
|
||||
|
||||
// Apply the DOM modification
|
||||
oneChat.setAttribute('id', 'chat-' + hash);
|
||||
oneChat.setAttribute('class', 'one-chat');
|
||||
|
@ -937,17 +1029,18 @@ var Mobile = (function () {
|
|||
|
||||
try {
|
||||
var hash = hex_md5(xid);
|
||||
|
||||
|
||||
// If the chat was not yet opened
|
||||
if(!self.exists('chat-' + hash)) {
|
||||
// No nick?
|
||||
if(!nick)
|
||||
if(!nick) {
|
||||
nick = self.getNick(xid, hash);
|
||||
|
||||
}
|
||||
|
||||
// Create the chat
|
||||
self.createChat(xid, nick, hash);
|
||||
}
|
||||
|
||||
|
||||
// Switch to the chat
|
||||
self.chatSwitch('chat-' + hash);
|
||||
} catch(e) {
|
||||
|
@ -990,6 +1083,7 @@ var Mobile = (function () {
|
|||
|
||||
try {
|
||||
onbeforeunload = self.doLogout;
|
||||
onload = self.doInitialize;
|
||||
} catch(e) {
|
||||
Console.error('Mobile.launch', e);
|
||||
}
|
||||
|
|
|
@ -31,129 +31,130 @@ var MUCAdmin = (function () {
|
|||
|
||||
try {
|
||||
// Popup HTML content
|
||||
var html_full =
|
||||
'<div class="top">' + Common._e("MUC administration") + '</div>' +
|
||||
|
||||
'<div class="content">' +
|
||||
'<div class="head mucadmin-head">' +
|
||||
'<div class="head-text mucadmin-head-text">' + Common._e("You administrate this room") + '</div>' +
|
||||
|
||||
'<div class="mucadmin-head-jid">' + xid + '</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="mucadmin-forms">' +
|
||||
'<div class="mucadmin-topic">' +
|
||||
'<fieldset>' +
|
||||
'<legend>' + Common._e("Subject") + '</legend>' +
|
||||
|
||||
'<label for="topic-text">' + Common._e("Enter new subject") + '</label>' +
|
||||
'<textarea id="topic-text" name="room-topic" rows="8" cols="60" ></textarea>' +
|
||||
'</fieldset>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="mucadmin-conf">' +
|
||||
'<fieldset>' +
|
||||
'<legend>' + Common._e("Configuration") + '</legend>' +
|
||||
|
||||
'<div class="results mucadmin-results"></div>' +
|
||||
'</fieldset>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="mucadmin-aut">' +
|
||||
'<fieldset>' +
|
||||
'<legend>' + Common._e("Authorizations") + '</legend>' +
|
||||
|
||||
'<label>' + Common._e("Member list") + '</label>' +
|
||||
'<div class="aut-member aut-group">' +
|
||||
'<a href="#" class="aut-add" onclick="return MUCAdmin.addInput(\'\', \'member\');">' + Common._e("Add an input") + '</a>' +
|
||||
'</div>' +
|
||||
|
||||
'<label>' + Common._e("Owner list") + '</label>' +
|
||||
'<div class="aut-owner aut-group">' +
|
||||
'<a href="#" class="aut-add" onclick="return MUCAdmin.addInput(\'\', \'owner\');">' + Common._e("Add an input") + '</a>' +
|
||||
'</div>' +
|
||||
|
||||
'<label>' + Common._e("Administrator list") + '</label>' +
|
||||
'<div class="aut-admin aut-group">' +
|
||||
'<a href="#" class="aut-add" onclick="return MUCAdmin.addInput(\'\', \'admin\');">' + Common._e("Add an input") + '</a>' +
|
||||
'</div>' +
|
||||
|
||||
'<label>' + Common._e("Outcast list") + '</label>' +
|
||||
'<div class="aut-outcast aut-group">' +
|
||||
'<a href="#" class="aut-add" onclick="return MUCAdmin.addInput(\'\', \'outcast\');">' + Common._e("Add an input") + '</a>' +
|
||||
'</div>' +
|
||||
'</fieldset>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="mucadmin-others">' +
|
||||
'<fieldset>' +
|
||||
'<legend>' + Common._e("Others") + '</legend>' +
|
||||
|
||||
'<label>' + Common._e("Destroy this MUC") + '</label>' +
|
||||
'<a href="#" onclick="return MUCAdmin.destroy();">' + Common._e("Yes, let's do it!") + '</a>' +
|
||||
'</fieldset>' +
|
||||
'</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>' +
|
||||
var html_full =
|
||||
'<div class="top">' + Common._e("MUC administration") + '</div>' +
|
||||
|
||||
'<div class="content">' +
|
||||
'<div class="head mucadmin-head">' +
|
||||
'<div class="head-text mucadmin-head-text">' + Common._e("You administrate this room") + '</div>' +
|
||||
|
||||
'<div class="mucadmin-head-jid">' + xid + '</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="mucadmin-forms">' +
|
||||
'<div class="mucadmin-topic">' +
|
||||
'<fieldset>' +
|
||||
'<legend>' + Common._e("Subject") + '</legend>' +
|
||||
|
||||
'<label for="topic-text">' + Common._e("Enter new subject") + '</label>' +
|
||||
'<textarea id="topic-text" name="room-topic" rows="8" cols="60" ></textarea>' +
|
||||
'</fieldset>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="mucadmin-conf">' +
|
||||
'<fieldset>' +
|
||||
'<legend>' + Common._e("Configuration") + '</legend>' +
|
||||
|
||||
'<div class="results mucadmin-results"></div>' +
|
||||
'</fieldset>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="mucadmin-aut">' +
|
||||
'<fieldset>' +
|
||||
'<legend>' + Common._e("Authorizations") + '</legend>' +
|
||||
|
||||
'<label>' + Common._e("Member list") + '</label>' +
|
||||
'<div class="aut-member aut-group">' +
|
||||
'<a href="#" class="aut-add" onclick="return MUCAdmin.addInput(\'\', \'member\');">' + Common._e("Add an input") + '</a>' +
|
||||
'</div>' +
|
||||
|
||||
'<label>' + Common._e("Owner list") + '</label>' +
|
||||
'<div class="aut-owner aut-group">' +
|
||||
'<a href="#" class="aut-add" onclick="return MUCAdmin.addInput(\'\', \'owner\');">' + Common._e("Add an input") + '</a>' +
|
||||
'</div>' +
|
||||
|
||||
'<label>' + Common._e("Administrator list") + '</label>' +
|
||||
'<div class="aut-admin aut-group">' +
|
||||
'<a href="#" class="aut-add" onclick="return MUCAdmin.addInput(\'\', \'admin\');">' + Common._e("Add an input") + '</a>' +
|
||||
'</div>' +
|
||||
|
||||
'<label>' + Common._e("Outcast list") + '</label>' +
|
||||
'<div class="aut-outcast aut-group">' +
|
||||
'<a href="#" class="aut-add" onclick="return MUCAdmin.addInput(\'\', \'outcast\');">' + Common._e("Add an input") + '</a>' +
|
||||
'</div>' +
|
||||
'</fieldset>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="mucadmin-others">' +
|
||||
'<fieldset>' +
|
||||
'<legend>' + Common._e("Others") + '</legend>' +
|
||||
|
||||
'<label>' + Common._e("Destroy this MUC") + '</label>' +
|
||||
'<a href="#" onclick="return MUCAdmin.destroy();">' + Common._e("Yes, let's do it!") + '</a>' +
|
||||
'</fieldset>' +
|
||||
'</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>';
|
||||
|
||||
var html_partial =
|
||||
'<div class="top">' + Common._e("MUC administration") + '</div>' +
|
||||
|
||||
'<div class="content">' +
|
||||
'<div class="head mucadmin-head">' +
|
||||
'<div class="head-text mucadmin-head-text">' + Common._e("You administrate this room") + '</div>' +
|
||||
|
||||
'<div class="mucadmin-head-jid">' + xid + '</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="mucadmin-forms">' +
|
||||
'<div class="mucadmin-aut">' +
|
||||
'<fieldset>' +
|
||||
'<legend>' + Common._e("Authorizations") + '</legend>' +
|
||||
|
||||
'<label>' + Common._e("Member list") + '</label>' +
|
||||
'<div class="aut-member aut-group">' +
|
||||
'<a href="#" class="aut-add" onclick="return MUCAdmin.addInput(\'\', \'member\');">' + Common._e("Add an input") + '</a>' +
|
||||
'</div>' +
|
||||
|
||||
'<label>' + Common._e("Outcast list") + '</label>' +
|
||||
'<div class="aut-outcast aut-group">' +
|
||||
'<a href="#" class="aut-add" onclick="return MUCAdmin.addInput(\'\', \'outcast\');">' + Common._e("Add an input") + '</a>' +
|
||||
'</div>' +
|
||||
'</fieldset>' +
|
||||
'</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>';
|
||||
|
||||
|
||||
var html_partial =
|
||||
'<div class="top">' + Common._e("MUC administration") + '</div>' +
|
||||
|
||||
'<div class="content">' +
|
||||
'<div class="head mucadmin-head">' +
|
||||
'<div class="head-text mucadmin-head-text">' + Common._e("You administrate this room") + '</div>' +
|
||||
|
||||
'<div class="mucadmin-head-jid">' + xid + '</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="mucadmin-forms">' +
|
||||
'<div class="mucadmin-aut">' +
|
||||
'<fieldset>' +
|
||||
'<legend>' + Common._e("Authorizations") + '</legend>' +
|
||||
|
||||
'<label>' + Common._e("Member list") + '</label>' +
|
||||
'<div class="aut-member aut-group">' +
|
||||
'<a href="#" class="aut-add" onclick="return MUCAdmin.addInput(\'\', \'member\');">' + Common._e("Add an input") + '</a>' +
|
||||
'</div>' +
|
||||
|
||||
'<label>' + Common._e("Outcast list") + '</label>' +
|
||||
'<div class="aut-outcast aut-group">' +
|
||||
'<a href="#" class="aut-add" onclick="return MUCAdmin.addInput(\'\', \'outcast\');">' + Common._e("Add an input") + '</a>' +
|
||||
'</div>' +
|
||||
'</fieldset>' +
|
||||
'</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>';
|
||||
|
||||
// Create the popup
|
||||
if(aff == 'owner')
|
||||
Popup.create('mucadmin', html_full);
|
||||
if(aff == 'admin')
|
||||
Popup.create('mucadmin', html_partial);
|
||||
|
||||
|
||||
// Associate the events
|
||||
self.instance();
|
||||
|
||||
|
||||
// We get the affiliated user's privileges
|
||||
if(aff == 'owner') {
|
||||
self.query(xid, 'member');
|
||||
self.query(xid, 'owner');
|
||||
self.query(xid, 'admin');
|
||||
self.query(xid, 'outcast');
|
||||
|
||||
// We query the room to edit
|
||||
DataForm.go(xid, 'muc', '', '', 'mucadmin');
|
||||
} else if(aff == 'admin') {
|
||||
|
@ -196,10 +197,10 @@ var MUCAdmin = (function () {
|
|||
|
||||
try {
|
||||
var path = $(element).parent();
|
||||
|
||||
|
||||
// We first hide the container of the input
|
||||
path.hide();
|
||||
|
||||
|
||||
// Then, we add a special class to the input
|
||||
path.find('input').addClass('aut-dustbin');
|
||||
} catch(e) {
|
||||
|
@ -222,20 +223,20 @@ var MUCAdmin = (function () {
|
|||
|
||||
try {
|
||||
var hash = hex_md5(xid + affiliation);
|
||||
|
||||
|
||||
// Add the HTML code
|
||||
$('#mucadmin .aut-' + affiliation + ' .aut-add').after(
|
||||
'<div class="one-aut ' + hash + '">' +
|
||||
'<input id="aut-' + affiliation + '" name="' + affiliation + '" type="text" class="mucadmin-i" value="' + xid + '" />' +
|
||||
'<a href="#" class="aut-remove">[-]</a>' +
|
||||
'<div class="one-aut ' + hash + '">' +
|
||||
'<input id="aut-' + affiliation + '" name="' + affiliation + '" type="text" class="mucadmin-i" value="' + xid + '" />' +
|
||||
'<a href="#" class="aut-remove">[-]</a>' +
|
||||
'</div>'
|
||||
);
|
||||
|
||||
|
||||
// Click event
|
||||
$('#mucadmin .' + hash + ' .aut-remove').click(function() {
|
||||
return self.removeInput(this);
|
||||
});
|
||||
|
||||
|
||||
// Focus on the input we added
|
||||
if(!xid) {
|
||||
$(document).oneTime(10, function() {
|
||||
|
@ -265,14 +266,14 @@ var MUCAdmin = (function () {
|
|||
// We parse the received xml
|
||||
var xid = $(this).attr('jid');
|
||||
var affiliation = $(this).attr('affiliation');
|
||||
|
||||
|
||||
// We create one input for one XID
|
||||
self.addInput(xid, affiliation);
|
||||
});
|
||||
|
||||
|
||||
// Hide the wait icon
|
||||
$('#mucadmin .wait').hide();
|
||||
|
||||
|
||||
Console.log('MUC admin items received: ' + Common.fullXID(Common.getStanzaFrom(iq)));
|
||||
} catch(e) {
|
||||
Console.error('MUCAdmin.handleAuth', e);
|
||||
|
@ -293,16 +294,16 @@ var MUCAdmin = (function () {
|
|||
try {
|
||||
// Show the wait icon
|
||||
$('#mucadmin .wait').show();
|
||||
|
||||
|
||||
// New IQ
|
||||
var iq = new JSJaCIQ();
|
||||
|
||||
|
||||
iq.setTo(xid);
|
||||
iq.setType('get');
|
||||
|
||||
|
||||
var iqQuery = iq.setQuery(NS_MUC_ADMIN);
|
||||
iqQuery.appendChild(iq.buildNode('item', {'affiliation': type, 'xmlns': NS_MUC_ADMIN}));
|
||||
|
||||
|
||||
con.send(iq, self.handleAuth);
|
||||
} catch(e) {
|
||||
Console.error('MUCAdmin.query', e);
|
||||
|
@ -322,7 +323,7 @@ var MUCAdmin = (function () {
|
|||
try {
|
||||
// We get the new topic
|
||||
var topic = $('.mucadmin-topic textarea').val();
|
||||
|
||||
|
||||
// We send the new topic if not blank
|
||||
if(topic) {
|
||||
var m = new JSJaCMessage();
|
||||
|
@ -330,7 +331,7 @@ var MUCAdmin = (function () {
|
|||
m.setType('groupchat');
|
||||
m.setSubject(topic);
|
||||
con.send(m);
|
||||
|
||||
|
||||
Console.info('MUC admin topic sent: ' + topic);
|
||||
}
|
||||
} catch(e) {
|
||||
|
@ -355,7 +356,7 @@ var MUCAdmin = (function () {
|
|||
$.each(types, function(i) {
|
||||
// We get the current type
|
||||
var tType = types[i];
|
||||
|
||||
|
||||
// We loop for all the elements
|
||||
$('.mucadmin-aut .aut-' + tType + ' input').each(function() {
|
||||
// We get the needed values
|
||||
|
@ -368,7 +369,7 @@ var MUCAdmin = (function () {
|
|||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Console.info('MUC admin authorizations form sent: ' + xid);
|
||||
} catch(e) {
|
||||
Console.error('MUCAdmin.sendAuth', e);
|
||||
|
@ -397,13 +398,13 @@ var MUCAdmin = (function () {
|
|||
iq.setType('set');
|
||||
|
||||
var iqQuery = iq.setQuery(NS_MUC_ADMIN);
|
||||
|
||||
|
||||
var item = iqQuery.appendChild(iq.buildNode('item', {
|
||||
'jid': user_xid,
|
||||
'affiliation': affiliation,
|
||||
'xmlns': NS_MUC_ADMIN
|
||||
}));
|
||||
|
||||
|
||||
con.send(iq, Errors.handleReply);
|
||||
} catch(e) {
|
||||
Console.error('MUCAdmin.setAffiliation', e);
|
||||
|
@ -426,20 +427,21 @@ var MUCAdmin = (function () {
|
|||
var room = Common.fullXID(Common.getStanzaFrom(iq));
|
||||
var hash = hex_md5(room);
|
||||
Interface.quitThisChat(room, hash, 'groupchat');
|
||||
|
||||
|
||||
// We close the muc admin popup
|
||||
self.close();
|
||||
|
||||
|
||||
// We tell the user that all is okay
|
||||
Board.openThisInfo(5);
|
||||
|
||||
|
||||
// We remove the user's favorite
|
||||
if(DataStore.existDB('favorites', room))
|
||||
if(DataStore.existDB(Connection.desktop_hash, 'favorites', room)) {
|
||||
Favorites.removeThis(room, Common.explodeThis('@', room, 0));
|
||||
|
||||
}
|
||||
|
||||
Console.info('MUC admin destroyed: ' + room);
|
||||
}
|
||||
|
||||
|
||||
// We hide the wait icon
|
||||
$('#mucadmin .wait').hide();
|
||||
} catch(e) {
|
||||
|
@ -460,14 +462,14 @@ var MUCAdmin = (function () {
|
|||
try {
|
||||
// We ask the server to delete the room
|
||||
var iq = new JSJaCIQ();
|
||||
|
||||
|
||||
iq.setTo(xid);
|
||||
iq.setType('set');
|
||||
var iqQuery = iq.setQuery(NS_MUC_OWNER);
|
||||
iqQuery.appendChild(iq.buildNode('destroy', {'xmlns': NS_MUC_OWNER}));
|
||||
|
||||
|
||||
con.send(iq, self.handleDestroyIQ);
|
||||
|
||||
|
||||
Console.info('MUC admin destroy sent: ' + xid);
|
||||
} catch(e) {
|
||||
Console.error('MUCAdmin.destroyIQ', e);
|
||||
|
@ -488,10 +490,10 @@ var MUCAdmin = (function () {
|
|||
try {
|
||||
// We get the XID of the current room
|
||||
var xid = $('#mucadmin .mucadmin-head-jid').text();
|
||||
|
||||
|
||||
// We show the wait icon
|
||||
$('#mucadmin .wait').show();
|
||||
|
||||
|
||||
// We send the iq
|
||||
self.destroyIQ(xid);
|
||||
} catch(e) {
|
||||
|
@ -511,10 +513,10 @@ var MUCAdmin = (function () {
|
|||
try {
|
||||
// We get the XID of the current room
|
||||
var xid = $('#mucadmin .mucadmin-head-jid').text();
|
||||
|
||||
|
||||
// We change the room topic
|
||||
self.sendTopic(xid);
|
||||
|
||||
|
||||
// We send the needed queries
|
||||
DataForm.send('x', 'submit', 'submit', $('#mucadmin .mucadmin-results').attr('data-session'), xid, '', '', 'mucadmin');
|
||||
self.sendAuth(xid);
|
||||
|
@ -535,7 +537,7 @@ var MUCAdmin = (function () {
|
|||
try {
|
||||
// We send the new options
|
||||
self.send();
|
||||
|
||||
|
||||
// And we quit the popup
|
||||
return self.close();
|
||||
} catch(e) {
|
||||
|
@ -555,10 +557,13 @@ var MUCAdmin = (function () {
|
|||
try {
|
||||
// Click events
|
||||
$('#mucadmin .bottom .finish').click(function() {
|
||||
if($(this).is('.cancel'))
|
||||
if($(this).is('.cancel')) {
|
||||
return self.close();
|
||||
if($(this).is('.save'))
|
||||
}
|
||||
|
||||
if($(this).is('.save')) {
|
||||
return self.save();
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('MUCAdmin.instance', e);
|
||||
|
|
1845
source/app/javascripts/muji.js
Normal file
|
@ -29,10 +29,10 @@ var Music = (function () {
|
|||
|
||||
try {
|
||||
var path = '.music-content';
|
||||
|
||||
|
||||
// Show the music bubble
|
||||
Bubble.show(path);
|
||||
|
||||
|
||||
$(document).oneTime(10, function() {
|
||||
$(path + ' input').focus();
|
||||
});
|
||||
|
@ -58,71 +58,70 @@ var Music = (function () {
|
|||
var path = '.music-content ';
|
||||
var content = path + '.list';
|
||||
var path_type = content + ' .' + type;
|
||||
|
||||
|
||||
// Create the result container
|
||||
if(!Common.exists(path_type)) {
|
||||
var code = '<div class="' + type + '"></div>';
|
||||
|
||||
if(type == 'local')
|
||||
|
||||
if(type == 'local') {
|
||||
$(content).prepend(code);
|
||||
else
|
||||
} else {
|
||||
$(content).append(code);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Fill the results
|
||||
$(xml).find('track').each(function() {
|
||||
// Parse the XML
|
||||
var id = $(this).find('id').text();
|
||||
var title = $(this).find('name').text();
|
||||
var artist = $(this).find('artist').text();
|
||||
var source = $(this).find('source').text();
|
||||
var duration = $(this).find('duration').text();
|
||||
var uri = $(this).find('url').text();
|
||||
var mime = $(this).find('type').text();
|
||||
|
||||
// No ID?
|
||||
if(!id)
|
||||
id = hex_md5(uri);
|
||||
|
||||
// No MIME?
|
||||
if(!mime)
|
||||
mime = 'audio/ogg';
|
||||
|
||||
var this_sel = $(this);
|
||||
|
||||
var id = this_sel.find('id').text() || hex_md5(uri);
|
||||
var title = this_sel.find('name').text();
|
||||
var artist = this_sel.find('artist').text();
|
||||
var source = this_sel.find('source').text();
|
||||
var duration = this_sel.find('duration').text();
|
||||
var uri = this_sel.find('url').text();
|
||||
var mime = this_sel.find('type').text() || 'audio/ogg';
|
||||
|
||||
// Local URL?
|
||||
if(type == 'local')
|
||||
if(type == 'local') {
|
||||
uri = Utils.generateURL(uri);
|
||||
|
||||
}
|
||||
|
||||
// Append the HTML code
|
||||
$(path_type).append('<a href="#" class="song" data-id="' + id + '">' + title + '</a>');
|
||||
|
||||
|
||||
// Current playing song?
|
||||
var current_song = $(path_type + ' a[data-id="' + id + '"]');
|
||||
|
||||
if(Common.exists('.music-audio[data-id="' + id + '"]'))
|
||||
|
||||
if(Common.exists('.music-audio[data-id="' + id + '"]')) {
|
||||
current_song.addClass('playing');
|
||||
|
||||
}
|
||||
|
||||
// Click event
|
||||
current_song.click(function() {
|
||||
return self.add(id, title, artist, source, duration, uri, mime, type);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// The search is finished
|
||||
if(Common.exists(content + ' .jamendo') && Common.exists(content + ' .local')) {
|
||||
// Get the result values
|
||||
var jamendo = $(content + ' .jamendo').text();
|
||||
var local = $(content + ' .local').text();
|
||||
|
||||
|
||||
// Enable the input
|
||||
$(path + 'input').val('').removeAttr('disabled');
|
||||
|
||||
|
||||
// No result
|
||||
if(!jamendo && !local)
|
||||
if(!jamendo && !local) {
|
||||
$(path + '.no-results').show();
|
||||
|
||||
}
|
||||
|
||||
// We must put a separator between the categories
|
||||
if(jamendo && local)
|
||||
if(jamendo && local) {
|
||||
$(content + ' .local').addClass('special');
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Music.parse', e);
|
||||
|
@ -140,24 +139,27 @@ var Music = (function () {
|
|||
|
||||
try {
|
||||
var path = '.music-content ';
|
||||
|
||||
|
||||
// We get the input string
|
||||
var string = $(path + 'input').val();
|
||||
|
||||
|
||||
// We lock the search input
|
||||
$(path + 'input').attr('disabled', true);
|
||||
|
||||
|
||||
// We reset the results
|
||||
$(path + '.list div').remove();
|
||||
$(path + '.no-results').hide();
|
||||
|
||||
|
||||
// Get the Jamendo results
|
||||
$.get('./server/music-search.php', {searchquery: string, location: 'jamendo'}, function(data) {
|
||||
self.parse(data, 'jamendo');
|
||||
});
|
||||
|
||||
|
||||
// Get the local results
|
||||
$.get('./server/music-search.php', {searchquery: string, location: JAPPIX_LOCATION}, function(data) {
|
||||
$.get('./server/music-search.php', {
|
||||
searchquery: string,
|
||||
location: JAPPIX_LOCATION
|
||||
}, function(data) {
|
||||
self.parse(data, 'local');
|
||||
});
|
||||
} catch(e) {
|
||||
|
@ -177,35 +179,37 @@ var Music = (function () {
|
|||
|
||||
try {
|
||||
// Initialize
|
||||
var playThis = document.getElementById('top-content').getElementsByTagName('audio')[0];
|
||||
|
||||
var audio_sel = document.getElementById('top-content').getElementsByTagName('audio')[0];
|
||||
|
||||
// Nothing to play, exit
|
||||
if(!playThis)
|
||||
if(!audio_sel) {
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
var stopButton = $('#top-content a.stop');
|
||||
|
||||
|
||||
// User play a song
|
||||
if(action == 'play') {
|
||||
stopButton.show();
|
||||
playThis.load();
|
||||
playThis.play();
|
||||
playThis.addEventListener('ended', function() {
|
||||
audio_sel.load();
|
||||
audio_sel.play();
|
||||
|
||||
audio_sel.addEventListener('ended', function() {
|
||||
self.action('stop');
|
||||
}, true);
|
||||
|
||||
}, true);
|
||||
|
||||
Console.log('Music is now playing.');
|
||||
}
|
||||
|
||||
// User stop the song or the song came to its end
|
||||
else if(action == 'stop') {
|
||||
} else if(action == 'stop') {
|
||||
// User stop the song / end of song
|
||||
stopButton.hide();
|
||||
playThis.pause();
|
||||
audio_sel.pause();
|
||||
|
||||
$('#top-content .music').removeClass('actived');
|
||||
$('.music-content .list a').removeClass('playing');
|
||||
$('.music-audio').remove();
|
||||
|
||||
self.publish();
|
||||
|
||||
|
||||
Console.log('Music is now stopped.');
|
||||
}
|
||||
} catch(e) {
|
||||
|
@ -236,42 +240,39 @@ var Music = (function () {
|
|||
if(Features.enabledPEP()) {
|
||||
var iq = new JSJaCIQ();
|
||||
iq.setType('set');
|
||||
|
||||
|
||||
// Create the main PubSub nodes
|
||||
var pubsub = iq.appendNode('pubsub', {'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 tune = item.appendChild(iq.buildNode('tune', {'xmlns': NS_TUNE}));
|
||||
|
||||
|
||||
// Enough data?
|
||||
if(title || artist || source || uri) {
|
||||
// Data array
|
||||
var nodes = new Array(
|
||||
'title',
|
||||
'artist',
|
||||
'source',
|
||||
'length',
|
||||
'uri'
|
||||
);
|
||||
|
||||
var values = new Array(
|
||||
title,
|
||||
artist,
|
||||
source,
|
||||
length,
|
||||
uri
|
||||
);
|
||||
|
||||
var music_data = {
|
||||
'title': title,
|
||||
'artist': artist,
|
||||
'source': source,
|
||||
'length': length,
|
||||
'uri': uri
|
||||
};
|
||||
|
||||
// Create the children nodes
|
||||
for(var i in nodes) {
|
||||
if(values[i]) {
|
||||
tune.appendChild(iq.buildNode(nodes[i], {'xmlns': NS_TUNE}, values[i]));
|
||||
var cur_value;
|
||||
|
||||
for(var cur_name in music_data) {
|
||||
cur_value = music_data[cur_name];
|
||||
|
||||
if(cur_value) {
|
||||
tune.appendChild(iq.buildNode(cur_name, {
|
||||
'xmlns': NS_TUNE
|
||||
}, cur_value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
con.send(iq);
|
||||
|
||||
|
||||
Console.info('New tune sent: ' + title);
|
||||
}
|
||||
} catch(e) {
|
||||
|
@ -298,27 +299,29 @@ var Music = (function () {
|
|||
|
||||
try {
|
||||
var path = '.music-content ';
|
||||
|
||||
var music_audio_sel = $('.music-audio');
|
||||
|
||||
// We remove & create a new audio tag
|
||||
$('.music-audio').remove();
|
||||
music_audio_sel.remove();
|
||||
$(path + '.player').prepend('<audio class="music-audio" type="' + mime + '" data-id="' + id + '" />');
|
||||
|
||||
|
||||
// We apply the new source to the player
|
||||
if(type == 'jamendo')
|
||||
$('.music-audio').attr('src', 'http://api.jamendo.com/get2/stream/track/redirect/?id=' + id + '&streamencoding=ogg2');
|
||||
else
|
||||
$('.music-audio').attr('src', uri);
|
||||
|
||||
if(type == 'jamendo') {
|
||||
music_audio_sel.attr('src', 'http://api.jamendo.com/get2/stream/track/redirect/?id=' + id + '&streamencoding=ogg2');
|
||||
} else {
|
||||
music_audio_sel.attr('src', uri);
|
||||
}
|
||||
|
||||
// We play the target sound
|
||||
self.action('play');
|
||||
|
||||
|
||||
// We set the actived class
|
||||
$('#top-content .music').addClass('actived');
|
||||
|
||||
|
||||
// We set a current played track indicator
|
||||
$(path + '.list a').removeClass('playing');
|
||||
$(path + 'a[data-id="' + id + '"]').addClass('playing');
|
||||
|
||||
|
||||
// We publish what we listen
|
||||
self.publish(title, artist, source, duration, uri);
|
||||
} catch(e) {
|
||||
|
@ -345,7 +348,7 @@ var Music = (function () {
|
|||
if(e.keyCode == 13 && $(this).val()) {
|
||||
self.search();
|
||||
}
|
||||
|
||||
|
||||
// Escape : quit
|
||||
if(e.keyCode == 27) {
|
||||
Bubble.close();
|
||||
|
|
|
@ -32,9 +32,9 @@ var Name = (function () {
|
|||
var iq = new JSJaCIQ();
|
||||
iq.setType('get');
|
||||
iq.setTo(xid);
|
||||
|
||||
|
||||
iq.appendNode('vCard', {'xmlns': NS_VCARD});
|
||||
|
||||
|
||||
con.send(iq, self.handleAddUser);
|
||||
} catch(e) {
|
||||
Console.error('Name.getAddUser', e);
|
||||
|
@ -53,18 +53,20 @@ var Name = (function () {
|
|||
|
||||
try {
|
||||
// Was it an obsolete request?
|
||||
if(!Common.exists('.add-contact-name-get[data-for="' + escape(Common.bareXID(Common.getStanzaFrom(iq))) + '"]'))
|
||||
if(!Common.exists('.add-contact-name-get[data-for="' + escape(Common.bareXID(Common.getStanzaFrom(iq))) + '"]')) {
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
// Reset the waiting item
|
||||
$('.add-contact-name-get').hide().removeAttr('data-for');
|
||||
|
||||
|
||||
// Get the names
|
||||
if(iq.getType() == 'result') {
|
||||
var full_name = self.generateBuddy(iq)[0];
|
||||
|
||||
if(full_name)
|
||||
|
||||
if(full_name) {
|
||||
$('.add-contact-name').val(full_name);
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Name.handleAddUser', e);
|
||||
|
@ -85,29 +87,30 @@ var Name = (function () {
|
|||
|
||||
try {
|
||||
// Get the IQ content
|
||||
var xml = $(iq.getNode()).find('vCard');
|
||||
|
||||
var vcard_sel = $(iq.getNode()).find('vCard');
|
||||
|
||||
// Get the full name & the nickname
|
||||
var pFull = xml.find('FN:first').text();
|
||||
var pNick = xml.find('NICKNAME:first').text();
|
||||
|
||||
var pFull = vcard_sel.find('FN:first').text();
|
||||
var pNick = vcard_sel.find('NICKNAME:first').text();
|
||||
|
||||
// No full name?
|
||||
if(!pFull) {
|
||||
// Get the given name
|
||||
var pN = xml.find('N:first');
|
||||
var pN = vcard_sel.find('N:first');
|
||||
var pGiven = pN.find('GIVEN:first').text();
|
||||
|
||||
|
||||
if(pGiven) {
|
||||
pFull = pGiven;
|
||||
|
||||
|
||||
// Get the family name (optional)
|
||||
var pFamily = pN.find('FAMILY:first').text();
|
||||
|
||||
if(pFamily)
|
||||
|
||||
if(pFamily) {
|
||||
pFull += ' ' + pFamily;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return [pFull, pNick];
|
||||
} catch(e) {
|
||||
Console.error('Name.generateBuddy', e);
|
||||
|
@ -127,29 +130,29 @@ var Name = (function () {
|
|||
try {
|
||||
// Initialize
|
||||
var cname, bname;
|
||||
|
||||
|
||||
// Cut the XID resource
|
||||
xid = Common.bareXID(xid);
|
||||
|
||||
|
||||
// This is me?
|
||||
if(Utils.isAnonymous() && !xid)
|
||||
if(Utils.isAnonymous() && !xid) {
|
||||
bname = Common._e("You");
|
||||
else if(xid == Common.getXID())
|
||||
} else if(xid == Common.getXID()) {
|
||||
bname = self.get();
|
||||
|
||||
}
|
||||
|
||||
// Not me!
|
||||
else {
|
||||
cname = $('#roster .buddy[data-xid="' + escape(xid) + '"]:first .buddy-name').html();
|
||||
|
||||
// If the complete name exists
|
||||
if(cname)
|
||||
|
||||
// Complete name exists?
|
||||
if(cname) {
|
||||
bname = cname.revertHtmlEnc();
|
||||
|
||||
// Else, we just get the nickname of the buddy
|
||||
else
|
||||
} else {
|
||||
bname = Common.getXIDNick(xid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return bname;
|
||||
} catch(e) {
|
||||
Console.error('Name.getBuddy', e);
|
||||
|
@ -168,11 +171,12 @@ var Name = (function () {
|
|||
try {
|
||||
// Try to read the user nickname
|
||||
var nick = DataStore.getDB(Connection.desktop_hash, 'profile', 'nick');
|
||||
|
||||
|
||||
// No nick?
|
||||
if(!nick)
|
||||
if(!nick) {
|
||||
nick = con.username;
|
||||
|
||||
}
|
||||
|
||||
return nick;
|
||||
} catch(e) {
|
||||
Console.error('Name.getNick', e);
|
||||
|
@ -191,11 +195,12 @@ var Name = (function () {
|
|||
try {
|
||||
// Try to read the user name
|
||||
var name = DataStore.getDB(Connection.desktop_hash, 'profile', 'name');
|
||||
|
||||
// No name? Use the nickname instead!
|
||||
if(!name)
|
||||
|
||||
// No name? Use the nickname instead
|
||||
if(!name) {
|
||||
name = self.getNick();
|
||||
|
||||
}
|
||||
|
||||
return name;
|
||||
} catch(e) {
|
||||
Console.error('Name.get', e);
|
||||
|
|
|
@ -50,29 +50,26 @@ var Notification = (function () {
|
|||
var notif = '#top-content .notifications';
|
||||
var nothing = '.notifications-content .nothing';
|
||||
var empty = '.notifications-content .empty';
|
||||
|
||||
|
||||
// Get the notifications number
|
||||
var number = $('.one-notification').size();
|
||||
|
||||
|
||||
// Remove the red notify bubble
|
||||
$(notif + ' .notify').remove();
|
||||
|
||||
|
||||
// Any notification?
|
||||
if(number) {
|
||||
$(notif).prepend('<div class="notify one-counter" data-counter="' + number + '">' + number + '</div>');
|
||||
$(nothing).hide();
|
||||
$(empty).show();
|
||||
}
|
||||
|
||||
// No notification!
|
||||
else {
|
||||
} else {
|
||||
$(empty).hide();
|
||||
$(nothing).show();
|
||||
|
||||
|
||||
// Purge the social inbox node
|
||||
self.purge();
|
||||
}
|
||||
|
||||
|
||||
// Update the page title
|
||||
Interface.updateTitle();
|
||||
} catch(e) {
|
||||
|
@ -96,142 +93,144 @@ var Notification = (function () {
|
|||
self.create = function(type, from, data, body, id, inverse) {
|
||||
|
||||
try {
|
||||
if(!type || !from)
|
||||
if(!type || !from) {
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// Generate an ID hash
|
||||
if(!id) {
|
||||
id = hex_md5(type + from);
|
||||
}
|
||||
|
||||
|
||||
// Generate the text to be displayed
|
||||
var text, action, code;
|
||||
var yes_path = 'href="#"';
|
||||
|
||||
|
||||
// User things
|
||||
from = Common.bareXID(from);
|
||||
var hash = hex_md5(from);
|
||||
|
||||
|
||||
switch(type) {
|
||||
case 'subscribe':
|
||||
// Get the name to display
|
||||
var display_name = data[1];
|
||||
|
||||
|
||||
if(!display_name)
|
||||
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?");
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
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?");
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case 'request':
|
||||
text = '<b>' + from.htmlEnc() + '</b> ' + Common._e("would like to get authorization.") + ' ' + Common._e("Do you accept?");
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case 'send':
|
||||
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?");
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
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>');
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
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>');
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
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>');
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
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>');
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case 'rosterx':
|
||||
text = Common.printf(Common._e("Do you want to see the friends %s suggests you?").htmlEnc(), '<b>' + Name.getBuddy(from).htmlEnc() + '</b>');
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
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>');
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case 'like':
|
||||
text = '<b>' + data[0].htmlEnc() + '</b> ' + Common.printf(Common._e("liked your post: “%s”.").htmlEnc(), '<em>' + Utils.truncate(body, 25).htmlEnc() + '</em>');
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case 'quote':
|
||||
text = '<b>' + data[0].htmlEnc() + '</b> ' + Common.printf(Common._e("quoted you somewhere: “%s”.").htmlEnc(), '<em>' + Utils.truncate(body, 25).htmlEnc() + '</em>');
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
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>');
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
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>');
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
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>');
|
||||
|
||||
|
||||
break;
|
||||
|
||||
case 'me_profile_new_success':
|
||||
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();
|
||||
|
||||
|
||||
break;
|
||||
|
||||
case 'me_profile_remove_success':
|
||||
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();
|
||||
|
||||
|
||||
break;
|
||||
|
||||
case 'me_profile_update_success':
|
||||
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();
|
||||
|
||||
|
||||
break;
|
||||
|
||||
case 'me_profile_check_error':
|
||||
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();
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// No text?
|
||||
if(!text)
|
||||
if(!text) {
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// Action links?
|
||||
switch(type) {
|
||||
// Hide/Show actions
|
||||
|
@ -248,8 +247,9 @@ var Notification = (function () {
|
|||
action = '<a href="#" class="no">' + Common._e("Hide") + '</a>';
|
||||
|
||||
// Any parent link?
|
||||
if((type == 'comment') && data[2])
|
||||
if((type == 'comment') && data[2]) {
|
||||
action = '<a href="#" class="yes">' + Common._e("Show") + '</a>' + action;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
@ -266,53 +266,55 @@ var Notification = (function () {
|
|||
default:
|
||||
action = '<a ' + yes_path + ' class="yes">' + Common._e("Yes") + '</a><a href="#" class="no">' + Common._e("No") + '</a>';
|
||||
}
|
||||
|
||||
|
||||
if(text) {
|
||||
// We display the notification
|
||||
if(!Common.exists('.notifications-content .' + id)) {
|
||||
// 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) + '">' +
|
||||
'<div class="avatar-container">' +
|
||||
'<img class="avatar" src="' + './images/others/default-avatar.png' + '" alt="" />' +
|
||||
'</div>' +
|
||||
|
||||
'<p class="notification-text">' + text + '</p>' +
|
||||
'<p class="notification-actions">' +
|
||||
'<span class="talk-images" />' +
|
||||
action +
|
||||
'</p>' +
|
||||
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">' +
|
||||
'<img class="avatar" src="' + './images/others/default-avatar.png' + '" alt="" />' +
|
||||
'</div>' +
|
||||
|
||||
'<p class="notification-text">' + text + '</p>' +
|
||||
'<p class="notification-actions">' +
|
||||
'<span class="talk-images" />' +
|
||||
action +
|
||||
'</p>' +
|
||||
'</div>';
|
||||
|
||||
|
||||
// Add the HTML code
|
||||
if(inverse)
|
||||
if(inverse) {
|
||||
$('.notifications-content .nothing').before(code);
|
||||
else
|
||||
} else {
|
||||
$('.notifications-content .empty').after(code);
|
||||
|
||||
}
|
||||
|
||||
// Play a sound to alert the user
|
||||
Audio.play('notification');
|
||||
|
||||
|
||||
// The yes click function
|
||||
$('.' + id + ' a.yes').click(function() {
|
||||
self.action(type, data, 'yes', id);
|
||||
|
||||
if(($(this).attr('href') == '#') && ($(this).attr('target') != '_blank'))
|
||||
|
||||
if(($(this).attr('href') == '#') && ($(this).attr('target') != '_blank')) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// The no click function
|
||||
$('.' + id + ' a.no').click(function() {
|
||||
return self.action(type, data, 'no', id);
|
||||
});
|
||||
|
||||
|
||||
// Get the user avatar
|
||||
Avatar.get(from, 'cache', 'true', 'forget');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// We tell the user he has a new pending notification
|
||||
self.check();
|
||||
|
||||
|
||||
Console.info('New notification: ' + from);
|
||||
} catch(e) {
|
||||
Console.error('Notification.new', e);
|
||||
|
@ -334,42 +336,37 @@ var Notification = (function () {
|
|||
|
||||
try {
|
||||
// We launch a function depending of the type
|
||||
if((type == 'subscribe') && (value == 'yes'))
|
||||
if((type == 'subscribe') && (value == 'yes')) {
|
||||
Presence.acceptSubscribe(data[0], data[1]);
|
||||
|
||||
else if((type == 'subscribe') && (value == 'no'))
|
||||
} else if((type == 'subscribe') && (value == 'no')) {
|
||||
Presence.sendSubscribe(data[0], 'unsubscribed');
|
||||
|
||||
else if((type == 'invite_room') && (value == 'yes'))
|
||||
} else if((type == 'invite_room') && (value == 'yes')) {
|
||||
Chat.checkCreate(data[0], 'groupchat');
|
||||
|
||||
else if(type == 'request')
|
||||
} else if(type == 'request') {
|
||||
HTTPReply.go(value, data[0]);
|
||||
|
||||
if((type == 'send') && (value == 'yes'))
|
||||
}
|
||||
|
||||
if((type == 'send') && (value == 'yes')) {
|
||||
OOB.reply(data[0], data[3], 'accept', data[2], data[4]);
|
||||
|
||||
else if((type == 'send') && (value == 'no'))
|
||||
} else if((type == 'send') && (value == 'no')) {
|
||||
OOB.reply(data[0], data[3], 'reject', data[2], data[4]);
|
||||
|
||||
else if((type == 'rosterx') && (value == 'yes'))
|
||||
} else if((type == 'rosterx') && (value == 'yes')) {
|
||||
RosterX.open(data[0]);
|
||||
|
||||
else if((type == 'comment') || (type == 'like') || (type == 'quote') || (type == 'wall') || (type == 'photo') || (type == 'video')) {
|
||||
} else if((type == 'comment') || (type == 'like') || (type == 'quote') || (type == 'wall') || (type == 'photo') || (type == 'video')) {
|
||||
if(value == 'yes') {
|
||||
// Get the microblog item
|
||||
Microblog.fromInfos(data[2]);
|
||||
|
||||
|
||||
// Append the marker
|
||||
$('#channel .top.individual').append('<input type="hidden" name="comments" value="' + Common.encodeQuotes(data[1]) + '" />');
|
||||
}
|
||||
|
||||
|
||||
self.remove(data[3]);
|
||||
}
|
||||
|
||||
|
||||
// We remove the notification
|
||||
$('.notifications-content .' + id).remove();
|
||||
|
||||
|
||||
// We check if there's any other pending notification
|
||||
self.closeEmpty();
|
||||
self.check();
|
||||
|
@ -392,7 +389,7 @@ var Notification = (function () {
|
|||
try {
|
||||
// Remove notifications
|
||||
$('.one-notification').remove();
|
||||
|
||||
|
||||
// Refresh
|
||||
self.closeEmpty();
|
||||
self.check();
|
||||
|
@ -415,12 +412,12 @@ var Notification = (function () {
|
|||
try {
|
||||
var iq = new JSJaCIQ();
|
||||
iq.setType('get');
|
||||
|
||||
|
||||
var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB});
|
||||
pubsub.appendChild(iq.buildNode('items', {'node': NS_URN_INBOX, 'xmlns': NS_PUBSUB}));
|
||||
|
||||
|
||||
con.send(iq, self.handle);
|
||||
|
||||
|
||||
Console.log('Getting social notifications...');
|
||||
} catch(e) {
|
||||
Console.error('Notification.get', e);
|
||||
|
@ -442,40 +439,44 @@ var Notification = (function () {
|
|||
if((stanza.getType() == 'error') && $(stanza.getNode()).find('item-not-found').size()) {
|
||||
// The node may not exist, create it!
|
||||
Pubsub.setup('', NS_URN_INBOX, '1', '1000000', 'whitelist', 'open', true);
|
||||
|
||||
|
||||
Console.warn('Error while getting social notifications, trying to reconfigure the Pubsub node!');
|
||||
}
|
||||
|
||||
|
||||
// Selector
|
||||
var items = $(stanza.getNode()).find('item');
|
||||
|
||||
|
||||
// Should we inverse?
|
||||
var inverse = true;
|
||||
|
||||
if(items.size() == 1)
|
||||
|
||||
if(items.size() == 1) {
|
||||
inverse = false;
|
||||
|
||||
}
|
||||
|
||||
// Parse notifications
|
||||
items.each(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// Parse the current item
|
||||
var current_item = $(this).attr('id');
|
||||
var current_type = $(this).find('link[rel="via"]:first').attr('title');
|
||||
var current_href = $(this).find('link[rel="via"]:first').attr('href');
|
||||
var current_parent_href = $(this).find('link[rel="related"]:first').attr('href');
|
||||
var current_xid = Common.explodeThis(':', $(this).find('author uri').text(), 1);
|
||||
var current_name = $(this).find('author name').text();
|
||||
var current_text = $(this).find('content[type="text"]:first').text();
|
||||
var current_item = this_sel.attr('id');
|
||||
var current_type = this_sel.find('link[rel="via"]:first').attr('title');
|
||||
var current_href = this_sel.find('link[rel="via"]:first').attr('href');
|
||||
var current_parent_href = this_sel.find('link[rel="related"]:first').attr('href');
|
||||
var current_xid = Common.explodeThis(':', this_sel.find('author uri').text(), 1);
|
||||
var current_name = this_sel.find('author name').text();
|
||||
var current_text = this_sel.find('content[type="text"]:first').text();
|
||||
var current_bname = Name.getBuddy(current_xid);
|
||||
var current_id = hex_md5(current_type + current_xid + current_href + current_text);
|
||||
|
||||
|
||||
// Choose the good name!
|
||||
if(!current_name || (current_bname != Common.getXIDNick(current_xid)))
|
||||
if(!current_name || (current_bname != Common.getXIDNick(current_xid))) {
|
||||
current_name = current_bname;
|
||||
|
||||
}
|
||||
|
||||
// Create it!
|
||||
self.create(current_type, current_xid, [current_name, current_href, current_parent_href, current_item], current_text, current_id, inverse);
|
||||
});
|
||||
|
||||
|
||||
Console.info(items.size() + ' social notification(s) got!');
|
||||
} catch(e) {
|
||||
Console.error('Notification.handle', e);
|
||||
|
@ -499,38 +500,38 @@ var Notification = (function () {
|
|||
try {
|
||||
// Notification ID
|
||||
var id = hex_md5(xid + text + DateUtils.getTimeStamp());
|
||||
|
||||
|
||||
// IQ
|
||||
var iq = new JSJaCIQ();
|
||||
iq.setType('set');
|
||||
iq.setTo(xid);
|
||||
|
||||
|
||||
// ATOM content
|
||||
var pubsub = iq.appendNode('pubsub', {'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 entry = item.appendChild(iq.buildNode('entry', {'xmlns': NS_ATOM}));
|
||||
|
||||
|
||||
// Notification author (us)
|
||||
var author = entry.appendChild(iq.buildNode('author', {'xmlns': NS_ATOM}));
|
||||
author.appendChild(iq.buildNode('name', {'xmlns': NS_ATOM}, Name.get()));
|
||||
author.appendChild(iq.buildNode('uri', {'xmlns': NS_ATOM}, 'xmpp:' + Common.getXID()));
|
||||
|
||||
|
||||
// Notification content
|
||||
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('link', {'rel': 'via', 'title': type, 'href': href, 'xmlns': NS_ATOM}));
|
||||
|
||||
|
||||
// Any parent item?
|
||||
if(parent && parent[0] && parent[1] && parent[2]) {
|
||||
// Generate the parent XMPP URI
|
||||
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}));
|
||||
}
|
||||
|
||||
|
||||
con.send(iq);
|
||||
|
||||
|
||||
Console.log('Sending a social notification to ' + xid + ' (type: ' + type + ')...');
|
||||
} catch(e) {
|
||||
Console.error('Notification.send', e);
|
||||
|
@ -550,11 +551,11 @@ var Notification = (function () {
|
|||
try {
|
||||
var iq = new JSJaCIQ();
|
||||
iq.setType('set');
|
||||
|
||||
|
||||
var pubsub = iq.appendNode('pubsub', {'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}));
|
||||
|
||||
|
||||
con.send(iq);
|
||||
} catch(e) {
|
||||
Console.error('Notification.remove', e);
|
||||
|
@ -574,10 +575,10 @@ var Notification = (function () {
|
|||
try {
|
||||
var iq = new JSJaCIQ();
|
||||
iq.setType('set');
|
||||
|
||||
|
||||
var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB_OWNER});
|
||||
pubsub.appendChild(iq.buildNode('purge', {'node': NS_URN_INBOX, 'xmlns': NS_PUBSUB_OWNER}));
|
||||
|
||||
|
||||
con.send(iq);
|
||||
} catch(e) {
|
||||
Console.error('Notification.purge', e);
|
||||
|
@ -598,12 +599,12 @@ var Notification = (function () {
|
|||
try {
|
||||
// Process the new height
|
||||
var max_height = $('#right-content').height() - 22;
|
||||
|
||||
|
||||
// New height too small
|
||||
if(max_height < 250) {
|
||||
max_height = 250;
|
||||
}
|
||||
|
||||
|
||||
// Apply the new height
|
||||
$('.notifications-content .tools-content-subitem').css('max-height', max_height);
|
||||
} catch(e) {
|
||||
|
|
|
@ -37,41 +37,42 @@ var OOB = (function () {
|
|||
// Get some values
|
||||
var id = hex_md5(genID() + to + url + desc);
|
||||
to = Caps.getFeatureResource(to, NS_IQOOB);
|
||||
|
||||
|
||||
// IQs cannot be sent to offline users
|
||||
if(!to)
|
||||
if(!to) {
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// Register the ID
|
||||
DataStore.setDB(Connection.desktop_hash, 'send/url', id, url);
|
||||
DataStore.setDB(Connection.desktop_hash, 'send/desc', id, desc);
|
||||
|
||||
|
||||
var aIQ = new JSJaCIQ();
|
||||
aIQ.setTo(Common.fullXID(to));
|
||||
aIQ.setType('set');
|
||||
aIQ.setID(id);
|
||||
|
||||
|
||||
// Append the query content
|
||||
var aQuery = aIQ.setQuery(NS_IQOOB);
|
||||
aQuery.appendChild(aIQ.buildNode('url', {'xmlns': NS_IQOOB}, url));
|
||||
aQuery.appendChild(aIQ.buildNode('desc', {'xmlns': NS_IQOOB}, desc));
|
||||
|
||||
|
||||
con.send(aIQ);
|
||||
}
|
||||
|
||||
|
||||
// Message stanza?
|
||||
else {
|
||||
var aMsg = new JSJaCMessage();
|
||||
aMsg.setTo(Common.bareXID(to));
|
||||
|
||||
|
||||
// Append the content
|
||||
aMsg.setBody(desc);
|
||||
var aX = aMsg.appendNode('x', {'xmlns': NS_XOOB});
|
||||
aX.appendChild(aMsg.buildNode('url', {'xmlns': NS_XOOB}, url));
|
||||
|
||||
|
||||
con.send(aMsg);
|
||||
}
|
||||
|
||||
|
||||
Console.log('Sent OOB request to: ' + to + ' (' + desc + ')');
|
||||
} catch(e) {
|
||||
Console.error('OOB.send', e);
|
||||
|
@ -92,29 +93,25 @@ var OOB = (function () {
|
|||
self.handle = function(from, id, type, node) {
|
||||
|
||||
try {
|
||||
var xid = '';
|
||||
var url = '';
|
||||
var desc = '';
|
||||
|
||||
// IQ stanza?
|
||||
var xid = '', url = '', desc = '';
|
||||
|
||||
if(type == 'iq') {
|
||||
// IQ stanza
|
||||
xid = Common.fullXID(from);
|
||||
url = $(node).find('url').text();
|
||||
desc = $(node).find('desc').text();
|
||||
}
|
||||
|
||||
// Message stanza?
|
||||
else {
|
||||
} else {
|
||||
// Message stanza
|
||||
xid = Common.bareXID(from);
|
||||
url = $(node).find('url').text();
|
||||
desc = $(node).find('body').text();
|
||||
}
|
||||
|
||||
|
||||
// No desc?
|
||||
if(!desc) {
|
||||
desc = url;
|
||||
}
|
||||
|
||||
|
||||
// Open a new notification
|
||||
if(type && xid && url && desc) {
|
||||
Notification.create('send', xid, [xid, url, type, id, node], desc, hex_md5(xid + url + desc + id));
|
||||
|
@ -140,36 +137,43 @@ var OOB = (function () {
|
|||
|
||||
try {
|
||||
// Not IQ type?
|
||||
if(type != 'iq')
|
||||
if(type != 'iq') {
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// New IQ
|
||||
var aIQ = new JSJaCIQ();
|
||||
aIQ.setTo(to);
|
||||
aIQ.setID(id);
|
||||
|
||||
|
||||
// OOB request accepted
|
||||
if(choice == 'accept') {
|
||||
aIQ.setType('result');
|
||||
|
||||
|
||||
Console.info('Accepted file request from: ' + to);
|
||||
}
|
||||
|
||||
|
||||
// OOB request rejected
|
||||
else {
|
||||
aIQ.setType('error');
|
||||
|
||||
|
||||
// Append stanza content
|
||||
for(var i = 0; i < node.childNodes.length; i++)
|
||||
for(var i = 0; i < node.childNodes.length; i++) {
|
||||
aIQ.getNode().appendChild(node.childNodes.item(i).cloneNode(true));
|
||||
|
||||
}
|
||||
|
||||
// Append error content
|
||||
var aError = aIQ.appendNode('error', {'xmlns': NS_CLIENT, 'code': '406', 'type': 'modify'});
|
||||
var aError = aIQ.appendNode('error', {
|
||||
'xmlns': NS_CLIENT,
|
||||
'code': '406',
|
||||
'type': 'modify'
|
||||
});
|
||||
|
||||
aError.appendChild(aIQ.buildNode('not-acceptable', {'xmlns': NS_STANZAS}));
|
||||
|
||||
|
||||
Console.info('Rejected file request from: ' + to);
|
||||
}
|
||||
|
||||
|
||||
con.send(aIQ);
|
||||
} catch(e) {
|
||||
Console.error('OOB.reply', e);
|
||||
|
@ -187,11 +191,16 @@ var OOB = (function () {
|
|||
|
||||
try {
|
||||
// Append the wait icon
|
||||
$('#page-engine .chat-tools-file:not(.mini) .tooltip-subitem *').hide();
|
||||
$('#page-engine .chat-tools-file:not(.mini) .tooltip-subitem').append('<div class="wait wait-medium"></div>');
|
||||
|
||||
var chat_tools_file_sel = page_engine_sel.find('.chat-tools-file:not(.mini)');
|
||||
var subitem_sel = chat_tools_file_sel.find('.tooltip-subitem');
|
||||
|
||||
subitem_sel.find('*').hide();
|
||||
subitem_sel.append(
|
||||
'<div class="wait wait-medium"></div>'
|
||||
);
|
||||
|
||||
// Lock the bubble
|
||||
$('#page-engine .chat-tools-file:not(.mini)').addClass('mini');
|
||||
chat_tools_file_sel.addClass('mini');
|
||||
} catch(e) {
|
||||
Console.error('OOB.waitUpload', e);
|
||||
}
|
||||
|
@ -208,54 +217,55 @@ var OOB = (function () {
|
|||
self.handleUpload = function(responseXML) {
|
||||
|
||||
try {
|
||||
var page_engine_sel = $('#page-engine');
|
||||
|
||||
// Data selector
|
||||
var dData = $(responseXML).find('jappix');
|
||||
|
||||
|
||||
// Get the values
|
||||
var fID = dData.find('id').text();
|
||||
var fURL = dData.find('url').text();
|
||||
var fDesc = dData.find('desc').text();
|
||||
|
||||
|
||||
// Get the OOB values
|
||||
var oob_has;
|
||||
|
||||
|
||||
// No ID provided?
|
||||
if(!fID)
|
||||
if(!fID) {
|
||||
oob_has = ':has(.wait)';
|
||||
else
|
||||
} else {
|
||||
oob_has = ':has(#oob-upload input[value="' + fID + '"])';
|
||||
|
||||
var xid = $('#page-engine .page-engine-chan' + oob_has).attr('data-xid');
|
||||
var oob_type = $('#page-engine .chat-tools-file' + oob_has).attr('data-oob');
|
||||
|
||||
// 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?
|
||||
else if(fURL && fDesc && !dData.find('error').size()) {
|
||||
// Send the OOB request
|
||||
self.send(xid, oob_type, fURL, fDesc);
|
||||
|
||||
|
||||
// Notify the sender
|
||||
Notification.create('send_pending', xid, [xid, fURL, oob_type, '', ''], fDesc, hex_md5(fURL + fDesc + fID));
|
||||
|
||||
|
||||
Console.info('File request sent.');
|
||||
}
|
||||
|
||||
// Upload error?
|
||||
else {
|
||||
} else {
|
||||
Board.openThisError(4);
|
||||
|
||||
|
||||
Console.error('Error while sending the file', dData.find('error').text());
|
||||
}
|
||||
} catch(e) {
|
||||
|
|
|
@ -29,191 +29,191 @@ var Options = (function () {
|
|||
|
||||
try {
|
||||
// Popup HTML content
|
||||
var html =
|
||||
'<div class="top">' + Common._e("Edit options") + '</div>' +
|
||||
|
||||
'<div class="tab">' +
|
||||
'<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-account" data-key="3">' + Common._e("Account") + '</a>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="content">' +
|
||||
'<div id="conf1" class="lap-active one-lap forms">' +
|
||||
'<fieldset class="privacy">' +
|
||||
'<legend>' + Common._e("Privacy") + '</legend>' +
|
||||
|
||||
var html =
|
||||
'<div class="top">' + Common._e("Edit options") + '</div>' +
|
||||
|
||||
'<div class="tab">' +
|
||||
'<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-account" data-key="3">' + Common._e("Account") + '</a>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="content">' +
|
||||
'<div id="conf1" class="lap-active one-lap forms">' +
|
||||
'<fieldset class="privacy">' +
|
||||
'<legend>' + Common._e("Privacy") + '</legend>' +
|
||||
|
||||
'<div class="geolocation">' +
|
||||
'<label for="geolocation" class="pep-hidable">' + Common._e("Geolocation") + '</label>' +
|
||||
'<input id="geolocation" type="checkbox" class="pep-hidable" />' +
|
||||
'<label for="geolocation" class="pep-hidable">' + Common._e("Geolocation") + '</label>' +
|
||||
'<input id="geolocation" type="checkbox" class="pep-hidable" />' +
|
||||
'</div>' +
|
||||
|
||||
|
||||
'<div class="archiving">' +
|
||||
'<label for="archiving" class="mam-hidable">' + Common._e("Message archiving") + '</label>' +
|
||||
'<select id="archiving" class="mam-hidable">' +
|
||||
'<option value="never">' + Common._e("Disabled") + '</option>' +
|
||||
'<option value="roster">' + Common._e("Store friend chats") + '</option>' +
|
||||
'<option value="always">' + Common._e("Store all chats") + '</option>' +
|
||||
'</select>' +
|
||||
'<a href="#" class="linked empty-archives mam-purge-hidable">' + Common._e("Remove all archives") + '</a>' +
|
||||
'<label for="archiving" class="mam-hidable">' + Common._e("Message archiving") + '</label>' +
|
||||
'<select id="archiving" class="mam-hidable">' +
|
||||
'<option value="never">' + Common._e("Disabled") + '</option>' +
|
||||
'<option value="roster">' + Common._e("Store friend chats") + '</option>' +
|
||||
'<option value="always">' + Common._e("Store all chats") + '</option>' +
|
||||
'</select>' +
|
||||
'<a href="#" class="linked empty-archives mam-purge-hidable">' + Common._e("Remove all archives") + '</a>' +
|
||||
'</div>' +
|
||||
'</fieldset>' +
|
||||
|
||||
'<fieldset class="application">' +
|
||||
'<legend>' + Common._e("Application") + '</legend>' +
|
||||
|
||||
'</fieldset>' +
|
||||
|
||||
'<fieldset class="application">' +
|
||||
'<legend>' + Common._e("Application") + '</legend>' +
|
||||
|
||||
'<div class="sounds">' +
|
||||
'<label for="sounds">' + Common._e("Sounds") + '</label>' +
|
||||
'<input id="sounds" type="checkbox" />' +
|
||||
'<label for="sounds">' + Common._e("Sounds") + '</label>' +
|
||||
'<input id="sounds" type="checkbox" />' +
|
||||
'</div>' +
|
||||
|
||||
|
||||
'<div class="showall">' +
|
||||
'<label for="showall">' + Common._e("Show all friends") + '</label>' +
|
||||
'<input id="showall" type="checkbox" />' +
|
||||
'<label for="showall">' + Common._e("Show all friends") + '</label>' +
|
||||
'<input id="showall" type="checkbox" />' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="groupchatpresence">' +
|
||||
'<label for="groupchatpresence">' + Common._e("Groupchat presence messages") + '</label>' +
|
||||
'<input id="groupchatpresence" type="checkbox" />' +
|
||||
'<label for="groupchatpresence">' + Common._e("Groupchat presence messages") + '</label>' +
|
||||
'<input id="groupchatpresence" type="checkbox" />' +
|
||||
'</div>' +
|
||||
|
||||
|
||||
'<div class="noxhtmlimg">' +
|
||||
'<label for="noxhtmlimg">' + Common._e("No chat images auto-load") + '</label>' +
|
||||
'<input id="noxhtmlimg" type="checkbox" />' +
|
||||
'<label for="noxhtmlimg">' + Common._e("No chat images auto-load") + '</label>' +
|
||||
'<input id="noxhtmlimg" type="checkbox" />' +
|
||||
'</div>' +
|
||||
|
||||
|
||||
'<div class="integratemedias">' +
|
||||
'<label for="integratemedias">' + Common._e("Media integration") + '</label>' +
|
||||
'<input id="integratemedias" type="checkbox" />' +
|
||||
'<label for="integratemedias">' + Common._e("Media integration") + '</label>' +
|
||||
'<input id="integratemedias" type="checkbox" />' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="localarchives mam-showable">' +
|
||||
'<label for="localarchives">' + Common._e("Keep local chat archives") + '</label>' +
|
||||
'<input id="localarchives" type="checkbox" />' +
|
||||
'<label for="localarchives">' + Common._e("Keep local chat archives") + '</label>' +
|
||||
'<input id="localarchives" type="checkbox" />' +
|
||||
'</div>' +
|
||||
|
||||
|
||||
'<div class="xmpplinks">' +
|
||||
'<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>' +
|
||||
'<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>' +
|
||||
'</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") + ' »</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") + ' »</a>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div id="conf2" class="one-lap forms">' +
|
||||
'<fieldset class="channel">' +
|
||||
'<legend>' + Common._e("Channel") + '</legend>' +
|
||||
|
||||
'<div class="empty-channel">' +
|
||||
'<label>' + Common._e("Empty") + '</label>' +
|
||||
'<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>' +
|
||||
'<label>' + Common._e("Empty") + '</label>' +
|
||||
'<a href="#" class="linked empty-channel">' + Common._e("Empty channel") + '</a>' +
|
||||
'</div>' +
|
||||
|
||||
'</fieldset>' +
|
||||
|
||||
'<div class="sub-ask sub-ask-empty sub-ask-element">' +
|
||||
'<div class="sub-ask-top">' +
|
||||
'<div class="sub-ask-title">' + Common._e("Empty channel") + '</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-microblog check-empty" required="" />' +
|
||||
'</div>' +
|
||||
|
||||
'<a href="#" class="sub-ask-bottom">' + Common._e("Empty") + ' »</a>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div id="conf3" class="one-lap forms">' +
|
||||
'<fieldset>' +
|
||||
'<legend>' + Common._e("Account") + '</legend>' +
|
||||
|
||||
'<label>' + Common._e("Password") + '</label>' +
|
||||
'<a href="#" class="linked change-password">' + Common._e("Change password") + '</a>' +
|
||||
|
||||
'<label>' + Common._e("Delete") + '</label>' +
|
||||
'<a href="#" class="linked delete-account">' + Common._e("Delete account") + '</a>' +
|
||||
'</fieldset>' +
|
||||
|
||||
'<div class="sub-ask sub-ask-pass sub-ask-element">' +
|
||||
'<div class="sub-ask-top">' +
|
||||
'<div class="sub-ask-title">' + Common._e("Change password") + '</div>' +
|
||||
'<a href="#" class="sub-ask-close">X</a>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="sub-ask-content">' +
|
||||
'<label>' + Common._e("Old") + '</label>' +
|
||||
'<input type="password" class="password-change old" required="" />' +
|
||||
|
||||
'<label>' + Common._e("New (2 times)") + '</label>' +
|
||||
'<input type="password" class="password-change new1" required="" />' +
|
||||
'<input type="password" class="password-change new2" required="" />' +
|
||||
'</div>' +
|
||||
|
||||
'<a href="#" class="sub-ask-bottom">' + Common._e("Continue") + ' »</a>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="sub-ask sub-ask-delete sub-ask-element">' +
|
||||
'<div class="sub-ask-top">' +
|
||||
'<div class="sub-ask-title">' + Common._e("Delete account") + '</div>' +
|
||||
'<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") + ' »</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 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>' +
|
||||
|
||||
'</fieldset>' +
|
||||
|
||||
'<div class="sub-ask sub-ask-empty sub-ask-element">' +
|
||||
'<div class="sub-ask-top">' +
|
||||
'<div class="sub-ask-title">' + Common._e("Empty channel") + '</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-microblog check-empty" required="" />' +
|
||||
'</div>' +
|
||||
|
||||
'<a href="#" class="sub-ask-bottom">' + Common._e("Empty") + ' »</a>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div id="conf3" class="one-lap forms">' +
|
||||
'<fieldset>' +
|
||||
'<legend>' + Common._e("Account") + '</legend>' +
|
||||
|
||||
'<label>' + Common._e("Password") + '</label>' +
|
||||
'<a href="#" class="linked change-password">' + Common._e("Change password") + '</a>' +
|
||||
|
||||
'<label>' + Common._e("Delete") + '</label>' +
|
||||
'<a href="#" class="linked delete-account">' + Common._e("Delete account") + '</a>' +
|
||||
'</fieldset>' +
|
||||
|
||||
'<div class="sub-ask sub-ask-pass sub-ask-element">' +
|
||||
'<div class="sub-ask-top">' +
|
||||
'<div class="sub-ask-title">' + Common._e("Change password") + '</div>' +
|
||||
'<a href="#" class="sub-ask-close">X</a>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="sub-ask-content">' +
|
||||
'<label>' + Common._e("Old") + '</label>' +
|
||||
'<input type="password" class="password-change old" required="" />' +
|
||||
|
||||
'<label>' + Common._e("New (2 times)") + '</label>' +
|
||||
'<input type="password" class="password-change new1" required="" />' +
|
||||
'<input type="password" class="password-change new2" required="" />' +
|
||||
'</div>' +
|
||||
|
||||
'<a href="#" class="sub-ask-bottom">' + Common._e("Continue") + ' »</a>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="sub-ask sub-ask-delete sub-ask-element">' +
|
||||
'<div class="sub-ask-top">' +
|
||||
'<div class="sub-ask-title">' + Common._e("Delete account") + '</div>' +
|
||||
'<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") + ' »</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>';
|
||||
|
||||
|
||||
// Create the popup
|
||||
Popup.create('options', html);
|
||||
|
||||
|
||||
// Apply the features
|
||||
Features.apply('options');
|
||||
|
||||
|
||||
// Associate the events
|
||||
self.instance();
|
||||
} catch(e) {
|
||||
|
@ -275,11 +275,13 @@ var Options = (function () {
|
|||
self.switchTab = function(id) {
|
||||
|
||||
try {
|
||||
$('#options .one-lap').hide();
|
||||
$('#options #conf' + id).show();
|
||||
$('#options .tab a').removeClass('tab-active');
|
||||
$('#options .tab a[data-key="' + id + '"]').addClass('tab-active');
|
||||
$('#options .sub-ask .sub-ask-close').click();
|
||||
var options_sel = $('#options');
|
||||
|
||||
options_sel.find('.one-lap').hide();
|
||||
options_sel.find('#conf' + id).show();
|
||||
options_sel.find('.tab a').removeClass('tab-active');
|
||||
options_sel.find('.tab a[data-key="' + id + '"]').addClass('tab-active');
|
||||
options_sel.find('.sub-ask .sub-ask-close').click();
|
||||
} catch(e) {
|
||||
Console.error('Options.switchTab', e);
|
||||
} finally {
|
||||
|
@ -298,15 +300,16 @@ var Options = (function () {
|
|||
self.wait = function(id) {
|
||||
|
||||
try {
|
||||
var sOptions = $('#options .content');
|
||||
|
||||
var options_sel = $('#options');
|
||||
var content_sel = options_sel.find('.content');
|
||||
|
||||
// Remove the current item class
|
||||
sOptions.removeClass(id);
|
||||
|
||||
content_sel.removeClass(id);
|
||||
|
||||
// Hide the waiting items if all was received
|
||||
if(!sOptions.hasClass('microblog') && !sOptions.hasClass('mam')) {
|
||||
$('#options .wait').hide();
|
||||
$('#options .finish:first').removeClass('disabled');
|
||||
if(!content_sel.hasClass('microblog') && !content_sel.hasClass('mam')) {
|
||||
options_sel.find('.wait').hide();
|
||||
options_sel.find('.finish:first').removeClass('disabled');
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Options.wait', e);
|
||||
|
@ -332,25 +335,25 @@ var Options = (function () {
|
|||
var integratemedias = DataStore.getDB(Connection.desktop_hash, 'options', 'integratemedias');
|
||||
var localarchives = DataStore.getDB(Connection.desktop_hash, 'options', 'localarchives');
|
||||
var status = DataStore.getDB(Connection.desktop_hash, 'options', 'presence-status');
|
||||
|
||||
|
||||
// Create an array to be looped
|
||||
var oType = ['sounds', 'geolocation', 'roster-showall', 'no-xhtml-images', 'groupchatpresence', 'integratemedias', 'localarchives', 'presence-status'];
|
||||
var oContent = [sounds, geolocation, showall, noxhtmlimg, groupchatpresence, integratemedias, localarchives, status];
|
||||
|
||||
|
||||
// New IQ
|
||||
var iq = new JSJaCIQ();
|
||||
iq.setType('set');
|
||||
|
||||
|
||||
var query = iq.setQuery(NS_PRIVATE);
|
||||
var storage = query.appendChild(iq.buildNode('storage', {'xmlns': NS_OPTIONS}));
|
||||
|
||||
|
||||
// Loop the array
|
||||
for(var i in oType) {
|
||||
storage.appendChild(iq.buildNode('option', {'type': oType[i], 'xmlns': NS_OPTIONS}, oContent[i]));
|
||||
}
|
||||
|
||||
|
||||
con.send(iq, self.handleStore);
|
||||
|
||||
|
||||
Console.info('Storing options...');
|
||||
} catch(e) {
|
||||
Console.error('Options.store', e);
|
||||
|
@ -390,27 +393,27 @@ var Options = (function () {
|
|||
try {
|
||||
// We apply the sounds
|
||||
var sounds = '0';
|
||||
|
||||
|
||||
if($('#sounds').filter(':checked').size()) {
|
||||
sounds = '1';
|
||||
}
|
||||
|
||||
|
||||
DataStore.setDB(Connection.desktop_hash, 'options', 'sounds', sounds);
|
||||
|
||||
|
||||
// We apply the geolocation
|
||||
if($('#geolocation').filter(':checked').size()) {
|
||||
DataStore.setDB(Connection.desktop_hash, 'options', 'geolocation', '1');
|
||||
|
||||
|
||||
// We geolocate the user on the go
|
||||
PEP.geolocate();
|
||||
} else {
|
||||
DataStore.setDB(Connection.desktop_hash, 'options', 'geolocation', '0');
|
||||
|
||||
|
||||
// We delete the geolocation informations
|
||||
PEP.sendPosition();
|
||||
DataStore.removeDB(Connection.desktop_hash, 'geolocation', 'now');
|
||||
}
|
||||
|
||||
|
||||
// We apply the roster show all
|
||||
if($('#showall').filter(':checked').size()) {
|
||||
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');
|
||||
Interface.showOnlineBuddies('options');
|
||||
}
|
||||
|
||||
|
||||
// We apply the XHTML-IM images filter
|
||||
var noxhtmlimg = '1' ? $('#noxhtmlimg').filter(':checked').size() : '0';
|
||||
DataStore.setDB(Connection.desktop_hash, 'options', 'no-xhtml-images', noxhtmlimg);
|
||||
|
||||
|
||||
// We apply the groupchat presence messages configuration
|
||||
var groupchatpresence = '1' ? $('#groupchatpresence').filter(':checked').size() : '0';
|
||||
DataStore.setDB(Connection.desktop_hash, 'options', 'groupchatpresence', groupchatpresence);
|
||||
|
@ -440,23 +443,23 @@ var Options = (function () {
|
|||
if(localarchives === '0') {
|
||||
Message.flushLocalArchive();
|
||||
}
|
||||
|
||||
|
||||
// We apply the message archiving
|
||||
if(Features.enabledMAM()) {
|
||||
MAM.setConfig($('#archiving').val() || 'never');
|
||||
}
|
||||
|
||||
|
||||
// We apply the microblog configuration
|
||||
var persist = '1' ? $('#persist').filter(':checked').size() : '0';
|
||||
var maximum = $('#maxnotices').val();
|
||||
|
||||
|
||||
if(Features.enabledPEP() && (Features.enabledPubSub() || Features.enabledPubSubCN())) {
|
||||
Pubsub.setup('', NS_URN_MBLOG, persist, maximum, '', '', false);
|
||||
}
|
||||
|
||||
|
||||
// We send the options to the database
|
||||
self.store();
|
||||
|
||||
|
||||
// Close the options
|
||||
self.close();
|
||||
} catch(e) {
|
||||
|
@ -479,13 +482,13 @@ var Options = (function () {
|
|||
try {
|
||||
// Remove the general wait item
|
||||
Interface.removeGeneralWait();
|
||||
|
||||
|
||||
// If no errors
|
||||
if(!Errors.handleReply(iq)) {
|
||||
Connection.clearLastSession();
|
||||
Connection.quit();
|
||||
Board.openThisInfo(1);
|
||||
|
||||
|
||||
Console.info('Password changed.');
|
||||
} else {
|
||||
Console.warn('Password not changed.');
|
||||
|
@ -510,45 +513,49 @@ var Options = (function () {
|
|||
var password0 = $('#options .old').val();
|
||||
var password1 = $('#options .new1').val();
|
||||
var password2 = $('#options .new2').val();
|
||||
|
||||
|
||||
if ((password1 == password2) && (password0 == Utils.getPassword())) {
|
||||
// We show the waiting image
|
||||
Interface.showGeneralWait();
|
||||
|
||||
|
||||
// We send the IQ
|
||||
var iq = new JSJaCIQ();
|
||||
|
||||
|
||||
iq.setTo(Utils.getServer());
|
||||
iq.setType('set');
|
||||
|
||||
|
||||
var iqQuery = iq.setQuery(NS_REGISTER);
|
||||
|
||||
|
||||
iqQuery.appendChild(iq.buildNode('username', {'xmlns': NS_REGISTER}, con.username));
|
||||
iqQuery.appendChild(iq.buildNode('password', {'xmlns': NS_REGISTER}, password1));
|
||||
|
||||
|
||||
con.send(iq, self.handlePwdChange);
|
||||
|
||||
|
||||
Console.info('Password change sent.');
|
||||
} else {
|
||||
$('.sub-ask-pass input').each(function() {
|
||||
var select = $(this);
|
||||
|
||||
if(!select.val())
|
||||
|
||||
if(!select.val()) {
|
||||
$(document).oneTime(10, function() {
|
||||
select.addClass('please-complete').focus();
|
||||
});
|
||||
else
|
||||
select.removeClass('please-complete');
|
||||
} else {
|
||||
select.removeClass('please-complete');
|
||||
}
|
||||
});
|
||||
|
||||
if(password0 != Utils.getPassword())
|
||||
|
||||
if(password0 != Utils.getPassword()) {
|
||||
$(document).oneTime(10, function() {
|
||||
$('#options .old').addClass('please-complete').focus();
|
||||
});
|
||||
if(password1 != password2)
|
||||
}
|
||||
|
||||
if(password1 != password2) {
|
||||
$(document).oneTime(10, function() {
|
||||
$('#options .new1, #options .new2').addClass('please-complete').focus();
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Options.sendNewPassword', e);
|
||||
|
@ -570,14 +577,14 @@ var Options = (function () {
|
|||
try {
|
||||
// Remove the general wait item
|
||||
Interface.removeGeneralWait();
|
||||
|
||||
|
||||
// If no errors
|
||||
if(!Errors.handleReply(iq)) {
|
||||
Connection.clearLastSession();
|
||||
Talk.destroy();
|
||||
Board.openThisInfo(2);
|
||||
Connection.logout();
|
||||
|
||||
|
||||
Console.info('Account deleted.');
|
||||
} else {
|
||||
Console.warn('Account not deleted.');
|
||||
|
@ -599,7 +606,7 @@ var Options = (function () {
|
|||
try {
|
||||
var pwd_input_sel = $('#options .check-mam');
|
||||
var password = pwd_input_sel.val();
|
||||
|
||||
|
||||
if(password == Utils.getPassword()) {
|
||||
MAM.purgeArchives();
|
||||
|
||||
|
@ -611,13 +618,14 @@ var Options = (function () {
|
|||
$('#options .sub-ask-mam .sub-ask-close').click();
|
||||
} else {
|
||||
var selector = $('#options .check-mam');
|
||||
|
||||
if(password != Utils.getPassword())
|
||||
|
||||
if(password != Utils.getPassword()) {
|
||||
$(document).oneTime(10, function() {
|
||||
selector.addClass('please-complete').focus();
|
||||
});
|
||||
else
|
||||
} else {
|
||||
selector.removeClass('please-complete');
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Options.purgeMyArchives', e);
|
||||
|
@ -640,31 +648,32 @@ var Options = (function () {
|
|||
try {
|
||||
var pwd_input_sel = $('#options .check-empty');
|
||||
var password = pwd_input_sel.val();
|
||||
|
||||
|
||||
if(password == Utils.getPassword()) {
|
||||
// Send the IQ to remove the item (and get eventual error callback)
|
||||
var iq = new JSJaCIQ();
|
||||
iq.setType('set');
|
||||
|
||||
|
||||
var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB_OWNER});
|
||||
pubsub.appendChild(iq.buildNode('purge', {'node': NS_URN_MBLOG, 'xmlns': NS_PUBSUB_OWNER}));
|
||||
|
||||
|
||||
con.send(iq, self.handleMicroblogPurge);
|
||||
|
||||
|
||||
// Hide the tool
|
||||
pwd_input_sel.val('');
|
||||
$('#options .sub-ask-empty .sub-ask-close').click();
|
||||
|
||||
|
||||
Console.info('Microblog purge sent.');
|
||||
} else {
|
||||
var selector = $('#options .check-empty');
|
||||
|
||||
if(password != Utils.getPassword())
|
||||
|
||||
if(password != Utils.getPassword()) {
|
||||
$(document).oneTime(10, function() {
|
||||
selector.addClass('please-complete').focus();
|
||||
});
|
||||
else
|
||||
} else {
|
||||
selector.removeClass('please-complete');
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Options.purgeMyMicroblog', e);
|
||||
|
@ -688,7 +697,7 @@ var Options = (function () {
|
|||
if(!Errors.handleReply(iq)) {
|
||||
// Remove the microblog items
|
||||
$('.one-update.update_' + hex_md5(Common.getXID())).remove();
|
||||
|
||||
|
||||
Console.info('Microblog purged.');
|
||||
} else {
|
||||
Console.warn('Microblog not purged.');
|
||||
|
@ -711,32 +720,31 @@ var Options = (function () {
|
|||
|
||||
try {
|
||||
var password = $('#options .check-password').val();
|
||||
|
||||
|
||||
if(password == Utils.getPassword()) {
|
||||
// We show the waiting image
|
||||
Interface.showGeneralWait();
|
||||
|
||||
|
||||
// We send the IQ
|
||||
var iq = new JSJaCIQ();
|
||||
iq.setType('set');
|
||||
|
||||
|
||||
var iqQuery = iq.setQuery(NS_REGISTER);
|
||||
iqQuery.appendChild(iq.buildNode('remove', {'xmlns': NS_REGISTER}));
|
||||
|
||||
|
||||
con.send(iq, self.handleAccDeletion);
|
||||
|
||||
|
||||
Console.info('Delete account sent.');
|
||||
}
|
||||
|
||||
else {
|
||||
} else {
|
||||
var selector = $('#options .check-password');
|
||||
|
||||
if(password != Utils.getPassword())
|
||||
|
||||
if(password != Utils.getPassword()) {
|
||||
$(document).oneTime(10, function() {
|
||||
selector.addClass('please-complete').focus();
|
||||
});
|
||||
else
|
||||
} else {
|
||||
selector.removeClass('please-complete');
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Options.deleteMyAccount', e);
|
||||
|
@ -761,70 +769,78 @@ var Options = (function () {
|
|||
var enabled_pubsub_cn = Features.enabledPubSubCN();
|
||||
var enabled_pep = Features.enabledPEP();
|
||||
var sWait = $('#options .content');
|
||||
|
||||
|
||||
// Show the waiting items if necessary
|
||||
if(enabled_mam || (enabled_pep && (enabled_pubsub || enabled_pubsub_cn))) {
|
||||
$('#options .wait').show();
|
||||
$('#options .finish:first').addClass('disabled');
|
||||
}
|
||||
|
||||
|
||||
// We get the archiving configuration
|
||||
if(enabled_mam) {
|
||||
sWait.addClass('mam');
|
||||
MAM.getConfig();
|
||||
}
|
||||
|
||||
|
||||
// We get the microblog configuration
|
||||
if((enabled_pubsub || enabled_pubsub_cn) && enabled_pep) {
|
||||
sWait.addClass('microblog');
|
||||
Microblog.getConfig();
|
||||
}
|
||||
|
||||
|
||||
// We show the "privacy" form if something is visible into it
|
||||
if(enabled_mam || enabled_pep)
|
||||
if(enabled_mam || enabled_pep) {
|
||||
$('#options fieldset.privacy').show();
|
||||
|
||||
}
|
||||
|
||||
// We get the values of the forms for the sounds
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'sounds') == '0')
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'sounds') == '0') {
|
||||
$('#sounds').attr('checked', false);
|
||||
else
|
||||
} else {
|
||||
$('#sounds').attr('checked', true);
|
||||
|
||||
}
|
||||
|
||||
// We get the values of the forms for the geolocation
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'geolocation') == '1')
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'geolocation') == '1') {
|
||||
$('#geolocation').attr('checked', true);
|
||||
else
|
||||
} else {
|
||||
$('#geolocation').attr('checked', false);
|
||||
|
||||
}
|
||||
|
||||
// We get the values of the forms for the roster show all
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'roster-showall') == '1')
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'roster-showall') == '1') {
|
||||
$('#showall').attr('checked', true);
|
||||
else
|
||||
} else {
|
||||
$('#showall').attr('checked', false);
|
||||
|
||||
}
|
||||
|
||||
// We get the values of the forms for the XHTML-IM images filter
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'no-xhtml-images') == '1')
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'no-xhtml-images') == '1') {
|
||||
$('#noxhtmlimg').attr('checked', true);
|
||||
else
|
||||
} else {
|
||||
$('#noxhtmlimg').attr('checked', false);
|
||||
|
||||
}
|
||||
|
||||
// We get the values of the forms for the integratemedias
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'integratemedias') == '0')
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'integratemedias') == '0') {
|
||||
$('#integratemedias').attr('checked', false);
|
||||
else
|
||||
} else {
|
||||
$('#integratemedias').attr('checked', true);
|
||||
}
|
||||
|
||||
// We get the values of the forms for the groupchatpresence
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'groupchatpresence') == '0')
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'groupchatpresence') == '0') {
|
||||
$('#groupchatpresence').attr('checked', false);
|
||||
else
|
||||
} else {
|
||||
$('#groupchatpresence').attr('checked', true);
|
||||
}
|
||||
|
||||
// We get the values of the forms for the localarchives
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'localarchives') == '0')
|
||||
if(DataStore.getDB(Connection.desktop_hash, 'options', 'localarchives') == '0') {
|
||||
$('#localarchives').attr('checked', false);
|
||||
else
|
||||
} else {
|
||||
$('#localarchives').attr('checked', true);
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Options.load', e);
|
||||
}
|
||||
|
@ -845,80 +861,80 @@ var Options = (function () {
|
|||
// Yet active?
|
||||
if($(this).hasClass('tab-active'))
|
||||
return false;
|
||||
|
||||
|
||||
// Switch to the good tab
|
||||
var key = parseInt($(this).attr('data-key'));
|
||||
|
||||
|
||||
return self.switchTab(key);
|
||||
});
|
||||
|
||||
|
||||
$('#options .linked').click(function() {
|
||||
$('#options .sub-ask').hide();
|
||||
$('#options .forms').removeClass('in_background');
|
||||
});
|
||||
|
||||
|
||||
$('#options .xmpp-links').click(function() {
|
||||
Utils.xmppLinksHandler();
|
||||
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#options .empty-archives').click(function() {
|
||||
var selector = '#options .sub-ask-mam';
|
||||
|
||||
|
||||
$(selector).show();
|
||||
$('#options .forms').addClass('in_background');
|
||||
|
||||
|
||||
$(document).oneTime(10, function() {
|
||||
$(selector + ' input').focus();
|
||||
});
|
||||
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
$('#options .empty-channel').click(function() {
|
||||
var selector = '#options .sub-ask-empty';
|
||||
|
||||
|
||||
$(selector).show();
|
||||
$('#options .forms').addClass('in_background');
|
||||
|
||||
|
||||
$(document).oneTime(10, function() {
|
||||
$(selector + ' input').focus();
|
||||
});
|
||||
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
$('#options .change-password').click(function() {
|
||||
var selector = '#options .sub-ask-pass';
|
||||
|
||||
|
||||
$(selector).show();
|
||||
$('#options .forms').addClass('in_background');
|
||||
|
||||
|
||||
$(document).oneTime(10, function() {
|
||||
$(selector + ' input:first').focus();
|
||||
});
|
||||
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
$('#options .delete-account').click(function() {
|
||||
var selector = '#options .sub-ask-delete';
|
||||
|
||||
|
||||
$(selector).show();
|
||||
$('#options .forms').addClass('in_background');
|
||||
|
||||
|
||||
$(document).oneTime(10, function() {
|
||||
$(selector + ' input').focus();
|
||||
});
|
||||
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
$('#options .sub-ask-pass .sub-ask-bottom').click(function() {
|
||||
return self.sendNewPassword();
|
||||
});
|
||||
|
||||
|
||||
$('#options .sub-ask-mam .sub-ask-bottom').click(function() {
|
||||
return self.purgeMyArchives();
|
||||
});
|
||||
|
@ -926,48 +942,55 @@ var Options = (function () {
|
|||
$('#options .sub-ask-empty .sub-ask-bottom').click(function() {
|
||||
return self.purgeMyMicroblog();
|
||||
});
|
||||
|
||||
|
||||
$('#options .sub-ask-delete .sub-ask-bottom').click(function() {
|
||||
return self.deleteMyAccount();
|
||||
});
|
||||
|
||||
|
||||
$('#options .sub-ask-close').click(function() {
|
||||
$('#options .sub-ask').hide();
|
||||
$('#options .forms').removeClass('in_background');
|
||||
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
$('#options .bottom .finish').click(function() {
|
||||
if($(this).is('.save') && !$(this).hasClass('disabled'))
|
||||
if($(this).is('.save') && !$(this).hasClass('disabled')) {
|
||||
return self.save();
|
||||
if($(this).is('.cancel'))
|
||||
}
|
||||
|
||||
if($(this).is('.cancel')) {
|
||||
return self.close();
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
// The keyup events
|
||||
$('#options .sub-ask input').keyup(function(e) {
|
||||
if(e.keyCode == 13) {
|
||||
// Archives purge
|
||||
if($(this).is('.purge-archives'))
|
||||
if($(this).is('.purge-archives')) {
|
||||
return self.purgeMyArchives();
|
||||
}
|
||||
|
||||
// Microblog purge
|
||||
else if($(this).is('.purge-microblog'))
|
||||
else if($(this).is('.purge-microblog')) {
|
||||
return self.purgeMyMicroblog();
|
||||
|
||||
}
|
||||
|
||||
// Password change
|
||||
else if($(this).is('.password-change'))
|
||||
else if($(this).is('.password-change')) {
|
||||
return self.sendNewPassword();
|
||||
|
||||
}
|
||||
|
||||
// Account deletion
|
||||
else if($(this).is('.delete-account'))
|
||||
else if($(this).is('.delete-account')) {
|
||||
return self.deleteMyAccount();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Load the options
|
||||
self.load();
|
||||
} catch(e) {
|
||||
|
|
|
@ -34,27 +34,27 @@ var Popup = (function () {
|
|||
if(Common.exists('#' + id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Popop on top of another one?
|
||||
var top_of = Common.exists('div.lock:has(div.popup)');
|
||||
|
||||
|
||||
// Append the popup code
|
||||
$('body').append(
|
||||
'<div id="' + id + '" class="lock removable">' +
|
||||
'<div class="popup">' +
|
||||
content +
|
||||
'</div>' +
|
||||
'<div id="' + id + '" class="lock removable">' +
|
||||
'<div class="popup">' +
|
||||
content +
|
||||
'</div>' +
|
||||
'</div>'
|
||||
);
|
||||
|
||||
|
||||
// Avoids darker popup background (if on top of another popup)
|
||||
if(top_of) {
|
||||
$('#' + id).css('background', 'transparent');
|
||||
}
|
||||
|
||||
|
||||
// Attach popup events
|
||||
self.instance(id);
|
||||
|
||||
|
||||
return true;
|
||||
} catch(e) {
|
||||
Console.error('Popup.create', e);
|
||||
|
@ -74,10 +74,10 @@ var Popup = (function () {
|
|||
try {
|
||||
// Stop the popup timers
|
||||
$('#' + id + ' *').stopTime();
|
||||
|
||||
|
||||
// Remove the popup
|
||||
$('#' + id).remove();
|
||||
|
||||
|
||||
// Manage input focus
|
||||
Interface.inputFocus();
|
||||
} catch(e) {
|
||||
|
@ -102,7 +102,7 @@ var Popup = (function () {
|
|||
if($(evt.target).is('.lock:not(.unavoidable)')) {
|
||||
// Destroy the popup
|
||||
self.destroy(id);
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -40,12 +40,12 @@ var Pubsub = (function () {
|
|||
// Create the PubSub node
|
||||
var iq = new JSJaCIQ();
|
||||
iq.setType('set');
|
||||
|
||||
|
||||
// Any external entity?
|
||||
if(entity) {
|
||||
iq.setTo(entity);
|
||||
}
|
||||
|
||||
|
||||
// Create it?
|
||||
var pubsub;
|
||||
|
||||
|
@ -55,38 +55,38 @@ var Pubsub = (function () {
|
|||
} else {
|
||||
pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB_OWNER});
|
||||
}
|
||||
|
||||
|
||||
// Configure it!
|
||||
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 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));
|
||||
|
||||
|
||||
// Persist items?
|
||||
if(persist) {
|
||||
var field2 = x.appendChild(iq.buildNode('field', {'var': 'pubsub#persist_items', 'xmlns': NS_XDATA}));
|
||||
field2.appendChild(iq.buildNode('value', {'xmlns': NS_XDATA}, persist));
|
||||
}
|
||||
|
||||
|
||||
// Maximum items?
|
||||
if(maximum) {
|
||||
var field3 = x.appendChild(iq.buildNode('field', {'var': 'pubsub#max_items', 'xmlns': NS_XDATA}));
|
||||
field3.appendChild(iq.buildNode('value', {'xmlns': NS_XDATA}, maximum));
|
||||
}
|
||||
|
||||
|
||||
// Access rights?
|
||||
if(access) {
|
||||
var field4 = x.appendChild(iq.buildNode('field', {'var': 'pubsub#access_model', 'xmlns': NS_XDATA}));
|
||||
field4.appendChild(iq.buildNode('value', {'xmlns': NS_XDATA}, access));
|
||||
}
|
||||
|
||||
|
||||
// Publish rights?
|
||||
if(publish) {
|
||||
var field5 = x.appendChild(iq.buildNode('field', {'var': 'pubsub#publish_model', 'xmlns': NS_XDATA}));
|
||||
field5.appendChild(iq.buildNode('value', {'xmlns': NS_XDATA}, publish));
|
||||
}
|
||||
|
||||
|
||||
con.send(iq);
|
||||
} catch(e) {
|
||||
Console.error('Pubsub.setup', e);
|
||||
|
|
|
@ -106,16 +106,17 @@ var Receipts = (function () {
|
|||
var aMsg = new JSJaCMessage();
|
||||
aMsg.setTo(to);
|
||||
aMsg.setID(id);
|
||||
|
||||
|
||||
// Any type?
|
||||
if(type)
|
||||
if(type) {
|
||||
aMsg.setType(type);
|
||||
|
||||
}
|
||||
|
||||
// Append the received node
|
||||
aMsg.appendNode('received', {'xmlns': NS_URN_RECEIPTS, 'id': id});
|
||||
|
||||
|
||||
con.send(aMsg);
|
||||
|
||||
|
||||
Console.log('Sent received to: ' + to);
|
||||
} catch(e) {
|
||||
Console.error('Receipts.sendReceived', e);
|
||||
|
@ -136,18 +137,18 @@ var Receipts = (function () {
|
|||
try {
|
||||
// Line selector
|
||||
var path = $('#' + hash + ' .one-line[data-id="' + id + '"]');
|
||||
|
||||
|
||||
// Add a received marker
|
||||
path.attr('data-received', 'true')
|
||||
.removeAttr('data-lost');
|
||||
|
||||
|
||||
// Group selector
|
||||
var group = path.parent();
|
||||
|
||||
|
||||
// Remove the group marker
|
||||
if(!group.find('.one-line[data-lost]').size()) {
|
||||
group.find('b.name').removeClass('talk-images')
|
||||
.removeAttr('title');
|
||||
.removeAttr('title');
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Receipts.messageReceived', e);
|
||||
|
@ -170,14 +171,19 @@ var Receipts = (function () {
|
|||
try {
|
||||
// Fire a check 10 seconds later
|
||||
$('#' + hash + ' .one-line[data-id="' + id + '"]').oneTime('10s', function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// Not received?
|
||||
if($(this).attr('data-received') != 'true') {
|
||||
if(this_sel.attr('data-received') != 'true') {
|
||||
// Add a "lost" marker
|
||||
$(this).attr('data-lost', 'true');
|
||||
|
||||
this_sel.attr('data-lost', 'true');
|
||||
|
||||
// Add a warn on the buddy-name
|
||||
$(this).parent().find('b.name').addClass('talk-images')
|
||||
.attr('title', Common._e("Your friend seems not to have received your message(s)!"));
|
||||
this_sel.parent().find('b.name').addClass('talk-images')
|
||||
.attr(
|
||||
'title',
|
||||
Common._e("Your friend seems not to have received your message(s)!")
|
||||
);
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
|
|
|
@ -18,7 +18,7 @@ var RosterX = (function () {
|
|||
* @private
|
||||
*/
|
||||
var self = {};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Opens the rosterx tools
|
||||
|
@ -30,32 +30,32 @@ var RosterX = (function () {
|
|||
|
||||
try {
|
||||
// Popup HTML content
|
||||
var html =
|
||||
'<div class="top">' + Common._e("Suggested friends") + '</div>' +
|
||||
|
||||
'<div class="content">' +
|
||||
'<div class="rosterx-head">' +
|
||||
'<a href="#" class="uncheck">' + Common._e("Uncheck all") + '</a>' +
|
||||
'<a href="#" class="check">' + Common._e("Check all") + '</a>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="results"></div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="bottom">' +
|
||||
'<a href="#" class="finish save">' + Common._e("Save") + '</a>' +
|
||||
'<a href="#" class="finish cancel">' + Common._e("Cancel") + '</a>' +
|
||||
var html =
|
||||
'<div class="top">' + Common._e("Suggested friends") + '</div>' +
|
||||
|
||||
'<div class="content">' +
|
||||
'<div class="rosterx-head">' +
|
||||
'<a href="#" class="uncheck">' + Common._e("Uncheck all") + '</a>' +
|
||||
'<a href="#" class="check">' + Common._e("Check all") + '</a>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="results"></div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="bottom">' +
|
||||
'<a href="#" class="finish save">' + Common._e("Save") + '</a>' +
|
||||
'<a href="#" class="finish cancel">' + Common._e("Cancel") + '</a>' +
|
||||
'</div>';
|
||||
|
||||
|
||||
// Create the popup
|
||||
Popup.create('rosterx', html);
|
||||
|
||||
|
||||
// Associate the events
|
||||
self.instance();
|
||||
|
||||
|
||||
// Parse the data
|
||||
self.parse(data);
|
||||
|
||||
|
||||
Console.log('Roster Item Exchange popup opened.');
|
||||
} catch(e) {
|
||||
Console.error('RosterX.open', e);
|
||||
|
@ -94,37 +94,47 @@ var RosterX = (function () {
|
|||
try {
|
||||
// Main selector
|
||||
var x = $(data).find('x[xmlns="' + NS_ROSTERX + '"]:first');
|
||||
|
||||
|
||||
// Parse data
|
||||
x.find('item').each(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// Generate group XML
|
||||
var group = '';
|
||||
|
||||
$(this).find('group').each(function() {
|
||||
group += '<group>' + $(this).text().htmlEnc() + '</group>';
|
||||
|
||||
this_sel.find('group').each(function() {
|
||||
group += '<group>' + this_sel.text().htmlEnc() + '</group>';
|
||||
});
|
||||
|
||||
if(group)
|
||||
|
||||
if(group) {
|
||||
group = '<groups>' + group + '</groups>';
|
||||
|
||||
}
|
||||
|
||||
// Display it!
|
||||
self.display($(this).attr('jid'), $(this).attr('name'), group, $(this).attr('action'));
|
||||
self.display(
|
||||
this_sel.attr('jid'),
|
||||
this_sel.attr('name'),
|
||||
group,
|
||||
this_sel.attr('action')
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
// Click to check/uncheck
|
||||
$('#rosterx .oneresult').click(function(evt) {
|
||||
// No need to apply when click on input
|
||||
if($(evt.target).is('input[type="checkbox"]'))
|
||||
if($(evt.target).is('input[type="checkbox"]')) {
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// Input selector
|
||||
var checkbox = $(this).find('input[type="checkbox"]');
|
||||
|
||||
|
||||
// Check or uncheck?
|
||||
if(checkbox.filter(':checked').size())
|
||||
if(checkbox.filter(':checked').size()) {
|
||||
checkbox.removeAttr('checked');
|
||||
else
|
||||
} else {
|
||||
checkbox.attr('checked', true);
|
||||
}
|
||||
});
|
||||
} catch(e) {
|
||||
Console.error('RosterX.parse', e);
|
||||
|
@ -146,24 +156,27 @@ var RosterX = (function () {
|
|||
|
||||
try {
|
||||
// End if no XID
|
||||
if(!xid)
|
||||
if(!xid) {
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
// Set up a default action if no one
|
||||
if(!action || (action != 'modify') || (action != 'delete'))
|
||||
if(!action || (action != 'modify') || (action != 'delete')) {
|
||||
action = 'add';
|
||||
|
||||
}
|
||||
|
||||
// Override "undefined" for nickname
|
||||
if(!nick)
|
||||
if(!nick) {
|
||||
nick = '';
|
||||
|
||||
}
|
||||
|
||||
// Display it
|
||||
$('#rosterx .results').append(
|
||||
'<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) + '" />' +
|
||||
'<span class="name">' + nick.htmlEnc() + '</span>' +
|
||||
'<span class="xid">' + xid.htmlEnc() + '</span>' +
|
||||
'<span class="action ' + action + ' talk-images"></span>' +
|
||||
'<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) + '" />' +
|
||||
'<span class="name">' + nick.htmlEnc() + '</span>' +
|
||||
'<span class="xid">' + xid.htmlEnc() + '</span>' +
|
||||
'<span class="action ' + action + ' talk-images"></span>' +
|
||||
'</div>'
|
||||
);
|
||||
|
||||
|
@ -178,31 +191,33 @@ var RosterX = (function () {
|
|||
/**
|
||||
* Saves the rosterx settings
|
||||
* @public
|
||||
* @return {undefined}
|
||||
* @return {boolean}
|
||||
*/
|
||||
self.save = function() {
|
||||
|
||||
try {
|
||||
// Send the requests
|
||||
$('#rosterx .results input[type="checkbox"]').filter(':checked').each(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// Read the attributes
|
||||
var nick = $(this).attr('data-name');
|
||||
var xid = $(this).attr('data-xid');
|
||||
var action = $(this).attr('data-action');
|
||||
var group = $(this).attr('data-group');
|
||||
|
||||
var nick = this_sel.attr('data-name');
|
||||
var xid = this_sel.attr('data-xid');
|
||||
var action = this_sel.attr('data-action');
|
||||
var group = this_sel.attr('data-group');
|
||||
|
||||
// Parse groups XML
|
||||
var group_arr = [];
|
||||
|
||||
|
||||
if(group) {
|
||||
$(group).find('group').each(function() {
|
||||
group_arr.push($(this).text().revertHtmlEnc());
|
||||
group_arr.push(this_sel.text().revertHtmlEnc());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Process the asked action
|
||||
var roster_item = $('#roster .' + hex_md5(xid));
|
||||
|
||||
|
||||
switch(action) {
|
||||
// Buddy add
|
||||
case 'add':
|
||||
|
@ -210,29 +225,31 @@ var RosterX = (function () {
|
|||
Presence.sendSubscribe(xid, 'subscribe');
|
||||
Roster.send(xid, '', nick, group_arr);
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
// Buddy edit
|
||||
case 'modify':
|
||||
if(Common.exists(roster_item))
|
||||
Roster.send(xid, '', nick, group_arr);
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
// Buddy delete
|
||||
case 'delete':
|
||||
if(Common.exists(roster_item))
|
||||
Roster.send(xid, 'remove');
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Close the popup
|
||||
self.close();
|
||||
} catch(e) {
|
||||
Console.error('RosterX.save', e);
|
||||
} finally {
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -248,18 +265,26 @@ var RosterX = (function () {
|
|||
try {
|
||||
// Click events
|
||||
$('#rosterx .bottom .finish').click(function() {
|
||||
if($(this).is('.save'))
|
||||
var this_sel = $(this);
|
||||
|
||||
if(this_sel.is('.save')) {
|
||||
return self.save();
|
||||
if($(this).is('.cancel'))
|
||||
}
|
||||
|
||||
if(this_sel.is('.cancel')) {
|
||||
return self.close();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
$('#rosterx .rosterx-head a').click(function() {
|
||||
if($(this).is('.check'))
|
||||
var this_sel = $(this);
|
||||
|
||||
if(this_sel.is('.check')) {
|
||||
$('#rosterx .results input[type="checkbox"]').attr('checked', true);
|
||||
else if($(this).is('.uncheck'))
|
||||
} else if(this_sel.is('.uncheck')) {
|
||||
$('#rosterx .results input[type="checkbox"]').removeAttr('checked');
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
} catch(e) {
|
||||
|
|
|
@ -37,34 +37,34 @@ var Search = (function () {
|
|||
if(!query) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Wildcard (*) submitted
|
||||
if(query == '*') {
|
||||
query = '';
|
||||
}
|
||||
|
||||
|
||||
// Replace forbidden characters in regex
|
||||
query = Common.escapeRegex(query);
|
||||
|
||||
|
||||
// Create an empty array
|
||||
var results = [];
|
||||
|
||||
|
||||
// Search regex
|
||||
var regex = new RegExp('((^)|( ))' + query, 'gi');
|
||||
|
||||
|
||||
// Search in the roster
|
||||
var buddies = Roster.getAllBuddies();
|
||||
|
||||
|
||||
for(var i in buddies) {
|
||||
var xid = buddies[i];
|
||||
var nick = Name.getBuddy(xid);
|
||||
|
||||
|
||||
// Buddy match our search, and not yet in the array
|
||||
if(nick.match(regex) && !Utils.existArrayValue(results, xid)) {
|
||||
results.push(xid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Return the results array
|
||||
return results;
|
||||
} catch(e) {
|
||||
|
@ -104,17 +104,18 @@ var Search = (function () {
|
|||
try {
|
||||
// Remove the search tool
|
||||
self.resetBuddy(destination);
|
||||
|
||||
|
||||
// Define a selector
|
||||
var input = $(destination + ' input');
|
||||
var value = input.val();
|
||||
|
||||
|
||||
// Get the old value (if there's another value)
|
||||
var old = '';
|
||||
|
||||
if(value.match(/(^(.+)(,)(\s)?)(\w+)$/))
|
||||
|
||||
if(value.match(/(^(.+)(,)(\s)?)(\w+)$/)) {
|
||||
old = RegExp.$1;
|
||||
|
||||
}
|
||||
|
||||
// Add the XID to the "to" input and focus on it
|
||||
$(document).oneTime(10, function() {
|
||||
input.val(old + xid).focus();
|
||||
|
@ -139,56 +140,57 @@ var Search = (function () {
|
|||
try {
|
||||
// Reset the search engine
|
||||
self.resetBuddy(destination);
|
||||
|
||||
|
||||
// Get the entered value
|
||||
var value = $(destination + ' input').val();
|
||||
|
||||
|
||||
// Separation with a comma?
|
||||
if(value.match(/^(.+)((,)(\s)?)(\w+)$/))
|
||||
if(value.match(/^(.+)((,)(\s)?)(\w+)$/)) {
|
||||
value = RegExp.$5;
|
||||
|
||||
}
|
||||
|
||||
// Get the result array
|
||||
var entered = self.processBuddy(value);
|
||||
|
||||
|
||||
// Display each result (if any)
|
||||
if(entered && entered.length) {
|
||||
// Set a special class to the search input
|
||||
$(destination + ' input').addClass('suggested');
|
||||
|
||||
// Append each found buddy in the container
|
||||
|
||||
// Append each found buddy in the container
|
||||
var regex = new RegExp('((^)|( ))' + value, 'gi');
|
||||
|
||||
|
||||
// Initialize the code generation
|
||||
var code = '<ul>';
|
||||
|
||||
|
||||
for(var b in entered) {
|
||||
// Get some values from the XID
|
||||
var current = Name.getBuddy(entered[b]).htmlEnc();
|
||||
current = current.replace(regex, '<b>$&</b>');
|
||||
|
||||
|
||||
// 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>';
|
||||
}
|
||||
|
||||
|
||||
// Finish the code generation
|
||||
code += '</ul>';
|
||||
|
||||
|
||||
// Creates the code in the DOM
|
||||
$(destination).append(code);
|
||||
|
||||
|
||||
// Put the hover on the first element
|
||||
$(destination + ' ul li:first').addClass('hovered');
|
||||
|
||||
|
||||
// Hover event, to not to remove this onblur and loose the click event
|
||||
$(destination + ' ul li').hover(function() {
|
||||
$(destination + ' ul li').removeClass('hovered');
|
||||
$(this).addClass('hovered');
|
||||
|
||||
|
||||
// Add a marker for the blur event
|
||||
$(destination + ' ul').attr('mouse-hover', 'true');
|
||||
}, function() {
|
||||
$(this).removeClass('hovered');
|
||||
|
||||
|
||||
// Remove the mouse over marker
|
||||
$(destination + ' ul').removeAttr('mouse-hover');
|
||||
});
|
||||
|
@ -212,52 +214,53 @@ var Search = (function () {
|
|||
try {
|
||||
// Down arrow: 40
|
||||
// Up arrown: 38
|
||||
|
||||
|
||||
// Initialize
|
||||
var code = evt.keyCode;
|
||||
|
||||
|
||||
// Not the key we want here
|
||||
if((code != 40) && (code != 38))
|
||||
if((code != 40) && (code != 38)) {
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// Remove the eventual mouse hover marker
|
||||
$(destination + ' ul').removeAttr('mouse-hover');
|
||||
|
||||
|
||||
// Create the path & get its size
|
||||
var path = destination + ' ul li';
|
||||
var pSize = $(path).size();
|
||||
|
||||
|
||||
// Define the i value
|
||||
var i = 0;
|
||||
|
||||
|
||||
// Switching yet launched
|
||||
if(Common.exists(path + '.hovered')) {
|
||||
var index = $(path).attr('data-hovered');
|
||||
|
||||
if(index)
|
||||
|
||||
if(index) {
|
||||
i = parseInt(index);
|
||||
|
||||
if(code == 40)
|
||||
}
|
||||
|
||||
if(code == 40) {
|
||||
i++;
|
||||
else
|
||||
} else {
|
||||
i--;
|
||||
}
|
||||
} else if(code == 38) {
|
||||
i = pSize - 1;
|
||||
}
|
||||
|
||||
else if(code == 38)
|
||||
i = pSize - 1;
|
||||
|
||||
|
||||
// We must not override the maximum i limit
|
||||
if(i >= pSize)
|
||||
if(i >= pSize) {
|
||||
i = 0;
|
||||
|
||||
// We must not have negative i
|
||||
else if(i < 0)
|
||||
} else if(i < 0) {
|
||||
i = pSize - 1;
|
||||
|
||||
}
|
||||
|
||||
// Modify the list
|
||||
$(path + '.hovered').removeClass('hovered');
|
||||
$(path).eq(i).addClass('hovered');
|
||||
|
||||
|
||||
// Store the i index
|
||||
$(path).attr('data-hovered', i);
|
||||
} catch(e) {
|
||||
|
@ -280,20 +283,22 @@ var Search = (function () {
|
|||
try {
|
||||
// Put a marker
|
||||
self.search_filtered = true;
|
||||
|
||||
|
||||
// Show the buddies that match the search string
|
||||
var rFilter = self.processBuddy(vFilter);
|
||||
|
||||
|
||||
// Hide all the buddies
|
||||
$('#roster .buddy').hide();
|
||||
|
||||
|
||||
// Only show the buddies which match the search
|
||||
if(!Roster.blist_all) {
|
||||
for(var i in rFilter)
|
||||
for(var i in rFilter) {
|
||||
$('#roster .buddy[data-xid="' + escape(rFilter[i]) + '"]:not(.hidden-buddy)').show();
|
||||
}
|
||||
} else {
|
||||
for(var j in rFilter)
|
||||
for(var j in rFilter) {
|
||||
$('#roster .buddy[data-xid="' + escape(rFilter[j]) + '"]').show();
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Search.goFilterBuddy', e);
|
||||
|
@ -312,14 +317,15 @@ var Search = (function () {
|
|||
try {
|
||||
// Remove the marker
|
||||
self.search_filtered = false;
|
||||
|
||||
|
||||
// Show all the buddies
|
||||
$('#roster .buddy').show();
|
||||
|
||||
|
||||
// Only show available buddies
|
||||
if(!Roster.blist_all)
|
||||
if(!Roster.blist_all) {
|
||||
$('#roster .buddy.hidden-buddy').hide();
|
||||
|
||||
}
|
||||
|
||||
// Update the groups
|
||||
Roster.updateGroups();
|
||||
} catch(e) {
|
||||
|
@ -342,26 +348,24 @@ var Search = (function () {
|
|||
var input = $('#roster .filter input');
|
||||
var cancel = $('#roster .filter a');
|
||||
var value = input.val();
|
||||
|
||||
|
||||
// Security: reset all the groups, empty or not, deployed or not
|
||||
$('#roster .one-group, #roster .group-buddies').show();
|
||||
$('#roster .group span').text('-');
|
||||
|
||||
|
||||
// Nothing is entered, or escape pressed
|
||||
if(!value || (keycode == 27)) {
|
||||
if(keycode == 27)
|
||||
if(keycode == 27) {
|
||||
input.val('');
|
||||
|
||||
}
|
||||
|
||||
self.resetFilterBuddy();
|
||||
cancel.hide();
|
||||
}
|
||||
|
||||
// Process the filtering
|
||||
else {
|
||||
} else {
|
||||
cancel.show();
|
||||
self.goFilterBuddy(value);
|
||||
}
|
||||
|
||||
|
||||
// Update the groups
|
||||
Roster.updateGroups();
|
||||
} catch(e) {
|
||||
|
@ -384,25 +388,25 @@ var Search = (function () {
|
|||
var array = [];
|
||||
var i = 0;
|
||||
var nearest = 0;
|
||||
|
||||
|
||||
// Add the stamp values to the array
|
||||
$(element).each(function() {
|
||||
var current_stamp = parseInt($(this).attr('data-stamp'));
|
||||
|
||||
|
||||
// Push it!
|
||||
array.push(current_stamp);
|
||||
});
|
||||
|
||||
|
||||
// Sort the array
|
||||
array.sort();
|
||||
|
||||
|
||||
// Get the nearest stamp value
|
||||
while(stamp > array[i]) {
|
||||
nearest = array[i];
|
||||
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
return nearest;
|
||||
} catch(e) {
|
||||
Console.error('Search.sortElementByStamp', e);
|
||||
|
|
|
@ -20,6 +20,51 @@ var Smileys = (function () {
|
|||
var self = {};
|
||||
|
||||
|
||||
/* Constants */
|
||||
self.emote_list = {
|
||||
'biggrin': ':-D',
|
||||
'devil': ']:->',
|
||||
'coolglasses': '8-)',
|
||||
'tongue': ':-P',
|
||||
'smile': ':-)',
|
||||
'wink': ';-)',
|
||||
'blush': ':-$',
|
||||
'stare': ':-|',
|
||||
'frowning': ':-/',
|
||||
'oh': '=-O',
|
||||
'unhappy': ':-(',
|
||||
'cry': ':\'-(',
|
||||
'angry': ':-@',
|
||||
'puke': ':-!',
|
||||
'hugright': '({)',
|
||||
'hugleft': '(})',
|
||||
'lion': ':3',
|
||||
'pussy': '(@)',
|
||||
'bat': ':-[',
|
||||
'kiss': ':-{}',
|
||||
'heart': '<3',
|
||||
'brheart': '</3',
|
||||
'flower': '@}->--',
|
||||
'brflower': '(W)',
|
||||
'thumbup': '(Y)',
|
||||
'thumbdown': '(N)',
|
||||
'lamp': '(I)',
|
||||
'coffee': '(C)',
|
||||
'drink': '(D)',
|
||||
'beer': '(B)',
|
||||
'boy': '(Z)',
|
||||
'girl': '(X)',
|
||||
'photo': '(P)',
|
||||
'phone': '(T)',
|
||||
'music': '(8)',
|
||||
'cuffs': '(%)',
|
||||
'mail': '(E)',
|
||||
'rainbow': '(R)',
|
||||
'star': '(*)',
|
||||
'moon': '(S)'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Generates the correct HTML code for an emoticon insertion tool
|
||||
* @public
|
||||
|
@ -43,103 +88,21 @@ var Smileys = (function () {
|
|||
* Emoticon links arrays
|
||||
* @public
|
||||
* @param {string} hash
|
||||
* @return {object}
|
||||
* @return {string}
|
||||
*/
|
||||
self.links = function(hash) {
|
||||
|
||||
try {
|
||||
var links = '';
|
||||
|
||||
var sArray = [
|
||||
':-D',
|
||||
']:->',
|
||||
'8-)',
|
||||
':-P',
|
||||
':-)',
|
||||
';-)',
|
||||
':-$',
|
||||
':-|',
|
||||
':-/',
|
||||
'=-O',
|
||||
':-(',
|
||||
':\'-(',
|
||||
':-@',
|
||||
':-!',
|
||||
'({)',
|
||||
'(})',
|
||||
':3',
|
||||
'(@)',
|
||||
':-[',
|
||||
':-{}',
|
||||
'<3',
|
||||
'</3',
|
||||
'@}->--',
|
||||
'(W)',
|
||||
'(Y)',
|
||||
'(N)',
|
||||
'(I)',
|
||||
'(C)',
|
||||
'(D)',
|
||||
'(B)',
|
||||
'(Z)',
|
||||
'(X)',
|
||||
'(P)',
|
||||
'(T)',
|
||||
'(8)',
|
||||
'(%)',
|
||||
'(E)',
|
||||
'(R)',
|
||||
'(*)',
|
||||
'(S)'
|
||||
];
|
||||
|
||||
var cArray = [
|
||||
'biggrin',
|
||||
'devil',
|
||||
'coolglasses',
|
||||
'tongue',
|
||||
'smile',
|
||||
'wink',
|
||||
'blush',
|
||||
'stare',
|
||||
'frowning',
|
||||
'oh',
|
||||
'unhappy',
|
||||
'cry',
|
||||
'angry',
|
||||
'puke',
|
||||
'hugright',
|
||||
'hugleft',
|
||||
'lion',
|
||||
'pussy',
|
||||
'bat',
|
||||
'kiss',
|
||||
'heart',
|
||||
'brheart',
|
||||
'flower',
|
||||
'brflower',
|
||||
'thumbup',
|
||||
'thumbdown',
|
||||
'lamp',
|
||||
'coffee',
|
||||
'drink',
|
||||
'beer',
|
||||
'boy',
|
||||
'girl',
|
||||
'photo',
|
||||
'phone',
|
||||
'music',
|
||||
'cuffs',
|
||||
'mail',
|
||||
'rainbow',
|
||||
'star',
|
||||
'moon'
|
||||
];
|
||||
|
||||
for(var i in sArray) {
|
||||
links += self.emoteLink(sArray[i], cArray[i], hash);
|
||||
|
||||
for(var cur_emote in self.emote_list) {
|
||||
links += self.emoteLink(
|
||||
self.emote_list[cur_emote],
|
||||
cur_emote,
|
||||
hash
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
return links;
|
||||
} catch(e) {
|
||||
Console.error('Smileys.links', e);
|
||||
|
|
|
@ -33,10 +33,10 @@ var Storage = (function () {
|
|||
try {
|
||||
var iq = new JSJaCIQ();
|
||||
iq.setType('get');
|
||||
|
||||
|
||||
var iqQuery = iq.setQuery(NS_PRIVATE);
|
||||
iqQuery.appendChild(iq.buildNode('storage', {'xmlns': type}));
|
||||
|
||||
|
||||
con.send(iq, self.handle);
|
||||
} catch(e) {
|
||||
Console.error('Storage.get', e);
|
||||
|
@ -56,111 +56,126 @@ var Storage = (function () {
|
|||
try {
|
||||
var handleXML = iq.getQuery();
|
||||
var handleFrom = Common.fullXID(Common.getStanzaFrom(iq));
|
||||
|
||||
|
||||
// Define some vars
|
||||
var options = $(handleXML).find('storage[xmlns="' + NS_OPTIONS + '"]');
|
||||
var inbox = $(handleXML).find('storage[xmlns="' + NS_INBOX + '"]');
|
||||
var bookmarks = $(handleXML).find('storage[xmlns="' + NS_BOOKMARKS + '"]');
|
||||
var rosternotes = $(handleXML).find('storage[xmlns="' + NS_ROSTERNOTES + '"]');
|
||||
|
||||
|
||||
// No options and node not yet configured
|
||||
if(options.size() && !options.find('option').size() && (iq.getType() != 'error')) {
|
||||
Welcome.open();
|
||||
}
|
||||
|
||||
|
||||
// Parse the options xml
|
||||
options.find('option').each(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// We retrieve the informations
|
||||
var type = $(this).attr('type');
|
||||
var value = $(this).text();
|
||||
|
||||
var type = this_sel.attr('type');
|
||||
var value = this_sel.text();
|
||||
|
||||
// We display the storage
|
||||
DataStore.setDB(Connection.desktop_hash, 'options', type, value);
|
||||
|
||||
|
||||
// If this is the buddy list show status
|
||||
if((type == 'roster-showall') && (value == '1'))
|
||||
if((type == 'roster-showall') && (value == '1')) {
|
||||
Interface.showAllBuddies('storage');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Parse the inbox xml
|
||||
inbox.find('message').each(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
Inbox.storeMessage(
|
||||
$(this).attr('from'),
|
||||
$(this).attr('subject'),
|
||||
$(this).text(),
|
||||
$(this).attr('status'),
|
||||
$(this).attr('id'),
|
||||
$(this).attr('date'),
|
||||
[
|
||||
$(this).attr('file_title'),
|
||||
$(this).attr('file_href'),
|
||||
$(this).attr('file_type'),
|
||||
$(this).attr('file_length')
|
||||
]
|
||||
);
|
||||
this_sel.attr('from'),
|
||||
this_sel.attr('subject'),
|
||||
this_sel.text(),
|
||||
this_sel.attr('status'),
|
||||
this_sel.attr('id'),
|
||||
this_sel.attr('date'),
|
||||
[
|
||||
this_sel.attr('file_title'),
|
||||
this_sel.attr('file_href'),
|
||||
this_sel.attr('file_type'),
|
||||
this_sel.attr('file_length')
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
// Parse the bookmarks xml
|
||||
bookmarks.find('conference').each(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// We retrieve the informations
|
||||
var xid = $(this).attr('jid');
|
||||
var name = $(this).attr('name');
|
||||
var autojoin = $(this).attr('autojoin');
|
||||
var password = $(this).find('password').text();
|
||||
var nick = $(this).find('nick').text();
|
||||
|
||||
var xid = this_sel.attr('jid');
|
||||
var name = this_sel.attr('name');
|
||||
var autojoin = this_sel.attr('autojoin');
|
||||
var password = this_sel.find('password').text();
|
||||
var nick = this_sel.find('nick').text();
|
||||
|
||||
// Filter autojoin (compatibility)
|
||||
autojoin = ((autojoin == 'true') || (autojoin == '1')) ? 'true' : 'false';
|
||||
|
||||
// We display the storage
|
||||
Favorites.display(xid, name, nick, autojoin, password);
|
||||
|
||||
|
||||
// Join the chat if autojoin is enabled
|
||||
if(autojoin == 'true')
|
||||
if(autojoin == 'true') {
|
||||
Chat.checkCreate(xid, 'groupchat', nick, password, name);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Parse the roster notes xml
|
||||
rosternotes.find('note').each(function() {
|
||||
DataStore.setDB(Connection.desktop_hash, 'rosternotes', $(this).attr('jid'), $(this).text());
|
||||
var this_sel = $(this);
|
||||
|
||||
DataStore.setDB(
|
||||
Connection.desktop_hash,
|
||||
'rosternotes',
|
||||
this_sel.attr('jid'),
|
||||
this_sel.text()
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
// Options received
|
||||
if(options.size()) {
|
||||
Console.log('Options received.');
|
||||
|
||||
|
||||
// Now, get the inbox
|
||||
self.get(NS_INBOX);
|
||||
|
||||
|
||||
// Geolocate the user
|
||||
PEP.geolocate();
|
||||
|
||||
|
||||
$('.options-hidable').show();
|
||||
}
|
||||
|
||||
|
||||
// Inbox received
|
||||
else if(inbox.size()) {
|
||||
Console.log('Inbox received.');
|
||||
|
||||
|
||||
// Send the first presence!
|
||||
Presence.sendFirst(DataStore.getDB(Connection.desktop_hash, 'checksum', 1));
|
||||
|
||||
|
||||
// Check we have new messages (play a sound if any unread messages)
|
||||
if(Inbox.checkMessages()) {
|
||||
Audio.play('notification');
|
||||
}
|
||||
|
||||
|
||||
$('.inbox-hidable').show();
|
||||
}
|
||||
|
||||
|
||||
// Bookmarks received
|
||||
else if(bookmarks.size()) {
|
||||
// Join the groupchats the admin defined (if any)
|
||||
Groupchat.joinConf();
|
||||
|
||||
|
||||
Console.log('Bookmarks received.');
|
||||
}
|
||||
|
||||
|
||||
// Roster notes received (for logger)
|
||||
else if(rosternotes.size()) {
|
||||
Console.log('Roster notes received.');
|
||||
|
|
|
@ -29,17 +29,21 @@ var System = (function () {
|
|||
|
||||
try {
|
||||
var url = window.location.href;
|
||||
|
||||
|
||||
// If the URL has variables, remove them
|
||||
if(url.indexOf('?') != -1)
|
||||
if(url.indexOf('?') != -1) {
|
||||
url = url.split('?')[0];
|
||||
if(url.indexOf('#') != -1)
|
||||
}
|
||||
|
||||
if(url.indexOf('#') != -1) {
|
||||
url = url.split('#')[0];
|
||||
|
||||
}
|
||||
|
||||
// No "/" at the end
|
||||
if(!url.match(/(.+)\/$/))
|
||||
if(!url.match(/(.+)\/$/)) {
|
||||
url += '/';
|
||||
|
||||
}
|
||||
|
||||
return url;
|
||||
} catch(e) {
|
||||
Console.error('System.location', e);
|
||||
|
|
|
@ -51,236 +51,241 @@ var Talk = (function () {
|
|||
|
||||
try {
|
||||
// Talkpage exists?
|
||||
if(Common.exists('#talk'))
|
||||
if(Common.exists('#talk')) {
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
// Anonymous detector
|
||||
var anonymous = Utils.isAnonymous();
|
||||
|
||||
|
||||
// Generate the HTML code
|
||||
var html =
|
||||
'<div id="talk" class="removable">' +
|
||||
'<div id="top-content">' +
|
||||
'<div class="tools tools-logo talk-images"></div>' +
|
||||
|
||||
var html =
|
||||
'<div id="talk" class="removable">' +
|
||||
'<div id="top-content">' +
|
||||
'<div class="tools tools-logo talk-images"></div>' +
|
||||
|
||||
'<div class="tools tools-all">';
|
||||
|
||||
if(!anonymous) html +=
|
||||
'<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 Options.open();" class="options-hidable">' + Common._e("Options") + '</a>' +
|
||||
|
||||
if(!anonymous) html +=
|
||||
'<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 Options.open();" class="options-hidable">' + Common._e("Options") + '</a>' +
|
||||
'<a href="#" onclick="return Connection.normalQuit();" class="quit">' + Common._e("Disconnect") + '</a>';
|
||||
|
||||
|
||||
else html +=
|
||||
'<a href="./">' + Common._e("Disconnect") + '</a>';
|
||||
|
||||
|
||||
html +=
|
||||
'</div>';
|
||||
|
||||
if(!anonymous && document.createElement('audio').canPlayType) html +=
|
||||
'<div class="tools-all ibubble">' +
|
||||
'<div class="tools music talk-images" onclick="return Music.open();"></div>' +
|
||||
|
||||
'<div class="music-content tools-content bubble hidable">' +
|
||||
'<div class="tools-content-subarrow talk-images"></div>' +
|
||||
|
||||
'<div class="tools-content-subitem">' +
|
||||
'<div class="player">' +
|
||||
'<a href="#" class="stop talk-images" onclick="return Music.action(\'stop\');"></a>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="list">' +
|
||||
'<p class="no-results">' + Common._e("No result!") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="search">' +
|
||||
'<input type="text" />' +
|
||||
'</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>' +
|
||||
|
||||
if(!anonymous && document.createElement('audio').canPlayType) html +=
|
||||
'<div class="tools-all ibubble">' +
|
||||
'<div class="tools music talk-images" onclick="return Music.open();"></div>' +
|
||||
|
||||
'<div class="music-content tools-content bubble hidable">' +
|
||||
'<div class="tools-content-subarrow talk-images"></div>' +
|
||||
|
||||
'<div class="tools-content-subitem">' +
|
||||
'<div class="player">' +
|
||||
'<a href="#" class="stop talk-images" onclick="return Music.action(\'stop\');"></a>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="list">' +
|
||||
'<p class="no-results">' + Common._e("No result!") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="search">' +
|
||||
'<input type="text" />' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
|
||||
if(!anonymous) html +=
|
||||
'<div class="tools-all">' +
|
||||
'<div class="tools jingle talk-images" onclick="return Jingle.open();">' +
|
||||
'<span class="streaming-items">' +
|
||||
'<span class="counter" data-default="00:00:00">00:00:00</span>' +
|
||||
'<a class="stop" href="#" onclick="return Jingle.stop();">' + Common._e("Stop") + '</a>' +
|
||||
'</span>' +
|
||||
'</div>' +
|
||||
if(!anonymous) html +=
|
||||
'<div class="tools-all ibubble">' +
|
||||
'<div class="tools notifications talk-images" onclick="return Bubble.show(\'.notifications-content\');"></div>' +
|
||||
|
||||
'<div class="jingle-content tools-content">' +
|
||||
'<div class="tools-content-subarrow talk-images"></div>' +
|
||||
|
||||
'<div class="tools-content-subitem"></div>' +
|
||||
'</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>';
|
||||
|
||||
|
||||
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 +=
|
||||
'</div>' +
|
||||
|
||||
'<div id="main-content">' +
|
||||
'</div>' +
|
||||
|
||||
'<div id="main-content">' +
|
||||
'<div id="left-content">';
|
||||
if(!anonymous) html +=
|
||||
'<div id="roster">' +
|
||||
'<div class="content"></div>' +
|
||||
|
||||
'<div class="filter">' +
|
||||
'<input type="text" placeholder="' + Common._e("Filter") + '" />' +
|
||||
'<a href="#">x</a>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="foot ibubble">' +
|
||||
'<div class="roster-add roster-icon">' +
|
||||
'<a href="#" class="add talk-images" title="' + Common._e("Add a friend") + '"></a>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="roster-join roster-icon">' +
|
||||
'<a href="#" class="join talk-images" title="' + Common._e("Join a chat") + '"></a>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="roster-groupchat roster-icon">' +
|
||||
'<a href="#" class="groupchat talk-images" title="' + Common._e("Your groupchats") + '"></a>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="roster-more roster-icon">' +
|
||||
'<a href="#" class="more talk-images" title="' + Common._e("More stuff") + '"></a>' +
|
||||
'</div>' +
|
||||
|
||||
'<div style="clear: both;"></div>' +
|
||||
'</div>' +
|
||||
if(!anonymous) html +=
|
||||
'<div id="roster">' +
|
||||
'<div class="content"></div>' +
|
||||
|
||||
'<div class="filter">' +
|
||||
'<input type="text" placeholder="' + Common._e("Filter") + '" />' +
|
||||
'<a href="#">x</a>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="foot ibubble">' +
|
||||
'<div class="roster-add roster-icon">' +
|
||||
'<a href="#" class="add talk-images" title="' + Common._e("Add a friend") + '"></a>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="roster-join roster-icon">' +
|
||||
'<a href="#" class="join talk-images" title="' + Common._e("Join a chat") + '"></a>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="roster-groupchat roster-icon">' +
|
||||
'<a href="#" class="groupchat talk-images" title="' + Common._e("Your groupchats") + '"></a>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="roster-muji roster-icon muji-hidable">' +
|
||||
'<a href="#" class="muji talk-images" title="' + Common._e("Audio/video conference") + '"></a>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="roster-more roster-icon">' +
|
||||
'<a href="#" class="more talk-images" title="' + Common._e("More stuff") + '"></a>' +
|
||||
'</div>' +
|
||||
|
||||
'<div style="clear: both;"></div>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
|
||||
|
||||
html +=
|
||||
'<div id="my-infos">' +
|
||||
'<div class="content">' +
|
||||
'<div class="element f-presence ibubble">' +
|
||||
'<a href="#" class="icon picker disabled" data-value="available">' +
|
||||
'<span class="talk-images"></span>' +
|
||||
'</a>' +
|
||||
|
||||
'<input id="presence-status" type="text" placeholder="' + Common._e("Status") + '" disabled="" />' +
|
||||
'<div id="my-infos">' +
|
||||
'<div class="content">' +
|
||||
'<div class="element f-presence ibubble">' +
|
||||
'<a href="#" class="icon picker disabled" data-value="available">' +
|
||||
'<span class="talk-images"></span>' +
|
||||
'</a>' +
|
||||
|
||||
'<input id="presence-status" type="text" placeholder="' + Common._e("Status") + '" disabled="" />' +
|
||||
'</div>';
|
||||
|
||||
if(!anonymous) html +=
|
||||
'<div class="element f-mood pep-hidable ibubble">' +
|
||||
'<a href="#" class="icon picker" data-value="happy">' +
|
||||
'<span class="talk-images"></span>' +
|
||||
'</a>' +
|
||||
|
||||
'<input id="mood-text" type="text" placeholder="' + Common._e("Mood") + '" />' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="element f-activity pep-hidable ibubble">' +
|
||||
'<a href="#" class="icon picker" data-value="exercising">' +
|
||||
'<span class="talk-images activity-exercising"></span>' +
|
||||
'</a>' +
|
||||
|
||||
'<input id="activity-text" type="text" placeholder="' + Common._e("Activity") + '" />' +
|
||||
|
||||
if(!anonymous) html +=
|
||||
'<div class="element f-mood pep-hidable ibubble">' +
|
||||
'<a href="#" class="icon picker" data-value="happy">' +
|
||||
'<span class="talk-images"></span>' +
|
||||
'</a>' +
|
||||
|
||||
'<input id="mood-text" type="text" placeholder="' + Common._e("Mood") + '" />' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="element f-activity pep-hidable ibubble">' +
|
||||
'<a href="#" class="icon picker" data-value="exercising">' +
|
||||
'<span class="talk-images activity-exercising"></span>' +
|
||||
'</a>' +
|
||||
|
||||
'<input id="activity-text" type="text" placeholder="' + Common._e("Activity") + '" />' +
|
||||
'</div>';
|
||||
|
||||
|
||||
html +=
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div id="right-content">' +
|
||||
'<div id="page-switch">' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div id="right-content">' +
|
||||
'<div id="page-switch">' +
|
||||
'<div class="chans">';
|
||||
if(!anonymous) html +=
|
||||
'<div class="channel switcher activechan" onclick="return Interface.switchChan(\'channel\');">' +
|
||||
'<div class="icon talk-images"></div>' +
|
||||
|
||||
'<div class="name">' + Common._e("Channel") + '</div>' +
|
||||
if(!anonymous) html +=
|
||||
'<div class="channel switcher activechan" onclick="return Interface.switchChan(\'channel\');">' +
|
||||
'<div class="icon talk-images"></div>' +
|
||||
|
||||
'<div class="name">' + Common._e("Channel") + '</div>' +
|
||||
'</div>';
|
||||
|
||||
html +=
|
||||
'</div>';
|
||||
|
||||
|
||||
if(anonymous) html +=
|
||||
'<div class="join ibubble">' +
|
||||
'<div class="join-button talk-images" onclick="return Interface.loadJoinGroupchat();" title="' + Common._e("Join groupchat") + '"></div>' +
|
||||
'<div class="join ibubble">' +
|
||||
'<div class="join-button talk-images" onclick="return Interface.loadJoinGroupchat();" title="' + Common._e("Join groupchat") + '"></div>' +
|
||||
'</div>';
|
||||
|
||||
html +=
|
||||
'<div class="more ibubble">' +
|
||||
'<div class="more-button talk-images" onclick="return Interface.loadChatSwitch();" title="' + Common._e("All tabs") + '"></div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="more ibubble">' +
|
||||
'<div class="more-button talk-images" onclick="return Interface.loadChatSwitch();" title="' + Common._e("All tabs") + '"></div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div id="page-engine">';
|
||||
if(!anonymous) html +=
|
||||
'<div id="channel" class="page-engine-chan" style="display: block;">' +
|
||||
'<div class="top mixed ' + hex_md5(Common.getXID()) + '">' +
|
||||
'<div class="avatar-container">' +
|
||||
'<img class="avatar" src="' + './images/others/default-avatar.png' + '" alt="" />' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="update">' +
|
||||
'<p>' + Common._e("What\'s up with you?") + '</p>' +
|
||||
|
||||
'<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="" />' +
|
||||
'</div>' +
|
||||
|
||||
'<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>' +
|
||||
|
||||
'<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-subitem">' +
|
||||
'<p class="attach-p">' + Common._e("Attach a file") + '</p>' +
|
||||
Interface.generateFileShare() +
|
||||
'</div>' +
|
||||
'</form>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="content mixed"></div>' +
|
||||
|
||||
'<div class="footer">' +
|
||||
'<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="fetch wait-small">' + Common._e("Fetching the social channel...") + '</div>' +
|
||||
'</div>' +
|
||||
if(!anonymous) html +=
|
||||
'<div id="channel" class="page-engine-chan" style="display: block;">' +
|
||||
'<div class="top mixed ' + hex_md5(Common.getXID()) + '">' +
|
||||
'<div class="avatar-container">' +
|
||||
'<img class="avatar" src="' + './images/others/default-avatar.png' + '" alt="" />' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="update">' +
|
||||
'<p>' + Common._e("What\'s up with you?") + '</p>' +
|
||||
|
||||
'<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="" />' +
|
||||
'</div>' +
|
||||
|
||||
'<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>' +
|
||||
|
||||
'<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-subitem">' +
|
||||
'<p class="attach-p">' + Common._e("Attach a file") + '</p>' +
|
||||
Interface.generateFileShare() +
|
||||
'</div>' +
|
||||
'</form>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="content mixed"></div>' +
|
||||
|
||||
'<div class="footer">' +
|
||||
'<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="fetch wait-small">' + Common._e("Fetching the social channel...") + '</div>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
|
||||
|
||||
html +=
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
|
||||
|
||||
// Create the HTML code
|
||||
$('body').prepend(html);
|
||||
|
||||
|
||||
// Adapt the roster size
|
||||
Roster.adapt();
|
||||
|
||||
|
||||
// Create JS events
|
||||
self.events();
|
||||
|
||||
|
||||
// Start the auto idle functions
|
||||
Presence.liveIdle();
|
||||
|
||||
|
||||
return true;
|
||||
} catch(e) {
|
||||
Console.error('Talk.create', e);
|
||||
|
@ -299,25 +304,25 @@ var Talk = (function () {
|
|||
try {
|
||||
// Reset our database
|
||||
DataStore.resetDB();
|
||||
|
||||
|
||||
// Reset some vars
|
||||
STANZA_ID = 1;
|
||||
Roster.blist_all = false;
|
||||
Presence.first_sent = false;
|
||||
Search.search_filtered = false;
|
||||
Avatar.pending = [];
|
||||
JOIN_SUGGEST = [];
|
||||
|
||||
Groupchat.join_suggest = [];
|
||||
|
||||
// Kill all timers, exept the board ones
|
||||
$('*:not(#board .one-board)').stopTime();
|
||||
|
||||
|
||||
// Kill the auto idle functions
|
||||
Presence.dieIdle();
|
||||
|
||||
|
||||
// We renitalise the html markup as its initiale look
|
||||
$('.removable').remove();
|
||||
Interface.title('home');
|
||||
|
||||
|
||||
// Finally we show the homepage
|
||||
$('#home').show();
|
||||
} catch(e) {
|
||||
|
|
|
@ -35,27 +35,28 @@ var Tooltip = (function () {
|
|||
var path = '#' + hash;
|
||||
var path_tooltip = path + ' .chat-tools-' + type;
|
||||
var path_bubble = path_tooltip + ' .bubble-' + type;
|
||||
|
||||
|
||||
// Yet exists?
|
||||
if(Common.exists(path_bubble))
|
||||
if(Common.exists(path_bubble)) {
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
// Generates special tooltip HTML code
|
||||
var title = '';
|
||||
var content = '';
|
||||
|
||||
|
||||
switch(type) {
|
||||
// Smileys
|
||||
case 'smileys':
|
||||
title = Common._e("Smiley insertion");
|
||||
content = Smileys.links(hash);
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
// Style
|
||||
case 'style':
|
||||
title = Common._e("Change style");
|
||||
|
||||
|
||||
// Generate fonts list
|
||||
var fonts = {
|
||||
'arial': 'Arial, Helvetica, sans-serif',
|
||||
|
@ -80,106 +81,106 @@ var Tooltip = (function () {
|
|||
'webdings': 'Webdings, sans-serif',
|
||||
'wingdings': 'Wingdings, \'Zapf Dingbats\', sans-serif'
|
||||
};
|
||||
|
||||
|
||||
var fonts_html = '<div class="font-list">';
|
||||
|
||||
|
||||
// No fonts
|
||||
fonts_html += '<a href="#">' + Common._e("None") + '</a>';
|
||||
|
||||
|
||||
// Available fonts
|
||||
$.each(fonts, function(id_name, full_name) {
|
||||
// Generate short name
|
||||
var short_name = full_name;
|
||||
|
||||
|
||||
if(short_name.match(/,/)) {
|
||||
var name_split = short_name.split(',');
|
||||
short_name = $.trim(name_split[0]);
|
||||
}
|
||||
|
||||
|
||||
short_name = short_name.replace(/([^a-z0-9\s]+)/gi, '');
|
||||
|
||||
|
||||
// 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 += '</div>';
|
||||
|
||||
content =
|
||||
'<label class="font">' +
|
||||
'<div class="font-icon talk-images"></div>' +
|
||||
|
||||
'<div class="fontsize-change">' +
|
||||
'<a class="fontsize-current" href="#">12</a>' +
|
||||
'<div class="fontsize-list">' +
|
||||
'<a href="#" class="reset talk-images"></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="14" style="font-size: 14px;">14</a>' +
|
||||
'<a href="#" data-value="16" style="font-size: 16px;">16</a>' +
|
||||
'<a href="#" data-value="18" style="font-size: 18px;">18</a>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="font-change">' +
|
||||
'<a class="font-current" href="#">' + Common._e("None") + '</a>' +
|
||||
fonts_html +
|
||||
'</div>' +
|
||||
'</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="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: #e5860c;" data-color="e5860c"></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: #0ba9a0;" data-color="0ba9a0"></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>' +
|
||||
'<div class="color-picker">' +
|
||||
'<a href="#" class="color-more talk-images"></a>' +
|
||||
'<div class="color-hex">' +
|
||||
'<span class="hex-begin">#</span>' +
|
||||
'<input class="hex-value" type="text" maxlength="6" placeholder="e1e1e1" />' +
|
||||
'</div>' +
|
||||
|
||||
content =
|
||||
'<label class="font">' +
|
||||
'<div class="font-icon talk-images"></div>' +
|
||||
|
||||
'<div class="fontsize-change">' +
|
||||
'<a class="fontsize-current" href="#">12</a>' +
|
||||
'<div class="fontsize-list">' +
|
||||
'<a href="#" class="reset talk-images"></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="14" style="font-size: 14px;">14</a>' +
|
||||
'<a href="#" data-value="16" style="font-size: 16px;">16</a>' +
|
||||
'<a href="#" data-value="18" style="font-size: 18px;">18</a>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="font-change">' +
|
||||
'<a class="font-current" href="#">' + Common._e("None") + '</a>' +
|
||||
fonts_html +
|
||||
'</div>' +
|
||||
'</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="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: #e5860c;" data-color="e5860c"></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: #0ba9a0;" data-color="0ba9a0"></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>' +
|
||||
'<div class="color-picker">' +
|
||||
'<a href="#" class="color-more talk-images"></a>' +
|
||||
'<div class="color-hex">' +
|
||||
'<span class="hex-begin">#</span>' +
|
||||
'<input class="hex-value" type="text" maxlength="6" placeholder="e1e1e1" />' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
// File send
|
||||
case '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 += '<form id="oob-upload" action="./server/send.php" method="post" enctype="multipart/form-data">' + Interface.generateFileShare() + '</form>';
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
// Chat log
|
||||
case 'save':
|
||||
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>';
|
||||
|
||||
|
||||
// Possible to generate any log?
|
||||
if($(path + ' .one-line').size())
|
||||
content += '<a href="#" class="tooltip-actionlog">' + Common._e("Generate file!") + '</a>';
|
||||
else
|
||||
content += '<span class="tooltip-nolog">' + Common._e("This chat is empty!") + '</span>';
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Generates general tooltip HTML code
|
||||
var html =
|
||||
'<div class="tooltip bubble-' + type + '">' +
|
||||
'<div class="tooltip-subitem">' +
|
||||
'<p class="tooltip-top">' + title + '</p>' +
|
||||
content +
|
||||
'</div>' +
|
||||
|
||||
'<div class="tooltip-subarrow talk-images"></div>' +
|
||||
var html =
|
||||
'<div class="tooltip bubble-' + type + '">' +
|
||||
'<div class="tooltip-subitem">' +
|
||||
'<p class="tooltip-top">' + title + '</p>' +
|
||||
content +
|
||||
'</div>' +
|
||||
|
||||
'<div class="tooltip-subarrow talk-images"></div>' +
|
||||
'</div>';
|
||||
|
||||
|
||||
// Append the HTML code
|
||||
$(path_tooltip).append(html);
|
||||
|
||||
|
||||
// Special events
|
||||
switch(type) {
|
||||
// Smileys
|
||||
|
@ -188,9 +189,9 @@ var Tooltip = (function () {
|
|||
$(path_tooltip + ' a.emoticon').click(function() {
|
||||
return Interface.insertSmiley($(this).attr('data-smiley'), hash);
|
||||
});
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
// Style
|
||||
case 'style':
|
||||
// Paths to items
|
||||
|
@ -207,198 +208,219 @@ var Tooltip = (function () {
|
|||
var color = bubble_style + ' div.color-picker';
|
||||
var color_more = color + ' a.color-more';
|
||||
var color_hex = color + ' div.color-hex';
|
||||
|
||||
|
||||
// Click event on style bubble
|
||||
$(bubble_style).click(function() {
|
||||
// Hide font selector if opened
|
||||
if($(font_list).is(':visible'))
|
||||
if($(font_list).is(':visible')) {
|
||||
$(font_current).click();
|
||||
|
||||
}
|
||||
|
||||
// Hide font-size selector if opened
|
||||
if($(fontsize_list).is(':visible'))
|
||||
if($(fontsize_list).is(':visible')) {
|
||||
$(fontsize_current).click();
|
||||
|
||||
}
|
||||
|
||||
// Hide color selector if opened
|
||||
if($(color_hex).is(':visible'))
|
||||
if($(color_hex).is(':visible')) {
|
||||
$(color_more).click();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Click event on font picker
|
||||
$(font_current).click(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// The clicked color is yet selected
|
||||
if($(font_list).is(':visible'))
|
||||
$(this).parent().removeClass('listed');
|
||||
else
|
||||
$(this).parent().addClass('listed');
|
||||
|
||||
if($(font_list).is(':visible')) {
|
||||
this_sel.parent().removeClass('listed');
|
||||
} else {
|
||||
this_sel.parent().addClass('listed');
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
// Click event on a new font in the picker
|
||||
$(font_select).click(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// No font selected
|
||||
if(!$(this).attr('data-value')) {
|
||||
if(!this_sel.attr('data-value')) {
|
||||
$(font_current).removeAttr('data-font')
|
||||
.removeAttr('data-value')
|
||||
.text(Common._e("None"));
|
||||
|
||||
|
||||
$(message_area).removeAttr('data-font');
|
||||
} else {
|
||||
$(font_current).attr('data-font', this_sel.attr('data-font'))
|
||||
.attr('data-value', this_sel.attr('data-value'))
|
||||
.text($(font_list).find('a[data-value="' + this_sel.attr('data-value') + '"]').text());
|
||||
|
||||
$(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;
|
||||
});
|
||||
|
||||
|
||||
// Click event on font-size picker
|
||||
$(fontsize_current).click(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// The clicked color is yet selected
|
||||
if($(fontsize_list).is(':visible'))
|
||||
$(this).parent().removeClass('listed');
|
||||
else
|
||||
$(this).parent().addClass('listed');
|
||||
|
||||
if($(fontsize_list).is(':visible')) {
|
||||
this_sel.parent().removeClass('listed');
|
||||
} else {
|
||||
this_sel.parent().addClass('listed');
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
// Click event on a new font-size in the picker
|
||||
$(fontsize_select).click(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// No font-size selected
|
||||
if(!$(this).attr('data-value')) {
|
||||
if(!this_sel.attr('data-value')) {
|
||||
$(fontsize_current).removeAttr('data-value').text(Common._e("16"));
|
||||
$(message_area).removeAttr('data-fontsize');
|
||||
}
|
||||
|
||||
|
||||
// A font-size is defined
|
||||
else {
|
||||
$(fontsize_current).attr('data-value', $(this).attr('data-value'))
|
||||
.text($(this).attr('data-value'));
|
||||
$(message_area).attr('data-fontsize', $(this).attr('data-value'));
|
||||
$(fontsize_current).attr('data-value', this_sel.attr('data-value'))
|
||||
.text(this_sel.attr('data-value'));
|
||||
$(message_area).attr('data-fontsize', this_sel.attr('data-value'));
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
// Click event on color picker
|
||||
$(colors).click(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// Reset the manual picker
|
||||
$(color_hex).find('input').val('');
|
||||
|
||||
|
||||
// The clicked color is yet selected
|
||||
if($(this).hasClass('selected')) {
|
||||
if(this_sel.hasClass('selected')) {
|
||||
$(message_area).removeAttr('data-color');
|
||||
$(this).removeClass('selected');
|
||||
this_sel.removeClass('selected');
|
||||
}
|
||||
|
||||
|
||||
else {
|
||||
$(message_area).attr('data-color', $(this).attr('data-color'));
|
||||
$(message_area).attr('data-color', this_sel.attr('data-color'));
|
||||
$(colors).removeClass('selected');
|
||||
$(this).addClass('selected');
|
||||
this_sel.addClass('selected');
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
// Click event on color picker
|
||||
$(color_more).click(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// The clicked color is yet selected
|
||||
if($(color_hex).is(':visible'))
|
||||
$(this).parent().removeClass('opened');
|
||||
|
||||
else {
|
||||
$(this).parent().addClass('opened');
|
||||
|
||||
if($(color_hex).is(':visible')) {
|
||||
this_sel.parent().removeClass('opened');
|
||||
} else {
|
||||
this_sel.parent().addClass('opened');
|
||||
|
||||
// Focus
|
||||
$(document).oneTime(10, function() {
|
||||
$(color_hex).find('input').focus();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
// Click event on color hex
|
||||
$(color_hex).click(function() {
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
// Keyup event on color picker
|
||||
$(color_hex).find('input').keyup(function(e) {
|
||||
var this_sel = $(this);
|
||||
|
||||
// Submit
|
||||
if(e.keyCode == 13) {
|
||||
if($(color_hex).is(':visible')) {
|
||||
$(color_more).click();
|
||||
|
||||
|
||||
// Focus again on the message textarea
|
||||
$(document).oneTime(10, function() {
|
||||
$(message_area).focus();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Reset current color
|
||||
$(message_area).removeAttr('data-color');
|
||||
$(colors).removeClass('selected');
|
||||
|
||||
|
||||
// Change value
|
||||
var new_value = $(this).val().replace(/([^a-z0-9]+)/gi, '');
|
||||
$(this).val(new_value);
|
||||
|
||||
if(new_value)
|
||||
var new_value = this_sel.val().replace(/([^a-z0-9]+)/gi, '');
|
||||
this_sel.val(new_value);
|
||||
|
||||
if(new_value) {
|
||||
$(message_area).attr('data-color', new_value);
|
||||
|
||||
}
|
||||
|
||||
// Regenerate style
|
||||
var style = Message.generateStyle(hash);
|
||||
|
||||
|
||||
// Any style to apply?
|
||||
if(style)
|
||||
if(style) {
|
||||
$(message_area).attr('style', style);
|
||||
else
|
||||
} else {
|
||||
$(message_area).removeAttr('style');
|
||||
}
|
||||
}).placeholder();
|
||||
|
||||
|
||||
// Change event on text style checkboxes
|
||||
$(style).change(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// Get current type
|
||||
var style_data = 'data-' + $(this).attr('class');
|
||||
|
||||
var style_data = 'data-' + this_sel.attr('class');
|
||||
|
||||
// Checked checkbox?
|
||||
if($(this).filter(':checked').size())
|
||||
if(this_sel.filter(':checked').size()) {
|
||||
$(message_area).attr(style_data, true);
|
||||
else
|
||||
} else {
|
||||
$(message_area).removeAttr(style_data);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Update the textarea style when it is changed
|
||||
$(style + ', ' + colors + ', ' + font_select + ', ' + fontsize_select).click(function() {
|
||||
var style = Message.generateStyle(hash);
|
||||
|
||||
|
||||
// Any style to apply?
|
||||
if(style)
|
||||
if(style) {
|
||||
$(message_area).attr('style', style);
|
||||
else
|
||||
} else {
|
||||
$(message_area).removeAttr('style');
|
||||
|
||||
}
|
||||
|
||||
// Focus again on the message textarea
|
||||
$(document).oneTime(10, function() {
|
||||
$(message_area).focus();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// Load current style
|
||||
self.loadStyleSelector(hash);
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
// File send
|
||||
case 'file':
|
||||
// File upload vars
|
||||
|
@ -407,34 +429,41 @@ var Tooltip = (function () {
|
|||
beforeSubmit: OOB.waitUpload,
|
||||
success: OOB.handleUpload
|
||||
};
|
||||
|
||||
|
||||
// Upload form submit event
|
||||
$(path_tooltip + ' #oob-upload').submit(function() {
|
||||
if($(path_tooltip + ' #oob-upload input[type="file"]').val())
|
||||
$(this).ajaxSubmit(oob_upload_options);
|
||||
|
||||
var this_sel = $(this);
|
||||
|
||||
if($(path_tooltip + ' #oob-upload input[type="file"]').val()) {
|
||||
this_sel.ajaxSubmit(oob_upload_options);
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
// Upload input change event
|
||||
$(path_tooltip + ' #oob-upload input[type="file"]').change(function() {
|
||||
if($(this).val())
|
||||
var this_sel = $(this);
|
||||
|
||||
if(this_sel.val()) {
|
||||
$(path_tooltip + ' #oob-upload').ajaxSubmit(oob_upload_options);
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
// Input click event
|
||||
$(path_tooltip + ' #oob-upload input[type="file"], ' + path_tooltip + ' #oob-upload input[type="submit"]').click(function() {
|
||||
if(Common.exists(path_tooltip + ' #oob-upload input[type="reset"]'))
|
||||
if(Common.exists(path_tooltip + ' #oob-upload input[type="reset"]')) {
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// Lock the bubble
|
||||
$(path_bubble).addClass('locked');
|
||||
|
||||
|
||||
// Add a cancel button
|
||||
$(this).after('<input type="reset" value="' + Common._e("Cancel") + '" />');
|
||||
|
||||
|
||||
// Cancel button click event
|
||||
$(path_tooltip + ' #oob-upload input[type="reset"]').click(function() {
|
||||
// Remove the bubble
|
||||
|
@ -442,24 +471,24 @@ var Tooltip = (function () {
|
|||
self.destroy(hash, 'file');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
// Chat log
|
||||
case 'save':
|
||||
// Chat log generation click event
|
||||
$(path_tooltip + ' .tooltip-actionlog').click(function() {
|
||||
// Replace it with a waiting notice
|
||||
$(this).replaceWith('<span class="tooltip-waitlog">' + Common._e("Please wait...") + '</span>');
|
||||
|
||||
|
||||
Interface.generateChatLog(xid, hash);
|
||||
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
} catch(e) {
|
||||
Console.error('Tooltip.create', e);
|
||||
|
@ -524,7 +553,7 @@ var Tooltip = (function () {
|
|||
self.hover(xid, hash, 'style');
|
||||
self.hover(xid, hash, 'file');
|
||||
self.hover(xid, hash, 'save');
|
||||
|
||||
|
||||
// Click events
|
||||
$('#' + hash + ' a.chat-tools-content, #' + hash + ' .chat-tools-content a').click(function() {
|
||||
return false;
|
||||
|
@ -553,33 +582,37 @@ var Tooltip = (function () {
|
|||
var font_select = $(bubble_style + ' div.font-list').find('a[data-value="' + font + '"]');
|
||||
var fontsize = message_area.attr('data-fontsize');
|
||||
var color = message_area.attr('data-color');
|
||||
|
||||
|
||||
// Apply message font
|
||||
if(font) {
|
||||
$(bubble_style + ' a.font-current').attr('data-value', font)
|
||||
.attr('data-font', font_select.attr('data-font'))
|
||||
.text(font_select.text());
|
||||
}
|
||||
|
||||
|
||||
// Apply message font-size
|
||||
if(fontsize) {
|
||||
$(bubble_style + ' a.fontsize-current').attr('data-value', fontsize)
|
||||
.text(fontsize);
|
||||
}
|
||||
|
||||
|
||||
// Apply the options to the style selector
|
||||
$(bubble_style + ' input[type="checkbox"]').each(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// Current input enabled?
|
||||
if(message_area.attr('data-' + $(this).attr('class')))
|
||||
$(this).attr('checked', true);
|
||||
if(message_area.attr('data-' + this_sel.attr('class'))) {
|
||||
this_sel.attr('checked', true);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Apply message color
|
||||
if(color) {
|
||||
if($(bubble_style + ' a.color[data-color="' + color + '"]').size())
|
||||
if($(bubble_style + ' a.color[data-color="' + color + '"]').size()) {
|
||||
$(bubble_style + ' a.color[data-color="' + color + '"]').addClass('selected');
|
||||
else
|
||||
} else {
|
||||
$(bubble_style + ' div.color-hex input.hex-value').val(color);
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('Tooltip.loadStyleSelector', e);
|
||||
|
|
|
@ -31,91 +31,91 @@ var UserInfos = (function () {
|
|||
try {
|
||||
// Can show shortcuts?
|
||||
var shortcuts = '';
|
||||
|
||||
|
||||
if(xid != Common.getXID()) {
|
||||
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="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>' +
|
||||
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="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>' +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
|
||||
// Popup HTML content
|
||||
var html =
|
||||
'<div class="top">' + Common._e("User profile") + '</div>' +
|
||||
|
||||
'<div class="tab">' +
|
||||
'<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="3">' + Common._e("Comments") + '</a>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="content">' +
|
||||
'<div class="lap-active one-lap info1">' +
|
||||
'<div class="main-infos">' +
|
||||
'<div class="avatar-container">' +
|
||||
'<img class="avatar" src="' + './images/others/default-avatar.png' + '" alt="" />' +
|
||||
'</div>' +
|
||||
|
||||
'<h1 id="BUDDY-FN" class="reset-info">' + Common._e("unknown") + '</h1>' +
|
||||
'<h2 class="buddy-xid" class="reset-info">' + Common._e("unknown") + '</h2>' +
|
||||
'<h3 class="buddy-last" class="reset-info">' + Common._e("unknown") + '</h3>' +
|
||||
|
||||
shortcuts +
|
||||
'</div>' +
|
||||
|
||||
'<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("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("Website") + '</b><span id="BUDDY-URL" class="reset-info">' + Common._e("unknown") + '</span></div>' +
|
||||
'</div>' +
|
||||
|
||||
'<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("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>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="one-lap info2">' +
|
||||
'<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("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("Country") + '</b><span id="BUDDY-ADR-CTRY" class="reset-info">' + Common._e("unknown") + '</span></div>' +
|
||||
'</div>' +
|
||||
|
||||
'<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>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="one-lap info3">' +
|
||||
'<textarea class="rosternotes" rows="8" cols="60"></textarea>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="bottom">' +
|
||||
'<div class="wait wait-medium"></div>' +
|
||||
|
||||
'<a href="#" class="finish">' + Common._e("Close") + '</a>' +
|
||||
var html =
|
||||
'<div class="top">' + Common._e("User profile") + '</div>' +
|
||||
|
||||
'<div class="tab">' +
|
||||
'<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="3">' + Common._e("Comments") + '</a>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="content">' +
|
||||
'<div class="lap-active one-lap info1">' +
|
||||
'<div class="main-infos">' +
|
||||
'<div class="avatar-container">' +
|
||||
'<img class="avatar" src="' + './images/others/default-avatar.png' + '" alt="" />' +
|
||||
'</div>' +
|
||||
|
||||
'<h1 id="BUDDY-FN" class="reset-info">' + Common._e("unknown") + '</h1>' +
|
||||
'<h2 class="buddy-xid" class="reset-info">' + Common._e("unknown") + '</h2>' +
|
||||
'<h3 class="buddy-last" class="reset-info">' + Common._e("unknown") + '</h3>' +
|
||||
|
||||
shortcuts +
|
||||
'</div>' +
|
||||
|
||||
'<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("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("Website") + '</b><span id="BUDDY-URL" class="reset-info">' + Common._e("unknown") + '</span></div>' +
|
||||
'</div>' +
|
||||
|
||||
'<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("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>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="one-lap info2">' +
|
||||
'<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("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("Country") + '</b><span id="BUDDY-ADR-CTRY" class="reset-info">' + Common._e("unknown") + '</span></div>' +
|
||||
'</div>' +
|
||||
|
||||
'<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>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="one-lap info3">' +
|
||||
'<textarea class="rosternotes" rows="8" cols="60"></textarea>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="bottom">' +
|
||||
'<div class="wait wait-medium"></div>' +
|
||||
|
||||
'<a href="#" class="finish">' + Common._e("Close") + '</a>' +
|
||||
'</div>';
|
||||
|
||||
|
||||
// Create the popup
|
||||
Popup.create('userinfos', html);
|
||||
|
||||
|
||||
// Associate the events
|
||||
UserInfos.instance();
|
||||
|
||||
|
||||
// We retrieve the user's vcard
|
||||
self.retrieve(xid);
|
||||
} catch(e) {
|
||||
|
@ -137,7 +137,7 @@ var UserInfos = (function () {
|
|||
try {
|
||||
// Send the buddy comments
|
||||
self.sendBuddyComments();
|
||||
|
||||
|
||||
// Destroy the popup
|
||||
Popup.destroy('userinfos');
|
||||
} catch(e) {
|
||||
|
@ -160,38 +160,38 @@ var UserInfos = (function () {
|
|||
try {
|
||||
// We setup the waiting indicator
|
||||
markers = 'vcard last';
|
||||
|
||||
|
||||
// We put the user's XID
|
||||
$('#userinfos .buddy-xid').text(xid);
|
||||
|
||||
|
||||
// We get the vCard
|
||||
vCard.get(xid, 'buddy');
|
||||
|
||||
|
||||
// Get the highest resource for this XID
|
||||
var cXID = Presence.highestPriority(xid);
|
||||
var pXID = xid;
|
||||
|
||||
|
||||
// If the user is logged in
|
||||
if(cXID) {
|
||||
// Change the XID
|
||||
pXID = cXID;
|
||||
|
||||
|
||||
// We request the user's system infos
|
||||
self.query(cXID, 'version');
|
||||
|
||||
|
||||
// We request the user's local time
|
||||
self.query(cXID, 'time');
|
||||
|
||||
|
||||
// Add these to the markers
|
||||
markers += ' version time';
|
||||
}
|
||||
|
||||
|
||||
// We request the user's last activity
|
||||
self.query(pXID, 'last');
|
||||
|
||||
|
||||
// Add the markers
|
||||
$('#userinfos .content').addClass(markers);
|
||||
|
||||
|
||||
// We request all the user's comments
|
||||
self.displayBuddyComments(xid);
|
||||
} catch(e) {
|
||||
|
@ -214,26 +214,26 @@ var UserInfos = (function () {
|
|||
// Generate a session ID
|
||||
var id = genID();
|
||||
$('#userinfos').attr('data-' + mode, id);
|
||||
|
||||
|
||||
// New IQ
|
||||
var iq = new JSJaCIQ();
|
||||
|
||||
|
||||
iq.setID(id);
|
||||
iq.setType('get');
|
||||
iq.setTo(xid);
|
||||
|
||||
|
||||
// Last activity query
|
||||
if(mode == 'last') {
|
||||
iq.setQuery(NS_LAST);
|
||||
con.send(iq, self.lastActivityUserInfos);
|
||||
}
|
||||
|
||||
|
||||
// Time query
|
||||
else if(mode == 'time') {
|
||||
iq.appendNode('time', {'xmlns': NS_URN_TIME});
|
||||
con.send(iq, self.localTime);
|
||||
}
|
||||
|
||||
|
||||
// Version query
|
||||
else if(mode == 'version') {
|
||||
iq.setQuery(NS_VERSION);
|
||||
|
@ -273,7 +273,7 @@ var UserInfos = (function () {
|
|||
|
||||
try {
|
||||
var value = DataStore.getDB(Connection.desktop_hash, 'rosternotes', xid);
|
||||
|
||||
|
||||
if(value) {
|
||||
$('#userinfos .rosternotes').val(value);
|
||||
}
|
||||
|
@ -296,26 +296,28 @@ var UserInfos = (function () {
|
|||
// Extract the request ID
|
||||
var id = iq.getID();
|
||||
var path = '#userinfos[data-last="' + id + '"]';
|
||||
|
||||
|
||||
// End if session does not exist
|
||||
if(!Common.exists(path))
|
||||
if(!Common.exists(path)) {
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if(iq && (iq.getType() == 'result')) {
|
||||
// Get the values
|
||||
var from = Common.fullXID(Common.getStanzaFrom(iq));
|
||||
var seconds = $(iq.getNode()).find('query').attr('seconds');
|
||||
|
||||
|
||||
// Any seconds?
|
||||
if(seconds !== undefined) {
|
||||
// Initialize the parsing
|
||||
var last;
|
||||
seconds = parseInt(seconds);
|
||||
|
||||
|
||||
// Active user
|
||||
if(seconds <= 60)
|
||||
if(seconds <= 60) {
|
||||
last = Common._e("User currently active");
|
||||
|
||||
}
|
||||
|
||||
// Inactive user
|
||||
else {
|
||||
// Parse the date
|
||||
|
@ -323,23 +325,25 @@ var UserInfos = (function () {
|
|||
var time_now = date_now.getTime();
|
||||
var date_last = new Date(date_now - (seconds * 1000));
|
||||
var date = date_last.toLocaleString();
|
||||
|
||||
|
||||
// Offline user
|
||||
if(from.indexOf('/') == -1)
|
||||
if(from.indexOf('/') == -1) {
|
||||
last = Common.printf(Common._e("Last seen: %s"), date);
|
||||
|
||||
}
|
||||
|
||||
// Online user
|
||||
else
|
||||
else {
|
||||
last = Common.printf(Common._e("Inactive since: %s"), date);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Append this text
|
||||
$('#userinfos .buddy-last').text(last);
|
||||
}
|
||||
|
||||
|
||||
Console.log('Last activity received: ' + from);
|
||||
}
|
||||
|
||||
|
||||
$('#userinfos .content').removeClass('last');
|
||||
self.wait();
|
||||
} catch(e) {
|
||||
|
@ -361,11 +365,12 @@ var UserInfos = (function () {
|
|||
// Extract the request ID
|
||||
var id = iq.getID();
|
||||
var path = '#userinfos[data-version="' + id + '"]';
|
||||
|
||||
|
||||
// End if session does not exist
|
||||
if(!Common.exists(path))
|
||||
if(!Common.exists(path)) {
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// Extract the reply data
|
||||
if(iq && (iq.getType() == 'result')) {
|
||||
// Get the values
|
||||
|
@ -373,20 +378,24 @@ var UserInfos = (function () {
|
|||
var name = $(xml).find('name').text();
|
||||
var version = $(xml).find('version').text();
|
||||
var os = $(xml).find('os').text();
|
||||
|
||||
|
||||
// Put the values together
|
||||
if(name && version)
|
||||
if(name && version) {
|
||||
name = name + ' ' + version;
|
||||
|
||||
}
|
||||
|
||||
// Display the values
|
||||
if(name)
|
||||
if(name) {
|
||||
$(path + ' #BUDDY-CLIENT').text(name);
|
||||
if(os)
|
||||
}
|
||||
|
||||
if(os) {
|
||||
$(path + ' #BUDDY-SYSTEM').text(os);
|
||||
|
||||
}
|
||||
|
||||
Console.log('Software version received: ' + Common.fullXID(Common.getStanzaFrom(iq)));
|
||||
}
|
||||
|
||||
|
||||
$('#userinfos .content').removeClass('version');
|
||||
self.wait();
|
||||
} catch(e) {
|
||||
|
@ -408,33 +417,35 @@ var UserInfos = (function () {
|
|||
// Extract the request ID
|
||||
var id = iq.getID();
|
||||
var path = '#userinfos[data-time="' + id + '"]';
|
||||
|
||||
|
||||
// End if session does not exist
|
||||
if(!Common.exists(path))
|
||||
if(!Common.exists(path)) {
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if(iq && (iq.getType() == 'result')) {
|
||||
// Get the values
|
||||
var xml = iq.getNode();
|
||||
var tzo = $(xml).find('tzo').text();
|
||||
var utc = $(xml).find('utc').text();
|
||||
|
||||
|
||||
// Any UTC?
|
||||
if(utc) {
|
||||
// Add the TZO if there's no one
|
||||
if(tzo && utc.match(/^(.+)Z$/))
|
||||
if(tzo && utc.match(/^(.+)Z$/)) {
|
||||
utc = RegExp.$1 + tzo;
|
||||
|
||||
}
|
||||
|
||||
// Get the local date string
|
||||
var local_string = Date.hrTime(utc);
|
||||
|
||||
|
||||
// Then display it
|
||||
$(path + ' #BUDDY-TIME').text(local_string);
|
||||
}
|
||||
|
||||
|
||||
Console.log('Local time received: ' + Common.fullXID(Common.getStanzaFrom(iq)));
|
||||
}
|
||||
|
||||
|
||||
$('#userinfos .content').removeClass('time');
|
||||
self.wait();
|
||||
} catch(e) {
|
||||
|
@ -453,9 +464,10 @@ var UserInfos = (function () {
|
|||
|
||||
try {
|
||||
var selector = $('#userinfos .content');
|
||||
|
||||
if(!selector.hasClass('vcard') && !selector.hasClass('last') && !selector.hasClass('version') && !selector.hasClass('time'))
|
||||
|
||||
if(!selector.hasClass('vcard') && !selector.hasClass('last') && !selector.hasClass('version') && !selector.hasClass('time')) {
|
||||
$('#userinfos .wait').hide();
|
||||
}
|
||||
} catch(e) {
|
||||
Console.error('UserInfos.wait', e);
|
||||
}
|
||||
|
@ -474,41 +486,43 @@ var UserInfos = (function () {
|
|||
// Update the current value
|
||||
var value = $('#userinfos .rosternotes').val();
|
||||
var xid = $('#userinfos .buddy-xid').text();
|
||||
|
||||
|
||||
// Necessary to update?
|
||||
var old_value = DataStore.getDB(Connection.desktop_hash, 'rosternotes', xid);
|
||||
|
||||
if((old_value == value) || (!old_value && !value))
|
||||
|
||||
if((old_value == value) || (!old_value && !value)) {
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
// Update the database
|
||||
DataStore.setDB(Connection.desktop_hash, 'rosternotes', xid, value);
|
||||
|
||||
|
||||
// Send the new buddy storage values
|
||||
var iq = new JSJaCIQ();
|
||||
iq.setType('set');
|
||||
var query = iq.setQuery(NS_PRIVATE);
|
||||
var storage = query.appendChild(iq.buildNode('storage', {'xmlns': NS_ROSTERNOTES}));
|
||||
|
||||
|
||||
// We regenerate the XML
|
||||
var db_regex = new RegExp(('^' + Connection.desktop_hash + '_') + 'rosternotes' + ('_(.+)'));
|
||||
|
||||
for(var i = 0; i < DataStore.storageDB.length; i++) {
|
||||
// Get the pointer values
|
||||
var current = DataStore.storageDB.key(i);
|
||||
|
||||
|
||||
// If the pointer is on a stored rosternote
|
||||
if(current.match(db_regex)) {
|
||||
var cur_xid = RegExp.$1;
|
||||
var cur_value = DataStore.storageDB.getItem(current);
|
||||
|
||||
if(cur_xid && cur_value)
|
||||
|
||||
if(cur_xid && cur_value) {
|
||||
storage.appendChild(iq.buildNode('note', {'jid': cur_xid, 'xmlns': NS_ROSTERNOTES}, cur_value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
con.send(iq);
|
||||
|
||||
|
||||
return false;
|
||||
} catch(e) {
|
||||
Console.error('UserInfos.sendBuddyComments', e);
|
||||
|
@ -526,10 +540,15 @@ var UserInfos = (function () {
|
|||
self.switchTab = function(id) {
|
||||
|
||||
try {
|
||||
$('#userinfos .content .one-lap').hide();
|
||||
$('#userinfos .content .info' + id).show();
|
||||
$('#userinfos .tab a').removeClass('tab-active');
|
||||
$('#userinfos .tab a[data-key="' + id + '"]').addClass('tab-active');
|
||||
var userinfos_sel = $('#userinfos');
|
||||
var content_sel = userinfos_sel.find('.content');
|
||||
var tab_link_sel = userinfos_sel.find('.tab a');
|
||||
|
||||
content_sel.find('.one-lap').hide();
|
||||
content_sel.find('.info' + id).show();
|
||||
|
||||
tab_link_sel.removeClass('tab-active');
|
||||
tab_link_sel.filter('[data-key="' + id + '"]').addClass('tab-active');
|
||||
} catch(e) {
|
||||
Console.error('UserInfos.switchTab', e);
|
||||
} finally {
|
||||
|
@ -558,11 +577,11 @@ var UserInfos = (function () {
|
|||
$('#' + hash + ' .top .name .bc-name').text(nick);
|
||||
$('#page-switch .' + hash + ' .name').text(nick);
|
||||
}
|
||||
|
||||
|
||||
// Get the buddy PEP informations
|
||||
PEP.displayAll(xid);
|
||||
}
|
||||
|
||||
|
||||
// Display the buddy presence
|
||||
Presence.funnel(xid, hash);
|
||||
} catch(e) {
|
||||
|
@ -582,16 +601,19 @@ var UserInfos = (function () {
|
|||
try {
|
||||
// Click events
|
||||
$('#userinfos .tab a').click(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// Yet active?
|
||||
if($(this).hasClass('tab-active'))
|
||||
if(this_sel.hasClass('tab-active')) {
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
// Switch to the good tab
|
||||
var key = parseInt($(this).attr('data-key'));
|
||||
|
||||
var key = parseInt(this_sel.attr('data-key'));
|
||||
|
||||
return self.switchTab(key);
|
||||
});
|
||||
|
||||
|
||||
$('#userinfos .bottom .finish').click(function() {
|
||||
return self.close();
|
||||
});
|
||||
|
|
|
@ -52,9 +52,10 @@ var Utils = (function () {
|
|||
|
||||
try {
|
||||
// HTTPS not allowed
|
||||
if((HTTPS_STORAGE != 'on') && url.match(/^https(.+)/))
|
||||
if((HTTPS_STORAGE != 'on') && url.match(/^https(.+)/)) {
|
||||
url = 'http' + RegExp.$1;
|
||||
|
||||
}
|
||||
|
||||
return url;
|
||||
} catch(e) {
|
||||
Console.error('Utils.generateURL', e);
|
||||
|
@ -76,7 +77,7 @@ var Utils = (function () {
|
|||
if(value == condition) {
|
||||
return ' disabled=""';
|
||||
}
|
||||
|
||||
|
||||
return '';
|
||||
} catch(e) {
|
||||
Console.error('Utils.disableInput', e);
|
||||
|
@ -99,7 +100,7 @@ var Utils = (function () {
|
|||
if(string.length > limit) {
|
||||
string = string.substr(0, limit) + '...';
|
||||
}
|
||||
|
||||
|
||||
return string;
|
||||
} catch(e) {
|
||||
Console.error('Utils.truncate', e);
|
||||
|
@ -215,31 +216,37 @@ var Utils = (function () {
|
|||
// Get browser name & version
|
||||
var browser_name = BrowserDetect.browser;
|
||||
var browser_version = BrowserDetect.version;
|
||||
|
||||
|
||||
// No DOM storage
|
||||
if(!DataStore.hasDB() || !DataStore.hasPersistent())
|
||||
if(!DataStore.hasDB() || !DataStore.hasPersistent()) {
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
// Obsolete IE
|
||||
if((browser_name == 'Explorer') && (browser_version < 8))
|
||||
if((browser_name == 'Explorer') && (browser_version < 8)) {
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
// Obsolete Chrome
|
||||
if((browser_name == 'Chrome') && (browser_version < 7))
|
||||
if((browser_name == 'Chrome') && (browser_version < 7)) {
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
// Obsolete Safari
|
||||
if((browser_name == 'Safari') && (browser_version < 4))
|
||||
if((browser_name == 'Safari') && (browser_version < 4)) {
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
// Obsolete Firefox
|
||||
if((browser_name == 'Firefox') && (browser_version < 3.5))
|
||||
if((browser_name == 'Firefox') && (browser_version < 3.5)) {
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
// Obsolete Opera
|
||||
if((browser_name == 'Opera') && (browser_version < 9))
|
||||
if((browser_name == 'Opera') && (browser_version < 9)) {
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
} catch(e) {
|
||||
Console.error('Utils.isObsolete', e);
|
||||
|
@ -341,7 +348,7 @@ var Utils = (function () {
|
|||
} catch(e) {
|
||||
Console.error('Utils.quoteMyNick', e);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -355,7 +362,7 @@ var Utils = (function () {
|
|||
|
||||
try {
|
||||
var cat;
|
||||
|
||||
|
||||
switch(ext) {
|
||||
// Images
|
||||
case 'jpg':
|
||||
|
@ -371,9 +378,9 @@ var Utils = (function () {
|
|||
case 'psb':
|
||||
case 'xcf':
|
||||
cat = 'image';
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
// Videos
|
||||
case 'ogv':
|
||||
case 'ogg':
|
||||
|
@ -395,9 +402,9 @@ var Utils = (function () {
|
|||
case '3gp':
|
||||
case 'avc':
|
||||
cat = 'video';
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
// Sounds
|
||||
case 'oga':
|
||||
case 'mka':
|
||||
|
@ -422,9 +429,9 @@ var Utils = (function () {
|
|||
case 'snd':
|
||||
case 'voc':
|
||||
cat = 'audio';
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
// Documents
|
||||
case 'pdf':
|
||||
case 'odt':
|
||||
|
@ -463,9 +470,9 @@ var Utils = (function () {
|
|||
case 'dhtml':
|
||||
case 'mshtml':
|
||||
cat = 'document';
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
// Packages
|
||||
case 'tgz':
|
||||
case 'gz':
|
||||
|
@ -490,16 +497,16 @@ var Utils = (function () {
|
|||
case 'arj':
|
||||
case 'msi':
|
||||
cat = 'package';
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
// Others
|
||||
default:
|
||||
cat = 'other';
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return cat;
|
||||
} catch(e) {
|
||||
Console.error('Utils.fileCategory', e);
|
||||
|
@ -517,7 +524,7 @@ var Utils = (function () {
|
|||
|
||||
try {
|
||||
navigator.registerProtocolHandler('xmpp', JAPPIX_LOCATION + '?x=%s', SERVICE_NAME);
|
||||
|
||||
|
||||
return true;
|
||||
} catch(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
|
||||
* @public
|
||||
|
@ -595,26 +629,27 @@ var Utils = (function () {
|
|||
|
||||
try {
|
||||
var array = [];
|
||||
|
||||
|
||||
// Any string to convert?
|
||||
if(string) {
|
||||
// More than one item
|
||||
if(string.match(/,/gi)) {
|
||||
var string_split = string.split(',');
|
||||
|
||||
|
||||
for(var i in string_split) {
|
||||
if(string_split[i])
|
||||
if(string_split[i]) {
|
||||
array.push(string_split[i]);
|
||||
else
|
||||
} else {
|
||||
array.push('');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Only one item
|
||||
else
|
||||
array.push(string);
|
||||
}
|
||||
|
||||
|
||||
return array;
|
||||
} catch(e) {
|
||||
Console.error('Utils.stringToArray', e);
|
||||
|
@ -634,20 +669,21 @@ var Utils = (function () {
|
|||
|
||||
try {
|
||||
// Nothing?
|
||||
if(!array || !array.length)
|
||||
if(!array || !array.length) {
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
// Read the index of the value
|
||||
var index = 0;
|
||||
|
||||
|
||||
for(var i = 0; i < array.length; i++) {
|
||||
if(array[i] == value) {
|
||||
index = i;
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return index;
|
||||
} catch(e) {
|
||||
Console.error('Utils.indexArrayValue', e);
|
||||
|
|
|
@ -30,122 +30,122 @@ var vCard = (function () {
|
|||
try {
|
||||
// Popup HTML content
|
||||
var html =
|
||||
'<div class="top">' + Common._e("Your profile") + '</div>' +
|
||||
|
||||
'<div class="tab">' +
|
||||
'<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="3">' + Common._e("Others") + '</a>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="content">' +
|
||||
'<div id="lap1" class="lap-active one-lap forms">' +
|
||||
'<fieldset>' +
|
||||
'<legend>' + Common._e("Personal") + '</legend>' +
|
||||
|
||||
'<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" />' +
|
||||
|
||||
'<label for="USER-NICKNAME">' + Common._e("Nickname") + '</label>' +
|
||||
'<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>' +
|
||||
'<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>' +
|
||||
'<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>' +
|
||||
'<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>' +
|
||||
'<legend>' + Common._e("Contact") + '</legend>' +
|
||||
|
||||
'<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" />' +
|
||||
|
||||
'<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" />' +
|
||||
|
||||
'<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" />' +
|
||||
'</fieldset>' +
|
||||
'</div>' +
|
||||
|
||||
'<div id="lap2" class="one-lap forms">' +
|
||||
'<fieldset>' +
|
||||
'<legend>' + Common._e("New") + '</legend>' +
|
||||
|
||||
'<input type="hidden" id="USER-PHOTO-TYPE" 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">' +
|
||||
Interface.generateFileShare() +
|
||||
'</form>' +
|
||||
'</fieldset>' +
|
||||
|
||||
'<fieldset>' +
|
||||
'<legend>' + Common._e("Current") + '</legend>' +
|
||||
|
||||
'<div class="avatar-container"></div>' +
|
||||
|
||||
'<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>' +
|
||||
'</fieldset>' +
|
||||
|
||||
'<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-error avatar-info">' + Common._e("The image file is not supported or has a bad size.") + '</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div id="lap3" class="one-lap forms">' +
|
||||
'<fieldset>' +
|
||||
'<legend>' + Common._e("Address") + '</legend>' +
|
||||
|
||||
'<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" />' +
|
||||
|
||||
'<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" />' +
|
||||
|
||||
'<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" />' +
|
||||
|
||||
'<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" />' +
|
||||
'</fieldset>' +
|
||||
|
||||
'<fieldset>' +
|
||||
'<legend>' + Common._e("Biography") + '</legend>' +
|
||||
|
||||
'<textarea id="USER-DESC" data-vcard4="note-text" rows="8" cols="60" class="vcard-item"></textarea>' +
|
||||
'</fieldset>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="infos">' +
|
||||
'<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("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><b><a href="https://me.jappix.com/new" target="_blank">' + Common._e("Enable my public profile") + ' »</a></b></p>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="bottom">' +
|
||||
'<div class="wait wait-medium"></div>' +
|
||||
|
||||
'<a href="#" class="finish save disabled">' + Common._e("Save") + '</a>' +
|
||||
'<a href="#" class="finish cancel">' + Common._e("Cancel") + '</a>' +
|
||||
'<div class="top">' + Common._e("Your profile") + '</div>' +
|
||||
|
||||
'<div class="tab">' +
|
||||
'<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="3">' + Common._e("Others") + '</a>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="content">' +
|
||||
'<div id="lap1" class="lap-active one-lap forms">' +
|
||||
'<fieldset>' +
|
||||
'<legend>' + Common._e("Personal") + '</legend>' +
|
||||
|
||||
'<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" />' +
|
||||
|
||||
'<label for="USER-NICKNAME">' + Common._e("Nickname") + '</label>' +
|
||||
'<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>' +
|
||||
'<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>' +
|
||||
'<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>' +
|
||||
'<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>' +
|
||||
'<legend>' + Common._e("Contact") + '</legend>' +
|
||||
|
||||
'<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" />' +
|
||||
|
||||
'<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" />' +
|
||||
|
||||
'<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" />' +
|
||||
'</fieldset>' +
|
||||
'</div>' +
|
||||
|
||||
'<div id="lap2" class="one-lap forms">' +
|
||||
'<fieldset>' +
|
||||
'<legend>' + Common._e("New") + '</legend>' +
|
||||
|
||||
'<input type="hidden" id="USER-PHOTO-TYPE" 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">' +
|
||||
Interface.generateFileShare() +
|
||||
'</form>' +
|
||||
'</fieldset>' +
|
||||
|
||||
'<fieldset>' +
|
||||
'<legend>' + Common._e("Current") + '</legend>' +
|
||||
|
||||
'<div class="avatar-container"></div>' +
|
||||
|
||||
'<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>' +
|
||||
'</fieldset>' +
|
||||
|
||||
'<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-error avatar-info">' + Common._e("The image file is not supported or has a bad size.") + '</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div id="lap3" class="one-lap forms">' +
|
||||
'<fieldset>' +
|
||||
'<legend>' + Common._e("Address") + '</legend>' +
|
||||
|
||||
'<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" />' +
|
||||
|
||||
'<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" />' +
|
||||
|
||||
'<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" />' +
|
||||
|
||||
'<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" />' +
|
||||
'</fieldset>' +
|
||||
|
||||
'<fieldset>' +
|
||||
'<legend>' + Common._e("Biography") + '</legend>' +
|
||||
|
||||
'<textarea id="USER-DESC" data-vcard4="note-text" rows="8" cols="60" class="vcard-item"></textarea>' +
|
||||
'</fieldset>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="infos">' +
|
||||
'<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("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><b><a href="https://me.jappix.com/new" target="_blank">' + Common._e("Enable my public profile") + ' »</a></b></p>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="bottom">' +
|
||||
'<div class="wait wait-medium"></div>' +
|
||||
|
||||
'<a href="#" class="finish save disabled">' + Common._e("Save") + '</a>' +
|
||||
'<a href="#" class="finish cancel">' + Common._e("Cancel") + '</a>' +
|
||||
'</div>';
|
||||
|
||||
|
||||
// Create the popup
|
||||
Popup.create('vcard', html);
|
||||
|
||||
|
||||
// Associate the events
|
||||
self.instance();
|
||||
|
||||
|
||||
// We get the VCard informations
|
||||
self.get(Common.getXID(), 'user');
|
||||
} catch(e) {
|
||||
|
@ -167,12 +167,12 @@ var vCard = (function () {
|
|||
try {
|
||||
// Destroy the popup
|
||||
Popup.destroy('vcard');
|
||||
|
||||
|
||||
// Create the welcome end popup?
|
||||
if(Welcome.is_done) {
|
||||
// Open popup
|
||||
Me.open();
|
||||
|
||||
|
||||
// Unavoidable popup
|
||||
$('#me').addClass('unavoidable');
|
||||
}
|
||||
|
@ -217,7 +217,7 @@ var vCard = (function () {
|
|||
try {
|
||||
// Reset the avatar info
|
||||
$('#vcard .avatar-info').hide().stopTime();
|
||||
|
||||
|
||||
// Show the wait info
|
||||
$('#vcard .avatar-wait').show();
|
||||
} catch(e) {
|
||||
|
@ -238,53 +238,53 @@ var vCard = (function () {
|
|||
try {
|
||||
// Data selector
|
||||
var dData = $(responseXML).find('jappix');
|
||||
|
||||
|
||||
// Not current upload session?
|
||||
if(parseInt(dData.attr('id')) != parseInt($('#vcard-avatar input[name="id"]').val())) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Reset the avatar info
|
||||
$('#vcard .avatar-info').hide().stopTime();
|
||||
|
||||
|
||||
// Process the returned data
|
||||
if(!dData.find('error').size()) {
|
||||
// Read the values
|
||||
var aType = dData.find('type').text();
|
||||
var aBinval = dData.find('binval').text();
|
||||
|
||||
|
||||
// We remove everything that isn't useful right here
|
||||
$('#vcard .no-avatar').hide();
|
||||
$('#vcard .avatar').remove();
|
||||
|
||||
|
||||
// We display the delete button
|
||||
$('#vcard .avatar-delete').show();
|
||||
|
||||
|
||||
// We tell the user it's okay
|
||||
$('#vcard .avatar-ok').show();
|
||||
|
||||
|
||||
// Timer
|
||||
$('#vcard .avatar-info').oneTime('10s', function() {
|
||||
$(this).hide();
|
||||
});
|
||||
|
||||
|
||||
// We put the base64 values in a hidden input to be sent
|
||||
$('#USER-PHOTO-TYPE').val(aType);
|
||||
$('#USER-PHOTO-BINVAL').val(aBinval);
|
||||
|
||||
// We display the avatar !
|
||||
|
||||
// We display the avatar!
|
||||
$('#vcard .avatar-container').replaceWith('<div class="avatar-container"><img class="avatar" src="data:' + aType + ';base64,' + aBinval + '" alt="" /></div>');
|
||||
}
|
||||
|
||||
|
||||
// Any error?
|
||||
else {
|
||||
$('#vcard .avatar-error').show();
|
||||
|
||||
|
||||
// Timer
|
||||
$('#vcard .avatar-info').oneTime('10s', function() {
|
||||
$(this).hide();
|
||||
});
|
||||
|
||||
|
||||
Console.error('Error while uploading the avatar', dData.find('error').text());
|
||||
}
|
||||
} catch(e) {
|
||||
|
@ -306,10 +306,10 @@ var vCard = (function () {
|
|||
$('#vcard .avatar-info').stopTime();
|
||||
$('#vcard .avatar-info, #vcard .avatar-wait, #vcard .avatar-error, #vcard .avatar-ok, #vcard .avatar-delete').hide();
|
||||
$('#vcard .avatar').remove();
|
||||
|
||||
|
||||
// We reset the input value
|
||||
$('#USER-PHOTO-TYPE, #USER-PHOTO-BINVAL').val('');
|
||||
|
||||
|
||||
// We show the avatar-uploading request
|
||||
$('#vcard .no-avatar').show();
|
||||
} catch(e) {
|
||||
|
@ -333,7 +333,7 @@ var vCard = (function () {
|
|||
try {
|
||||
// Generate the new ID
|
||||
id = 'USER-' + id;
|
||||
|
||||
|
||||
// Can append the content
|
||||
if((type == 'user') && !Common.exists('#vcard #' + id)) {
|
||||
$('#vcard .content').append('<input id="' + id + '" class="vcard-item" type="hidden" />');
|
||||
|
@ -357,32 +357,30 @@ var vCard = (function () {
|
|||
try {
|
||||
// Generate a special ID
|
||||
var id = genID();
|
||||
|
||||
|
||||
// New IQ
|
||||
var iq = new JSJaCIQ();
|
||||
iq.setID(id);
|
||||
iq.setType('get');
|
||||
iq.appendNode('vCard', {'xmlns': NS_VCARD});
|
||||
|
||||
|
||||
// Send the IQ to the good user
|
||||
if(type == 'user') {
|
||||
// Show the wait icon
|
||||
$('#vcard .wait').show();
|
||||
|
||||
|
||||
// Apply the session ID
|
||||
$('#vcard').attr('data-vcard', id);
|
||||
|
||||
|
||||
// Send the IQ
|
||||
con.send(iq, self.handleUser);
|
||||
}
|
||||
|
||||
else {
|
||||
} else {
|
||||
// Show the wait icon
|
||||
$('#userinfos .wait').show();
|
||||
|
||||
|
||||
// Apply the session ID
|
||||
$('#userinfos').attr('data-vcard', id);
|
||||
|
||||
|
||||
// Send the IQ
|
||||
iq.setTo(to);
|
||||
con.send(iq, self.handleBuddy);
|
||||
|
@ -446,7 +444,7 @@ var vCard = (function () {
|
|||
// Define some paths
|
||||
var path_vcard = '#vcard[data-vcard="' + iqID + '"]';
|
||||
var path_userInfos = '#userinfos[data-vcard="' + iqID + '"]';
|
||||
|
||||
|
||||
// End if the session does not exist
|
||||
if(((type == 'user') && !Common.exists(path_vcard)) || ((type == 'buddy') && !Common.exists(path_userInfos))) {
|
||||
return;
|
||||
|
@ -454,80 +452,85 @@ var vCard = (function () {
|
|||
|
||||
// We retrieve main values
|
||||
var values_yet = [];
|
||||
|
||||
|
||||
$(iqNode).find('vCard').children().each(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// Read the current parent node name
|
||||
var tokenname = (this).nodeName.toUpperCase();
|
||||
|
||||
|
||||
// Node with a parent
|
||||
if($(this).children().size()) {
|
||||
$(this).children().each(function() {
|
||||
if(this_sel.children().size()) {
|
||||
this_sel.children().each(function() {
|
||||
// Get the node values
|
||||
var currentID = tokenname + '-' + (this).nodeName.toUpperCase();
|
||||
var currentText = $(this).text();
|
||||
|
||||
|
||||
// Not yet added?
|
||||
if(!Utils.existArrayValue(values_yet, currentID)) {
|
||||
// Create an input if it does not exist
|
||||
self.createInput(values_yet, type);
|
||||
|
||||
|
||||
// Userinfos viewer popup
|
||||
if((type == 'buddy') && currentText) {
|
||||
if(currentID == 'EMAIL-USERID')
|
||||
if(currentID == 'EMAIL-USERID') {
|
||||
$(path_userInfos + ' #BUDDY-' + currentID).html('<a href="mailto:' + currentText.htmlEnc() + '" target="_blank">' + currentText.htmlEnc() + '</a>');
|
||||
else
|
||||
} else {
|
||||
$(path_userInfos + ' #BUDDY-' + currentID).text(currentText.htmlEnc());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Profile editor popup
|
||||
else if(type == 'user') {
|
||||
$(path_vcard + ' #USER-' + currentID).val(currentText);
|
||||
}
|
||||
|
||||
|
||||
// Avoid duplicating the value
|
||||
values_yet.push(currentID);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Node without any parent
|
||||
else {
|
||||
// Get the node values
|
||||
var currentText = $(this).text();
|
||||
|
||||
|
||||
// Not yet added?
|
||||
if(!Utils.existArrayValue(values_yet, tokenname)) {
|
||||
// Create an input if it does not exist
|
||||
self.createInput(tokenname, type);
|
||||
|
||||
|
||||
// Userinfos viewer popup
|
||||
if((type == 'buddy') && currentText) {
|
||||
// URL modification
|
||||
if(tokenname == 'URL') {
|
||||
// No http:// or https:// prefix, we should add it
|
||||
if(!currentText.match(/^https?:\/\/(.+)/))
|
||||
if(!currentText.match(/^https?:\/\/(.+)/)) {
|
||||
currentText = 'http://' + currentText;
|
||||
|
||||
}
|
||||
|
||||
currentText = '<a href="' + currentText + '" target="_blank">' + currentText.htmlEnc() + '</a>';
|
||||
}
|
||||
|
||||
|
||||
// Description modification
|
||||
else if(tokenname == 'DESC') {
|
||||
currentText = Filter.message(currentText, Name.getBuddy(iqFrom).htmlEnc(), true);
|
||||
}
|
||||
|
||||
|
||||
// Other stuffs
|
||||
else {
|
||||
currentText = currentText.htmlEnc();
|
||||
}
|
||||
|
||||
|
||||
$(path_userInfos + ' #BUDDY-' + tokenname).html(currentText);
|
||||
}
|
||||
|
||||
|
||||
// Profile editor popup
|
||||
else if(type == 'user')
|
||||
else if(type == 'user') {
|
||||
$(path_vcard + ' #USER-' + tokenname).val(currentText);
|
||||
|
||||
}
|
||||
|
||||
// Avoid duplicating the value
|
||||
values_yet.push(tokenname);
|
||||
}
|
||||
|
@ -538,27 +541,25 @@ var vCard = (function () {
|
|||
if(type == 'buddy') {
|
||||
// Get the avatar XML
|
||||
var xml = DataStore.getPersistent('global', 'avatar', iqFrom);
|
||||
|
||||
|
||||
// If there were no stored avatar previously
|
||||
if($(Common.XMLFromString(xml)).find('type').text() == 'none') {
|
||||
xml = xml.replace(/<forced>false<\/forced>/gi, '<forced>true</forced>');
|
||||
DataStore.setPersistent(Common.getXID(), 'avatar', iqFrom, xml);
|
||||
}
|
||||
|
||||
|
||||
// Handle the user avatar
|
||||
Avatar.handle(iq);
|
||||
}
|
||||
|
||||
// The avatar values targets
|
||||
var aBinval, aType, aContainer;
|
||||
|
||||
|
||||
if(type == 'user') {
|
||||
aBinval = $('#USER-PHOTO-BINVAL').val();
|
||||
aType = $('#USER-PHOTO-TYPE').val();
|
||||
aContainer = path_vcard + ' .avatar-container';
|
||||
}
|
||||
|
||||
else {
|
||||
} else {
|
||||
aBinval = $(iqNode).find('BINVAL:first').text();
|
||||
aType = $(iqNode).find('TYPE:first').text();
|
||||
aContainer = path_userInfos + ' .avatar-container';
|
||||
|
@ -570,18 +571,20 @@ var vCard = (function () {
|
|||
if(!aType) {
|
||||
aType = 'image/png';
|
||||
}
|
||||
|
||||
|
||||
if(type == 'user') {
|
||||
// We move all the things that we don't need in that case
|
||||
$(path_vcard + ' .no-avatar').hide();
|
||||
$(path_vcard + ' .avatar-delete').show();
|
||||
$(path_vcard + ' .avatar').remove();
|
||||
}
|
||||
|
||||
|
||||
var avatar_src = ('data:' + aType + ';base64,' + aBinval);
|
||||
|
||||
// We display the avatar we have just received
|
||||
$(aContainer).replaceWith('<div class="avatar-container"><img class="avatar" src="data:' + aType + ';base64,' + aBinval + '" alt="" /></div>');
|
||||
$(aContainer).replaceWith('<div class="avatar-container"><img class="avatar" src="' + avatar_src + '" alt="" /></div>');
|
||||
}
|
||||
|
||||
|
||||
else if(type == 'buddy') {
|
||||
$(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 {
|
||||
UserInfos.vCard();
|
||||
}
|
||||
|
||||
|
||||
Console.log('vCard received: ' + iqFrom);
|
||||
} catch(e) {
|
||||
Console.error('vCard.handle', e);
|
||||
|
@ -613,18 +616,18 @@ var vCard = (function () {
|
|||
// Send both vcard-temp + vCard4
|
||||
self._sendLegacy();
|
||||
self._sendForward();
|
||||
|
||||
|
||||
// Send the user nickname & avatar over PEP
|
||||
if(Features.enabledPEP()) {
|
||||
self._sendPubsub();
|
||||
}
|
||||
|
||||
|
||||
// Close the vCard stuffs
|
||||
self.close();
|
||||
|
||||
|
||||
// Get our new avatar
|
||||
Avatar.get(Common.getXID(), 'force', 'true', 'forget');
|
||||
|
||||
|
||||
Console.log('vCard sent.');
|
||||
} catch(e) {
|
||||
Console.error('vCard.send', e);
|
||||
|
@ -668,11 +671,12 @@ var vCard = (function () {
|
|||
var tagname = Common.explodeThis('-', item_id, 0);
|
||||
var cur_node;
|
||||
|
||||
if(node.getElementsByTagName(tagname).length > 0)
|
||||
if(node.getElementsByTagName(tagname).length > 0) {
|
||||
cur_node = node.getElementsByTagName(tagname).item(0);
|
||||
else
|
||||
} else {
|
||||
cur_node = node.appendChild(stanza.buildNode(tagname, {'xmlns': namespace}));
|
||||
|
||||
}
|
||||
|
||||
cur_node.appendChild(
|
||||
stanza.buildNode(
|
||||
Common.explodeThis('-', item_id, 1),
|
||||
|
@ -723,13 +727,13 @@ var vCard = (function () {
|
|||
try {
|
||||
var iq = new JSJaCIQ();
|
||||
iq.setType('set');
|
||||
|
||||
|
||||
var vCard = iq.appendNode('vCard', {
|
||||
'xmlns': NS_VCARD
|
||||
});
|
||||
|
||||
self._generateTree(NS_VCARD, iq, vCard);
|
||||
|
||||
|
||||
con.send(iq);
|
||||
} catch(e) {
|
||||
Console.error('vCard._sendLegacy', e);
|
||||
|
@ -748,7 +752,7 @@ var vCard = (function () {
|
|||
try {
|
||||
var iq = new JSJaCIQ();
|
||||
iq.setType('set');
|
||||
|
||||
|
||||
// Build Pubsub headers
|
||||
var pubsub = iq.appendNode('pubsub', {'xmlns': NS_PUBSUB});
|
||||
|
||||
|
@ -766,9 +770,9 @@ var vCard = (function () {
|
|||
var vcard = item.appendChild(iq.buildNode('vcard', {
|
||||
'xmlns': NS_IETF_VCARD4
|
||||
}));
|
||||
|
||||
|
||||
self._generateTree(NS_IETF_VCARD4, iq, vcard);
|
||||
|
||||
|
||||
con.send(iq);
|
||||
|
||||
// Make it publicly-viewable
|
||||
|
@ -791,7 +795,7 @@ var vCard = (function () {
|
|||
// Generate some values
|
||||
var photo_bin = $('#USER-PHOTO-BINVAL').val();
|
||||
var photo_data = Base64.decode(photo_bin) || '';
|
||||
|
||||
|
||||
// Data to be sent
|
||||
var send_data = {};
|
||||
send_data[NS_NICK] = $('#USER-NICKNAME').val();
|
||||
|
@ -801,12 +805,12 @@ var vCard = (function () {
|
|||
'id': (hex_sha1(photo_data) || ''),
|
||||
'bytes': (photo_data.length || '')
|
||||
};
|
||||
|
||||
|
||||
// Generate the XML
|
||||
$.each(send_data, function(namespace, data) {
|
||||
var iq = new JSJaCIQ();
|
||||
iq.setType('set');
|
||||
|
||||
|
||||
var pubsub = iq.appendNode('pubsub', {'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) {
|
||||
item = publish.appendChild(iq.buildNode('item', {'xmlns': NS_PUBSUB}));
|
||||
|
||||
|
||||
// Nickname element
|
||||
item.appendChild(iq.buildNode('nick', {'xmlns': NS_NICK}, data));
|
||||
} else if(namespace === NS_URN_ADATA || namespace === NS_URN_AMETA) {
|
||||
item = publish.appendChild(iq.buildNode('item', {'xmlns': NS_PUBSUB}));
|
||||
|
||||
|
||||
// Apply the SHA-1 hash
|
||||
if(send_data[NS_URN_AMETA].id) {
|
||||
item.setAttribute('id', send_data[NS_URN_AMETA].id);
|
||||
}
|
||||
|
||||
|
||||
// Append XML nodes depending on namespace
|
||||
if(namespace === NS_URN_ADATA) {
|
||||
item.appendChild(iq.buildNode('data', {'xmlns': NS_URN_ADATA}, data));
|
||||
} else if(namespace === NS_URN_AMETA) {
|
||||
var metadata = item.appendChild(iq.buildNode('metadata', {'xmlns': NS_URN_AMETA}));
|
||||
|
||||
|
||||
if(data) {
|
||||
var meta_info = metadata.appendChild(iq.buildNode('info', {'xmlns': NS_URN_AMETA}));
|
||||
|
||||
|
||||
if(data.type)
|
||||
meta_info.setAttribute('type', data.type);
|
||||
if(data.id)
|
||||
|
@ -870,62 +874,77 @@ var vCard = (function () {
|
|||
$(document).oneTime(10, function() {
|
||||
$('#vcard input:first').focus();
|
||||
});
|
||||
|
||||
|
||||
// Keyboard events
|
||||
$('#vcard input[type="text"]').keyup(function(e) {
|
||||
// Enter pressed: send the vCard
|
||||
if((e.keyCode == 13) && !$('#vcard .finish.save').hasClass('disabled'))
|
||||
if((e.keyCode == 13) && !$('#vcard .finish.save').hasClass('disabled')) {
|
||||
return self.send();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Click events
|
||||
$('#vcard .tab a').click(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// Yet active?
|
||||
if($(this).hasClass('tab-active'))
|
||||
if(this_sel.hasClass('tab-active')) {
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
// Switch to the good tab
|
||||
var key = parseInt($(this).attr('data-key'));
|
||||
|
||||
var key = parseInt(this_sel.attr('data-key'));
|
||||
|
||||
return self.switchTab(key);
|
||||
});
|
||||
|
||||
|
||||
$('#vcard .avatar-delete').click(function() {
|
||||
return self.deleteAvatar();
|
||||
});
|
||||
|
||||
|
||||
$('#vcard .bottom .finish').click(function() {
|
||||
if($(this).is('.cancel'))
|
||||
var this_sel = $(this);
|
||||
|
||||
if(this_sel.is('.cancel')) {
|
||||
return self.close();
|
||||
if($(this).is('.save') && !$(this).hasClass('disabled'))
|
||||
}
|
||||
|
||||
if(this_sel.is('.save') && !this_sel.hasClass('disabled')) {
|
||||
return self.send();
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
// Avatar upload vars
|
||||
var avatar_options = {
|
||||
dataType: 'xml',
|
||||
beforeSubmit: self.waitAvatarUpload,
|
||||
success: self.handleAvatarUpload
|
||||
};
|
||||
|
||||
|
||||
// Avatar upload form submit event
|
||||
$('#vcard-avatar').submit(function() {
|
||||
if($('#vcard .wait').is(':hidden') && $('#vcard .avatar-info.avatar-wait').is(':hidden') && $('#vcard-avatar input[type="file"]').val())
|
||||
if($('#vcard .wait').is(':hidden') &&
|
||||
$('#vcard .avatar-info.avatar-wait').is(':hidden') &&
|
||||
$('#vcard-avatar input[type="file"]').val()) {
|
||||
$(this).ajaxSubmit(avatar_options);
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
// Avatar upload input change event
|
||||
$('#vcard-avatar input[type="file"]').change(function() {
|
||||
if($('#vcard .wait').is(':hidden') && $('#vcard .avatar-info.avatar-wait').is(':hidden') && $(this).val())
|
||||
if($('#vcard .wait').is(':hidden') &&
|
||||
$('#vcard .avatar-info.avatar-wait').is(':hidden') &&
|
||||
$(this).val()) {
|
||||
$('#vcard-avatar').ajaxSubmit(avatar_options);
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
// Placeholders
|
||||
$('#vcard-avatar input[type="text"]').placeholder();
|
||||
} catch(e) {
|
||||
|
|
|
@ -23,7 +23,7 @@ var Welcome = (function () {
|
|||
/* Variables */
|
||||
self.is_done = false;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Opens the welcome tools
|
||||
* @public
|
||||
|
@ -34,125 +34,125 @@ var Welcome = (function () {
|
|||
try {
|
||||
// Share message
|
||||
var share_msg = Common.printf(Common._e("Using Jappix, an open social platform. I am %s!"), Common.getXID());
|
||||
|
||||
|
||||
// Popup HTML content
|
||||
var html =
|
||||
'<div class="top">' + Common._e("Welcome!") + '</div>' +
|
||||
|
||||
'<div class="tab">' +
|
||||
'<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="3">' + Common._e("Share") + '</a>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="content">' +
|
||||
'<div class="lap-active one-lap welcome1">' +
|
||||
'<div class="infos">' +
|
||||
'<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>' +
|
||||
'</div>' +
|
||||
|
||||
'<a href="#" class="box enabled" title="' + Common._e("Click to disable") + '">' +
|
||||
'<span class="option">' + Common._e("Sounds") + '</span>' +
|
||||
'<span class="description">' + Common._e("Enable notification sounds") + '</span>' +
|
||||
'<span class="image sound talk-images"></span>' +
|
||||
'<span class="tick talk-images"></span>' +
|
||||
'</a>' +
|
||||
|
||||
'<a href="#" class="box enabled pep-hidable" title="' + Common._e("Click to disable") + '">' +
|
||||
'<span class="option">' + Common._e("Geolocation") + '</span>' +
|
||||
'<span class="description">' + Common._e("Share your position on the globe") + '</span>' +
|
||||
'<span class="image geolocation talk-images"></span>' +
|
||||
'<span class="tick talk-images"></span>' +
|
||||
'</a>' +
|
||||
|
||||
'<a href="#" class="box xmpplinks-hidable" title="' + Common._e("Click to enable") + '">' +
|
||||
'<span class="option">' + Common._e("XMPP links") + '</span>' +
|
||||
'<span class="description">' + Common._e("Open XMPP links with Jappix") + '</span>' +
|
||||
'<span class="image xmpp talk-images"></span>' +
|
||||
'<span class="tick talk-images"></span>' +
|
||||
'</a>' +
|
||||
|
||||
'<a href="#" class="box mam-hidable pref" title="' + Common._e("Click to enable") + '">' +
|
||||
'<span class="option">' + Common._e("Message archiving") + '</span>' +
|
||||
'<span class="description">' + Common._e("Store a history of your chats") + '</span>' +
|
||||
'<span class="image mam talk-images"></span>' +
|
||||
'<span class="tick talk-images"></span>' +
|
||||
'</a>' +
|
||||
|
||||
'<a href="#" class="box" title="' + Common._e("Click to enable") + '">' +
|
||||
'<span class="option">' + Common._e("Offline friends") + '</span>' +
|
||||
'<span class="description">' + Common._e("Don\'t hide offline friends") + '</span>' +
|
||||
'<span class="image offline talk-images"></span>' +
|
||||
'<span class="tick talk-images"></span>' +
|
||||
'</a>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="one-lap welcome2">' +
|
||||
'<div class="infos">' +
|
||||
'<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>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="results welcome-results"></div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="one-lap welcome3">' +
|
||||
'<div class="infos">' +
|
||||
'<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("When you will press the save button, the profile editor will be opened. Happy socializing!") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<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="name">Facebook</span>' +
|
||||
'<span class="description">' + Common.printf(Common._e("Share Jappix on %s"), 'Facebook') + '</span>' +
|
||||
'<span class="go talk-images"></span>' +
|
||||
'</a>' +
|
||||
|
||||
'<a class="box share" href="http://twitter.com/intent/tweet?text=' + Common.encodeQuotes(share_msg) + '&url=' + Common.encodeQuotes(Utils.generateURL(JAPPIX_LOCATION)) + '" target="_blank">' +
|
||||
'<span class="logo twitter welcome-images"></span>' +
|
||||
'<span class="name">Twitter</span>' +
|
||||
'<span class="description">' + Common.printf(Common._e("Share Jappix on %s"), 'Twitter') + '</span>' +
|
||||
'<span class="go talk-images"></span>' +
|
||||
'</a>' +
|
||||
|
||||
'<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="name">Google+</span>' +
|
||||
'<span class="description">' + Common.printf(Common._e("Share Jappix on %s"), 'Google+') + '</span>' +
|
||||
'<span class="go talk-images"></span>' +
|
||||
'</a>' +
|
||||
|
||||
'<a class="box share" href="https://waaave.com/spot/jappix/" target="_blank">' +
|
||||
'<span class="logo waaave welcome-images"></span>' +
|
||||
'<span class="name">Waaave</span>' +
|
||||
'<span class="description">' + Common.printf(Common._e("Follow Jappix topic on %s"), 'Waaave') + '</span>' +
|
||||
'<span class="go talk-images"></span>' +
|
||||
'</a>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="bottom">' +
|
||||
'<div class="wait wait-medium"></div>' +
|
||||
|
||||
'<a href="#" class="finish next">' + Common._e("Next") + ' »</a>' +
|
||||
'<a href="#" class="finish save">' + Common._e("Save") + '</a>' +
|
||||
var html =
|
||||
'<div class="top">' + Common._e("Welcome!") + '</div>' +
|
||||
|
||||
'<div class="tab">' +
|
||||
'<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="3">' + Common._e("Share") + '</a>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="content">' +
|
||||
'<div class="lap-active one-lap welcome1">' +
|
||||
'<div class="infos">' +
|
||||
'<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>' +
|
||||
'</div>' +
|
||||
|
||||
'<a href="#" class="box enabled" title="' + Common._e("Click to disable") + '">' +
|
||||
'<span class="option">' + Common._e("Sounds") + '</span>' +
|
||||
'<span class="description">' + Common._e("Enable notification sounds") + '</span>' +
|
||||
'<span class="image sound talk-images"></span>' +
|
||||
'<span class="tick talk-images"></span>' +
|
||||
'</a>' +
|
||||
|
||||
'<a href="#" class="box enabled pep-hidable" title="' + Common._e("Click to disable") + '">' +
|
||||
'<span class="option">' + Common._e("Geolocation") + '</span>' +
|
||||
'<span class="description">' + Common._e("Share your position on the globe") + '</span>' +
|
||||
'<span class="image geolocation talk-images"></span>' +
|
||||
'<span class="tick talk-images"></span>' +
|
||||
'</a>' +
|
||||
|
||||
'<a href="#" class="box xmpplinks-hidable" title="' + Common._e("Click to enable") + '">' +
|
||||
'<span class="option">' + Common._e("XMPP links") + '</span>' +
|
||||
'<span class="description">' + Common._e("Open XMPP links with Jappix") + '</span>' +
|
||||
'<span class="image xmpp talk-images"></span>' +
|
||||
'<span class="tick talk-images"></span>' +
|
||||
'</a>' +
|
||||
|
||||
'<a href="#" class="box mam-hidable pref" title="' + Common._e("Click to enable") + '">' +
|
||||
'<span class="option">' + Common._e("Message archiving") + '</span>' +
|
||||
'<span class="description">' + Common._e("Store a history of your chats") + '</span>' +
|
||||
'<span class="image mam talk-images"></span>' +
|
||||
'<span class="tick talk-images"></span>' +
|
||||
'</a>' +
|
||||
|
||||
'<a href="#" class="box" title="' + Common._e("Click to enable") + '">' +
|
||||
'<span class="option">' + Common._e("Offline friends") + '</span>' +
|
||||
'<span class="description">' + Common._e("Don\'t hide offline friends") + '</span>' +
|
||||
'<span class="image offline talk-images"></span>' +
|
||||
'<span class="tick talk-images"></span>' +
|
||||
'</a>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="one-lap welcome2">' +
|
||||
'<div class="infos">' +
|
||||
'<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>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="results welcome-results"></div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="one-lap welcome3">' +
|
||||
'<div class="infos">' +
|
||||
'<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("When you will press the save button, the profile editor will be opened. Happy socializing!") + '</p>' +
|
||||
'</div>' +
|
||||
|
||||
'<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="name">Facebook</span>' +
|
||||
'<span class="description">' + Common.printf(Common._e("Share Jappix on %s"), 'Facebook') + '</span>' +
|
||||
'<span class="go talk-images"></span>' +
|
||||
'</a>' +
|
||||
|
||||
'<a class="box share" href="http://twitter.com/intent/tweet?text=' + Common.encodeQuotes(share_msg) + '&url=' + Common.encodeQuotes(Utils.generateURL(JAPPIX_LOCATION)) + '" target="_blank">' +
|
||||
'<span class="logo twitter welcome-images"></span>' +
|
||||
'<span class="name">Twitter</span>' +
|
||||
'<span class="description">' + Common.printf(Common._e("Share Jappix on %s"), 'Twitter') + '</span>' +
|
||||
'<span class="go talk-images"></span>' +
|
||||
'</a>' +
|
||||
|
||||
'<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="name">Google+</span>' +
|
||||
'<span class="description">' + Common.printf(Common._e("Share Jappix on %s"), 'Google+') + '</span>' +
|
||||
'<span class="go talk-images"></span>' +
|
||||
'</a>' +
|
||||
|
||||
'<a class="box share" href="https://waaave.com/spot/jappix/" target="_blank">' +
|
||||
'<span class="logo waaave welcome-images"></span>' +
|
||||
'<span class="name">Waaave</span>' +
|
||||
'<span class="description">' + Common.printf(Common._e("Follow Jappix topic on %s"), 'Waaave') + '</span>' +
|
||||
'<span class="go talk-images"></span>' +
|
||||
'</a>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
'<div class="bottom">' +
|
||||
'<div class="wait wait-medium"></div>' +
|
||||
|
||||
'<a href="#" class="finish next">' + Common._e("Next") + ' »</a>' +
|
||||
'<a href="#" class="finish save">' + Common._e("Save") + '</a>' +
|
||||
'</div>';
|
||||
|
||||
|
||||
// Create the popup
|
||||
Popup.create('welcome', html);
|
||||
|
||||
|
||||
// Unavoidable popup
|
||||
$('#welcome').addClass('unavoidable');
|
||||
|
||||
|
||||
// Apply the features
|
||||
Features.apply('welcome');
|
||||
|
||||
|
||||
// Associate the events
|
||||
self.instance();
|
||||
|
||||
|
||||
Console.log('Welcome assistant opened.');
|
||||
} catch(e) {
|
||||
Console.error('Welcome.open', e);
|
||||
|
@ -194,19 +194,20 @@ var Welcome = (function () {
|
|||
var content = welcome + '.content .';
|
||||
var tab = welcome + '.tab ';
|
||||
var wait = $(welcome + '.wait');
|
||||
|
||||
|
||||
$(content + 'one-lap').hide();
|
||||
$(content + 'welcome' + id).show();
|
||||
$(tab + 'a').removeClass('tab-active');
|
||||
$(tab + 'a[data-step="' + id + '"]').addClass('tab-active').removeClass('tab-missing');
|
||||
|
||||
|
||||
// Update the "save" button if all is okay
|
||||
if(!Common.exists(tab + '.tab-missing')) {
|
||||
var finish = welcome + '.finish.';
|
||||
|
||||
$(finish + 'save').show();
|
||||
$(finish + 'next').hide();
|
||||
}
|
||||
|
||||
|
||||
// If this is ID 2: vJUD search
|
||||
if(id == 2) {
|
||||
wait.show();
|
||||
|
@ -235,26 +236,26 @@ var Welcome = (function () {
|
|||
// Sends the options
|
||||
var iq = new JSJaCIQ();
|
||||
iq.setType('set');
|
||||
|
||||
|
||||
var query = iq.setQuery(NS_PRIVATE);
|
||||
var storage = query.appendChild(iq.buildNode('storage', {'xmlns': NS_OPTIONS}));
|
||||
|
||||
|
||||
// Value array
|
||||
var tags = ['sounds', 'geolocation', '', '', 'roster-showall'];
|
||||
|
||||
|
||||
// Build the XML with the array
|
||||
for(var i in array) {
|
||||
var value = array[i];
|
||||
var tag = tags[i];
|
||||
|
||||
|
||||
if((i != 2) && (i != 3) && tag && value) {
|
||||
storage.appendChild(iq.buildNode('option', {'type': tag, 'xmlns': NS_OPTIONS}, value));
|
||||
DataStore.setDB(Connection.desktop_hash, 'options', tag, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
con.send(iq);
|
||||
|
||||
|
||||
// If geolocation is enabled
|
||||
if(array[1] == '1') {
|
||||
PEP.geolocate();
|
||||
|
@ -276,24 +277,27 @@ var Welcome = (function () {
|
|||
try {
|
||||
// Get the new options
|
||||
var array = [];
|
||||
|
||||
|
||||
$('#welcome a.box').each(function() {
|
||||
var current = '0';
|
||||
|
||||
if($(this).hasClass('enabled'))
|
||||
|
||||
if($(this).hasClass('enabled')) {
|
||||
current = '1';
|
||||
|
||||
}
|
||||
|
||||
array.push(current);
|
||||
});
|
||||
|
||||
|
||||
// If XMPP links is enabled
|
||||
if(array[2] == '1')
|
||||
if(array[2] == '1') {
|
||||
Utils.xmppLinksHandler();
|
||||
|
||||
}
|
||||
|
||||
// If offline buddies showing is enabled
|
||||
if(array[4] == '1')
|
||||
if(array[4] == '1') {
|
||||
Interface.showAllBuddies('welcome');
|
||||
|
||||
}
|
||||
|
||||
// If archiving is supported by the server
|
||||
if(Features.enabledMAM()) {
|
||||
// If archiving is enabled
|
||||
|
@ -301,19 +305,19 @@ var Welcome = (function () {
|
|||
MAM.setConfig('roster');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Send the new options
|
||||
self.send(array);
|
||||
|
||||
|
||||
// Close the welcome tool
|
||||
self.close();
|
||||
|
||||
|
||||
// Open the profile editor
|
||||
vCard.open();
|
||||
|
||||
|
||||
// Unavoidable popup
|
||||
$('#vcard').addClass('unavoidable');
|
||||
|
||||
|
||||
self.is_done = true;
|
||||
} catch(e) {
|
||||
Console.error('Welcome.save', e);
|
||||
|
@ -335,10 +339,11 @@ var Welcome = (function () {
|
|||
// Check the next step to go to
|
||||
var next = 1;
|
||||
var missing = '#welcome .tab a.tab-missing';
|
||||
|
||||
if(Common.exists(missing))
|
||||
|
||||
if(Common.exists(missing)) {
|
||||
next = parseInt($(missing + ':first').attr('data-step'));
|
||||
|
||||
}
|
||||
|
||||
// Switch to the next step
|
||||
self.switchTab(next);
|
||||
} catch(e) {
|
||||
|
@ -360,27 +365,37 @@ var Welcome = (function () {
|
|||
try {
|
||||
// Click events
|
||||
$('#welcome .tab a').click(function() {
|
||||
var this_sel = $(this);
|
||||
|
||||
// Switch to the good tab
|
||||
var key = parseInt($(this).attr('data-step'));
|
||||
|
||||
var key = parseInt(this_sel.attr('data-step'));
|
||||
|
||||
return self.switchTab(key);
|
||||
});
|
||||
|
||||
|
||||
$('#welcome a.box:not(.share)').click(function() {
|
||||
if($(this).hasClass('enabled'))
|
||||
$(this).removeClass('enabled').attr('title', Common._e("Click to enable"));
|
||||
else
|
||||
$(this).addClass('enabled').attr('title', Common._e("Click to disable"));
|
||||
|
||||
var this_sel = $(this);
|
||||
|
||||
if(this_sel.hasClass('enabled')) {
|
||||
this_sel.removeClass('enabled').attr('title', Common._e("Click to enable"));
|
||||
} else {
|
||||
this_sel.addClass('enabled').attr('title', Common._e("Click to disable"));
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
$('#welcome .bottom .finish').click(function() {
|
||||
if($(this).is('.next'))
|
||||
var this_sel = $(this);
|
||||
|
||||
if(this_sel.is('.next')) {
|
||||
return self.next();
|
||||
if($(this).is('.save'))
|
||||
}
|
||||
|
||||
if(this_sel.is('.save')) {
|
||||
return self.save();
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
} catch(e) {
|
||||
|
|