Comparar commits

..

334 Commits

Autor SHA1 Mensagem Data
sualko 49ecac9f7b build v2.1.3 2015-09-08 14:26:31 +02:00
Klaus 736119b375 show unread notifications only if the chat window has no focus (fix #212) 2015-08-29 17:54:08 +02:00
Klaus d8733e73d3 fix bookmark loading (fix #211) 2015-08-29 17:29:33 +02:00
Klaus 7f73c45af0 remove deprecated dependencies from example 2015-08-29 17:15:17 +02:00
sualko f8c4bf1d3b build v2.1.2 2015-08-12 10:50:10 +02:00
sualko 3c5ff959e5 update grunt-sass
fix #203

recreate deprecated image-url function with grunt-text-replace
2015-08-12 10:34:06 +02:00
sualko 49cf0eebca build v2.1.1 2015-08-10 13:33:39 +02:00
sualko 4efa02e4ae do not stringify jquery objects
otherwise safari will fail
2015-08-10 13:33:09 +02:00
sualko 3b51e7d7a5 update favico.js 2015-08-10 12:34:23 +02:00
sualko c46e9fc534 add option for online user manual 2015-08-10 12:17:10 +02:00
sualko 03e423f439 fix placeholder replacement 2015-08-10 12:05:35 +02:00
sualko 2f432667e9 rearrange bootstrap import
fix #203
2015-08-10 12:01:13 +02:00
sualko 087e5c819c fix handling of escaped jids
#196
2015-08-07 13:57:15 +02:00
sualko fab9257282 fix undefined error variable in ie 2015-08-05 10:31:48 +02:00
sualko 3feb97b119 update strophe.jinglejs
fix #204
2015-08-05 10:13:47 +02:00
sualko 25667db4be build v2.1.0 2015-07-31 11:11:35 +02:00
sualko c8bf94971b add contributing.md 2015-07-31 10:55:41 +02:00
sualko 4ce384d9b1 fix window opening for auto-join rooms 2015-07-31 10:29:09 +02:00
sualko fc586cff7e Cache initial room configuration (fix #199) 2015-07-30 12:45:27 +02:00
sualko adb4afc8f5 build v2.1.0-beta1 2015-07-21 12:23:44 +02:00
sualko 7888f5ed09 fix handling of failed loadSettings function 2015-07-21 10:59:43 +02:00
sualko b50933b263 add join as URI query type 2015-07-21 10:34:46 +02:00
sualko d203f633f2 Support Reserved Room (XEP-0045#10.1.3)
close #166
2015-07-20 15:27:08 +02:00
sualko 22b7b71204 Merge branch 'develop' of github.com:jsxc/jsxc into develop 2015-07-20 10:45:55 +02:00
Klaus a48f7e6992 Merge pull request #192 from jsxc/bookmarks
[WIP] load bookmarks and attach remove handler
2015-07-20 10:09:46 +02:00
sualko ec33ace031 add bookmark backup storage 2015-07-10 13:44:59 +02:00
sualko a428903a00 Add bookmark options
- edit bookmark
- create bookmark after room was joined
- add bookmark icon
2015-07-09 15:19:15 +02:00
sualko 6bb5a152d7 connect room creation/destruction with bookmarks
- implement bookmark renaming
- delete bookmark on destruction
- add bookmark options to join dialog
- fix room presence
- ignore avatar for rooms
2015-07-09 13:54:42 +02:00
sualko b49d898c9c fix friendship dialog after incoming request 2015-07-08 11:35:15 +02:00
sualko e45aa6ccec load bookmarks and attach remove handler 2015-07-02 11:01:42 +02:00
sualko e16ab27416 fix add buddy dialog, fix debug message 2015-06-27 23:11:03 +02:00
sualko 3ba25a08f6 use bootstrap also in login box 2015-06-27 22:31:02 +02:00
sualko 87b3b1db32 fix unread counter for multiple tabs 2015-06-27 22:18:01 +02:00
sualko 3343044e95 update turn options
- turnCredentialsPath is now deprecated. Use now RTCPeerConfig.url
- ICE servers can now be passed as init option
- fix storage.removeUserElement
2015-06-27 20:05:46 +02:00
sualko 835fa8227c change loadSettings option
- loadSettings is no longer required
- provide callback method for asynchronous requests
2015-06-27 17:05:11 +02:00
sualko 82a28d6aba combine style dependencies in one file 2015-06-27 15:17:44 +02:00
sualko 7c3e4119dd display total number of unread messages in favicon
close #131
2015-06-27 15:17:26 +02:00
sualko 20e9f108e8 change default startMinimized option 2015-06-27 14:24:25 +02:00
sualko dad49f59fb add counter of unread messages to roster and window 2015-06-27 14:23:10 +02:00
sualko 455484e524 add startMinimized and change onlogin option
- add loginForm.startMinimized
- change xmpp.onlogin to loginForm.enable

close #174
2015-06-26 23:24:21 +02:00
sualko e70904b99d use .jsbeautifyrc, add newline to all files 2015-06-26 18:21:12 +02:00
sualko fef58dee3b Merge branch 'develop' of github.com:sualko/jsxc into develop 2015-06-26 17:50:13 +02:00
sualko 995505fc43 fix media failure 2015-06-26 14:28:53 +02:00
sualko c10c9453e9 remove non-spec restriction (fix #188) 2015-06-26 13:44:53 +02:00
sualko ae23b508da add attach if login form was found option 2015-06-25 15:39:46 +02:00
sualko aedb263d2b add roster resize hint, fix roster min init position 2015-06-25 14:03:21 +02:00
sualko 6a93988d15 concatenate strings (fix #163) 2015-06-25 13:16:40 +02:00
sualko 6fc12af3d9 clean up webrtc events 2015-06-24 15:30:13 +02:00
sualko d7daff286b update locales, add ru 2015-06-24 13:22:08 +02:00
sualko d8623963fe fix dsa key generation in chrome > 42 2015-06-24 13:05:21 +02:00
sualko e8da8085a1 fix merge issues 2015-06-24 12:58:53 +02:00
sualko 04e85ee881 Merge branch 'responsive-dialog' into develop
Conflicts:
	.gitignore
	.gitmodules
	Gruntfile.js
2015-06-24 11:27:07 +02:00
sualko efcff4f0be Merge branch 'jingle.js' into develop
- close #176
- replace strophe.jingle with strophe.jinglejs (jingle.js)
2015-06-24 11:13:25 +02:00
sualko ed19a6a323 update strophe.jinglejs, fix turn settings 2015-06-24 11:05:59 +02:00
sualko 54a65ca132 replace strophe.jingle with strophe.jinglejs 2015-06-24 01:56:48 +02:00
sualko 1c10198bb9 fix dev example 2015-06-22 13:14:15 +02:00
sualko f02eea99dd improve dialog styles 2015-06-17 13:28:58 +02:00
sualko e8a6b664c1 make dialog responsive
- replace colorbox with magnific popup
- use parts of bootstrap
2015-06-12 14:35:51 +02:00
sualko 597c6e6346 Add beautifier back to commit task
Add beautifier change detector
2015-06-12 14:28:37 +02:00
sualko d4d8c335e7 move beautifier to watch task 2015-06-11 14:03:19 +02:00
sualko 6b2b5991fc extract templates to single files 2015-06-11 13:48:00 +02:00
sualko 869c3d1fc0 clarify comment (close #182) 2015-06-10 11:34:17 +02:00
sualko fc1b2f4641 improve example 2015-05-27 15:33:52 +02:00
sualko 72a67f034a add css dependencies to build 2015-05-27 15:33:05 +02:00
sualko ce344f6bba add prettysass (#164) 2015-05-26 12:16:27 +02:00
sualko c3f1ff141c beautify javascript (#164) 2015-05-26 12:07:53 +02:00
Klaus a3eee043b3 Merge pull request #164 from jsxc/jsbeautifier
add jsbeautifier
2015-05-26 11:58:16 +02:00
sualko 0c5f405503 build v2.0.1 2015-05-23 16:05:53 +02:00
sualko 499804d53b fix login with different username after dirty logout 2015-05-23 16:02:58 +02:00
sualko 49a6782244 remove ie gradient 2015-05-22 17:22:50 +02:00
sualko 2c9efba0bd some webrtc fixes (fix jsxc/jsxc#173)
- improve video icon update
- fix ff support
2015-05-22 17:01:41 +02:00
sualko b73aeafb5c handle browsers without CSPRNG generator (fix #172) 2015-05-22 14:21:58 +02:00
sualko 616085d2a5 fix ajax login after credential failure 2015-05-22 07:07:05 -04:00
sualko 42c7939474 fix login option, add connecting event, fix template 404 2015-05-20 12:30:36 +02:00
sualko 3538a0ad62 improve login box 2015-05-19 14:51:34 +02:00
sualko 6925034cf3 remove broken mitm detection 2015-05-19 13:25:55 +02:00
sualko 50d5356ee4 revert src files 2015-05-19 13:22:42 +02:00
sualko c242f05afe build v2.0.0 2015-05-08 13:07:02 +02:00
sualko 3b23f20268 fix template variable replacement 2015-05-08 13:04:38 +02:00
sualko 3fba657d40 minor muc style fixes 2015-05-08 12:35:56 +02:00
sualko 3c1ef25e2c update translation 2015-05-08 11:23:16 +02:00
sualko 569ab66016 add missing segment 2015-05-08 11:09:49 +02:00
sualko 84aab421a0 add library credit 2015-05-08 10:56:10 +02:00
sualko 86ad16ef4b fix dependency concatination 2015-05-08 10:21:27 +02:00
sualko 2fe742f169 add missing segment 2015-05-06 15:50:18 +02:00
sualko d7e32cc638 add jsbeautifier to pre_commit hook 2015-05-06 12:02:09 +02:00
sualko 63e271e5e4 add jsbeautifier 2015-05-06 11:13:17 +02:00
Klaus ee93f36a4c Merge pull request #157 from anonimal/bugs/beta
Update jsxc*.js <script src= location in ./example
2015-05-01 13:43:42 +02:00
anonimal bdd4236d1a Update jsxc*.js <script src= location in ./example 2015-04-30 21:26:56 +00:00
Klaus Herberth c2c35b303a build v2.0.0-beta2 2015-04-29 20:07:55 +02:00
Klaus Herberth b9ef5b1a69 prevent false-positive muc service detection 2015-04-29 19:55:26 +02:00
sualko 3e0c752a13 build v2.0.0-beta1 2015-04-29 13:24:32 +02:00
sualko cafbd71c74 fix logout 2015-04-29 12:58:41 +02:00
sualko 423cea6d41 validate room node, fix room renaming 2015-04-29 12:12:04 +02:00
sualko 850febf328 add .wti to .gitignore 2015-04-28 17:19:49 +02:00
sualko 5d1719b92e Merge branch 'develop' 2015-04-28 16:43:10 +02:00
sualko d998e4cacb fix notification request
- prevent double notices
- fix notice function on page reload
2015-04-28 16:41:30 +02:00
sualko eda9ab60de Add offline status (fix #103) 2015-04-28 16:10:30 +02:00
sualko 13a02fa692 using each for emoticons (close #138) 2015-04-28 15:45:56 +02:00
sualko 36c0727828 add username autocomplete (close #143) 2015-04-28 15:38:19 +02:00
Klaus e1ffa79236 Merge pull request #114 from jsxc/muc
XEP-0045 Multi-User Chat
2015-04-28 13:47:28 +02:00
sualko e33e3b4853 Add comments 2015-04-28 13:11:15 +02:00
sualko 62eacdc5ff beautify muc code 2015-04-28 11:07:10 +02:00
sualko 40b5ff344b exception handling, minor fixes
- add translations
- add status messages
- handle message errors
- display subject change
- handle removal from room (ban, kick, ...)
2015-04-27 16:45:07 +02:00
sualko d8ae158d24 querying room info, handle nickname change, several fixes 2015-04-24 15:53:54 +02:00
sualko 5fdb292690 use own avatar placeholder 2015-04-23 17:32:33 +02:00
sualko a0a116901d show and scroll member list 2015-04-23 14:33:11 +02:00
sualko 5a34a0fd2e close a muc room 2015-04-16 18:13:20 +02:00
sualko 5435326fb9 discover muc server support 2015-04-16 15:09:33 +02:00
sualko ff453821bf handle muc error conditions 2015-04-14 16:13:02 +02:00
sualko 03ac47a264 fix nonexisting resource 2015-04-09 15:56:38 +02:00
sualko a17f046a92 muc design + muc leave function 2015-04-09 15:44:41 +02:00
sualko 1b0db86edf add room discovery 2015-04-08 13:42:47 +02:00
sualko 77863d7a27 muc adaptations to sass and i18n 2015-03-31 15:26:18 +02:00
sualko 03435fce9c fix dependencies 2015-03-31 15:15:46 +02:00
sualko f9598604e2 Merge remote-tracking branch 'origin/develop' into muc 2015-03-31 15:08:31 +02:00
sualko edd715b993 fix video calls 2015-03-30 13:28:58 +02:00
sualko a8b777e5b7 fix selection of chat message (fix #129) 2015-03-30 13:28:45 +02:00
sualko 3282285b3c fix login from login box 2015-03-08 13:23:16 +01:00
sualko 564aa7cd8a Show notifications if tab has no focus (close #130) 2015-03-08 10:42:02 +01:00
sualko 81047222c6 Use user avatar for notification icon 2015-03-08 02:02:50 +01:00
sualko 329f55978f add resize handler 2015-03-08 01:09:45 +01:00
sualko 01b14279b3 fix roster item duplicates on relogin 2015-03-08 00:38:40 +01:00
sualko 630bb45eb1 set emoticons inline 2015-03-07 22:45:00 +01:00
sualko 779103ed32 fix video calls 2015-03-07 15:41:04 +01:00
sualko fbd0511a76 Add dev example 2015-03-06 12:52:12 +01:00
sualko da0a7d7b5d fix translations 2015-03-06 12:51:48 +01:00
Klaus da020726ec Merge pull request #136 from jsxc/code-organisation
code organisation
2015-03-06 11:30:43 +01:00
sualko 79f05a0799 move files to src 2015-03-04 11:01:42 +01:00
sualko 2d832d1752 split files into namespaces 2015-03-03 15:26:39 +01:00
sualko 550485c07c update example 2015-03-02 22:01:23 +01:00
sualko 3566972527 convert quotes to apostrophes 2015-03-02 17:28:42 +01:00
sualko ca21753d73 fix get template 2015-03-02 17:28:42 +01:00
sualko 70abb7121c Merge branch 'master_upstream_i18next' of https://github.com/Zauberstuhl/jsxc (#123) into develop 2015-03-02 17:28:03 +01:00
sualko 4e9c802da9 build v1.1.0a 2015-02-25 19:15:41 +01:00
sualko 651c138b97 fix css url path (close #134) 2015-02-25 19:14:50 +01:00
Lukas Matt 318bd7ee7d Updated locales from webtranslateit 2015-02-19 14:07:53 +01:00
Lukas Matt 7929b20516 Replaced jsxc.translate function with i18next 2015-02-19 13:54:13 +01:00
Lukas Matt 20c8d0e2f6 Add grunt merge task and i18n dependency 2015-02-19 13:54:13 +01:00
Lukas Matt 3628cd751a Remove diaspora customization 2015-02-19 13:54:13 +01:00
Lukas Matt 996ae30df8 Fixed i18next fallback lng setting 2015-02-19 13:54:13 +01:00
Lukas Matt 7b32d598e4 Updated i18next translations
* updated german and french locales
2015-02-19 13:54:13 +01:00
Lukas Matt 5edf4c2368 Renamed Greek language file 2015-02-19 13:54:13 +01:00
Lukas Matt 9bec4084d8 Create own replace task for locales
Using regular expression to avoid unintentional replacements
2015-02-19 13:54:13 +01:00
Lukas Matt 700e62c9d4 Updated i18next translations
* new el-GR, fr, nds, pt-BR
* updated de, en, es

Conflicts:
	locales/es.json
2015-02-19 13:54:13 +01:00
Lukas Matt 9fa16fca40 Update i18next initialization with resStore option 2015-02-19 13:54:13 +01:00
Lukas Matt 5f0b2c8a35 Remove old translation from webrtc lib 2015-02-19 13:54:13 +01:00
Lukas Matt f41faaf9af Add merge_data task for locales to grunt build
Conflicts:
	Gruntfile.js
2015-02-19 13:54:13 +01:00
Lukas Matt 3dd2b14e5a Renamed locale files 2015-02-19 13:54:13 +01:00
Lukas Matt 3d2fa05b1f Add I18next global to jshint 2015-02-19 13:54:13 +01:00
Lukas Matt f8888fdbb2 Update .gitignore 2015-02-19 13:54:13 +01:00
Lukas Matt 8e5e90032c Add i18next submodule to repo 2015-02-19 13:54:13 +01:00
Lukas Matt 86df085723 Adjust Gruntfile and add dep and license information
Conflicts:
	Gruntfile.js
2015-02-19 13:54:13 +01:00
Lukas Matt b57ab86b8f Add global variables to jshint exception file 2015-02-19 13:54:13 +01:00
Lukas Matt 79c1a76427 Initial i18n library and set fallback language to en 2015-02-19 13:54:13 +01:00
Lukas Matt 7acca71a45 Replace internal translation with i18next
Conflicts:
	jsxc.lib.js
2015-02-19 13:54:12 +01:00
Lukas Matt 925ff098d0 Remove old translation from jsxc
Conflicts:
	jsxc.lib.js
2015-02-19 13:54:12 +01:00
Lukas Matt 4edcc578aa Add locale files
* german
* english
* spanish
2015-02-19 13:54:12 +01:00
Klaus 153f045b00 Update example.js 2015-02-16 10:19:26 +01:00
sualko ba03261f1e remove css folder 2015-02-08 21:20:58 +01:00
sualko 50fe563e1a build v1.1.0
close #124
2015-02-08 20:06:06 +01:00
sualko 31c9b29521 fix typo 2015-02-08 20:00:21 +01:00
Klaus b1ce729ec9 Update README.md 2015-02-08 19:54:43 +01:00
Klaus ffc3678cb9 Merge pull request #126 from shaggybb/master
Avoid duplicate window list
2015-02-08 19:42:34 +01:00
Iván Rubio 5772868738 Avoid duplicate window list 2015-02-08 19:41:11 +01:00
Iván Rubio 4529f71896 Avoid duplicate window list 2015-02-06 15:01:56 +01:00
sualko 8b53842bcd fix delayed timestamp (fix #125) 2015-02-06 14:52:50 +01:00
sualko 5c2bc52b55 build v1.1.0-beta 2015-02-03 12:04:27 +01:00
sualko e704f4d05a fix timestamp margin 2015-02-03 12:01:16 +01:00
sualko fa3febf0b6 fix example 2015-02-01 22:46:16 +01:00
sualko 2814cfb36e fix otr enable option 2015-02-01 22:11:28 +01:00
sualko 8aa2736e4a fix webrtc icon error (fix #111) 2015-02-01 22:09:40 +01:00
sualko a2b216443a clean up event handler on disconnect 2015-01-31 21:27:52 +01:00
sualko 487e32a7b9 add ajax/prebind login (close #98, close #92) 2015-01-31 21:27:23 +01:00
sualko 2950c747c9 update gruntfile
- rename default task to build
2015-01-29 11:15:47 +01:00
sualko f39cc79dff fix hide offline contacts, add css prefixes 2015-01-29 11:14:18 +01:00
sualko b62eb995d8 Merge branch 'dimaursu-scss' 2015-01-29 10:24:10 +01:00
sualko e45aa41ae8 replace group colors (#122) 2015-01-27 13:25:30 +01:00
sualko ee1d70a1db change color dependency 2015-01-21 18:21:55 +01:00
sualko 66b5ebda32 rename color names (#122)
- fix style issues
- use image-url function
- create jsxc and webrtc module
2015-01-21 16:47:09 +01:00
sualko 08beae250b update example 2015-01-20 11:59:37 +01:00
sualko 3de204d857 revert to core style
- remove grunt-merge-data
- replace color values with var
- revert diaspora stuff
2015-01-20 11:59:16 +01:00
Dumitru Ursu a2fe0b9383 Reorganize colors variables
Fix merge conflict
2015-01-18 19:57:59 +02:00
Dumitru Ursu e655247a01 Add new css task
Fix jsxc conflict
2015-01-18 19:57:54 +02:00
Dumitru Ursu 27eefde3b3 Fix packages conflict
Fix css merge conflict

Fix grunt merge conflict
2015-01-18 19:57:37 +02:00
sualko 708648e414 fix reconnection 2015-01-17 20:42:17 +01:00
sualko 6e9fcf2518 fix timestamp design & update otr 2015-01-17 17:31:49 +01:00
sualko d7316e895a fix backward compatibility 2015-01-16 19:39:54 +01:00
sualko 01c34f46dd handle delayed messages 2015-01-16 19:32:45 +01:00
sualko 65305f3609 Merge branch 'message_timestamp_upstream' of https://github.com/Zauberstuhl/jsxc into Zauberstuhl-message_timestamp_upstream 2015-01-16 17:03:11 +01:00
sualko 2cd5b5764a concat avatar chunks (close #113)
thanks @IllusionPerdu
2015-01-16 17:01:16 +01:00
Lukas Matt a52fe9884b Fixed appending date location 2015-01-14 11:50:50 +01:00
Lukas Matt c95e117857 Move time formatting to extra function
* remove date if it is the same day
2015-01-14 11:50:50 +01:00
Lukas Matt 5f2d4ce7a6 Fixed timestamp convert and tweaked appearance 2015-01-14 11:50:50 +01:00
Lukas Matt d988621b4d Add timestamp to every message
Conflicts:
	jsxc.css
	jsxc.lib.js
2015-01-14 11:50:44 +01:00
sualko 9d40ed8086 fix window, incoming msg 2015-01-13 13:20:21 +01:00
Klaus Herberth 9750a558f2 update example (fix #115) 2015-01-01 23:10:34 +01:00
sualko feb0c634a4 Merge branch 'master' into muc 2014-12-17 13:14:37 +01:00
sualko 89c6e28970 add option to disable otr (close #89)
Set display:none for .jsxc_transfer to remove padlock
2014-12-17 13:09:05 +01:00
Klaus 5224cdf30c Merge pull request #109 from sualko/xep-0280-carbons
XEP-0280 carbons
2014-12-17 12:51:36 +01:00
sualko c85ef77c21 cc enhancements
- ignore forwarded otr messages
- change default otr options
- add forwarded/encrypted class to message
2014-12-17 12:49:19 +01:00
sualko cebcc61496 add user setting for carbons 2014-12-16 13:26:08 +01:00
sualko 7cf71a7c8b add carbons option and handle prosody diso issue 2014-11-18 17:11:18 +01:00
Klaus 4bffcd665c Merge pull request #104 from Zauberstuhl/fix_var_declaration
Fix variable declaration
2014-11-18 12:05:43 +01:00
Lukas Matt 4fb9938049 Variable 'src' was used before it was defined 2014-11-17 23:43:18 +01:00
sualko 419eb17f65 implement xep-0280 and xep-0297 2014-11-14 17:42:34 +01:00
sualko 20cc517457 fix disco response with unknown node name for caps 2014-11-13 14:17:30 +01:00
sualko a30bcffeec Fix offline subscription request (fix #102) 2014-11-13 11:43:32 +01:00
Klaus e1f4d1d811 Merge pull request #100 from Zalmoxisus/master
Show avatar also by EXTVAL (url), not only by BINVAL
2014-11-11 17:04:29 +01:00
Zalmoxisus dea3a30149 Little fix 2014-11-11 15:12:10 +02:00
Zalmoxisus 2c2e13d966 Show avatar also by EXTVAL (url), not only by BINVAL
Many sites have already the user avatar url, and in such case it’s good
to use just url, not to generate and store another blob.
2014-11-11 01:49:46 +02:00
sualko 65c0b7a57a update muc to current interface 2014-11-07 15:06:57 +01:00
sualko 2b6dd690f4 build v1.0.0 2014-11-06 14:16:16 +01:00
Klaus Herberth 292e7646b6 fix duplicates on roster change 2014-11-05 23:16:17 +01:00
Klaus Herberth 9c137be6ae stop propagation 2014-11-05 23:11:22 +01:00
sualko c711167d3f fix own presence color 2014-11-04 15:44:49 +01:00
sualko 4c388212eb add default xmpp priorites to options 2014-11-04 15:41:36 +01:00
sualko b843aa2f03 fix jsxc.options.get 2014-11-04 15:35:36 +01:00
sualko 8d1fba000a update and generate doc 2014-11-04 15:32:23 +01:00
sualko e9f0634d29 remove flash check 2014-11-04 12:54:42 +01:00
sualko a69b70af1e build 1.0.0-beta2 2014-10-31 14:05:12 +01:00
sualko 341db9e625 change position of message trigger 2014-10-31 13:54:45 +01:00
sualko 67d2c12640 preventDefault for dialog and clean otr list 2014-10-31 13:39:14 +01:00
sualko c0fae24dcd change cursor to pointer for some elements 2014-10-31 13:23:41 +01:00
Klaus 05d9aaa01d fix update video icon 2014-10-30 23:02:40 +01:00
sualko 8cd97ec3e1 build 1.0.0-beta1 2014-10-29 14:13:39 +01:00
sualko 58e2fccf95 add new event restoreCompleted.jsxc 2014-10-29 11:48:25 +01:00
sualko 4b541d462a fix emoticon size from #86 2014-10-29 11:15:20 +01:00
Klaus 310ac4e0a6 Merge pull request #86 from Zauberstuhl/rails_assets
In respect of rails assets we should define images in css
2014-10-29 11:12:15 +01:00
sualko 53b44961ea support vcard retrieval from unknown jid 2014-10-29 11:08:58 +01:00
sualko 8271e64cf7 fix vcard on second tab 2014-10-29 10:51:49 +01:00
sualko 27438984e1 disable webrtc on second tab 2014-10-28 16:11:59 +01:00
sualko 0fb7de74ce fix otr enable 2014-10-28 16:10:58 +01:00
sualko 3db02b0560 Add spot to messages and add some translations 2014-10-28 15:30:17 +01:00
sualko e2dfb6bc94 Add email spot 2014-10-24 17:28:21 +02:00
sualko 55dbbdb636 Handle unknown jids 2014-10-24 16:37:25 +02:00
sualko 308ccc1426 Add has-come-online notification 2014-10-24 14:22:36 +02:00
sualko 7f1a011b1b improve notifications
- sync sound and message
- add icon
2014-10-24 13:52:39 +02:00
sualko d102d41f6b detec uri scheme in message 2014-10-23 14:57:03 +02:00
sualko 91def2febc detect xmpp: url in message 2014-10-23 14:47:40 +02:00
sualko 7ea444276b add uri query actions 2014-10-23 12:29:06 +02:00
sualko f810a8a28f fix opened flag 2014-10-23 11:11:20 +02:00
sualko 2acf47a872 add opened flag to toggle list 2014-10-23 00:58:35 +02:00
sualko 906136245a Implement XEP-0147 URI Scheme Query (close #39) 2014-10-21 16:52:50 +02:00
sualko a053753e10 detect email in message 2014-10-20 13:13:22 +02:00
sualko e996296b7f add unread flag to roster and scroll to target window 2014-10-16 13:04:58 +02:00
sualko d4a31dc8fc end all private conversations on logout 2014-10-15 15:49:59 +02:00
sualko c8ca2734e0 handle loadSettings failure 2014-10-15 14:20:32 +02:00
sualko 03e8ae8d1d remove email pattern from contact dialog 2014-10-15 13:17:57 +02:00
sualko d626eb355f improve smp 2014-10-15 13:00:04 +02:00
sualko 862c124366 esc closes window 2014-10-15 11:21:30 +02:00
Lukas Matt 3c2cf893be Adjust css namespace to jsxc 2014-10-14 23:24:36 +02:00
Lukas Matt ac8f014377 In respect of rails assets we should define images in css 2014-10-14 19:28:10 +02:00
sualko d0e16c0a2a fix window toggle in video mode 2014-10-14 17:14:36 +02:00
sualko cb926a1dec fix video icon 2014-10-14 16:56:16 +02:00
sualko 7aac1d6c28 set focus to input on textarea click 2014-10-09 12:58:42 +02:00
sualko 25a982f9c3 request notification permission silent 2014-10-09 12:54:46 +02:00
sualko 76da9c0fd1 improve video window
- add loader
- update video icon on presence
- slide chat
- cancel call on ice failure
- fix info for initiator
- only request available user media (chrome)
2014-10-09 12:33:23 +02:00
sualko a9d167acda Merge branch 'video-window-design' of https://github.com/sualko/jsxc 2014-10-09 08:22:34 +02:00
sualko 32960f39b0 fix non-square avatars (close #68) 2014-10-08 15:22:19 +02:00
sualko 3e1c1ded67 improve login box (close #82) 2014-10-08 15:06:52 +02:00
sualko e19da058f6 vCard: swap top and bottom (close #69) 2014-10-08 14:31:33 +02:00
sualko 80b5a4a350 replace user identifier (fix #78)
from css id to bar jid.
2014-10-08 14:05:40 +02:00
sualko 5c10a738cb Merge branch 'MarcelWaldvogel-language-update' 2014-09-24 13:43:03 +02:00
sualko 855b776ca2 update language vars 2014-09-24 13:38:37 +02:00
sualko 735016e676 Merge branch 'language-update' of git://github.com/MarcelWaldvogel/jsxc into MarcelWaldvogel-language-update 2014-09-24 13:18:51 +02:00
sualko 46897f0e66 handle resource case sensitive 2014-09-24 12:58:36 +02:00
sualko f1918e06cb add disco dtls feature (#65) 2014-09-24 12:28:58 +02:00
Klaus Herberth 3405d0e3c2 move chat window beside video 2014-09-17 11:36:30 +02:00
Marcel Waldvogel c280251e3c Language update
More consistent and user-friendly language (EN, DE) and dialog layout
2014-09-14 12:30:34 +02:00
sualko 0954c245c3 build v1.0.0-alpha1 2014-09-08 14:25:21 +02:00
sualko 1aa44434b3 intercept ff snapshot security error 2014-09-08 14:21:59 +02:00
sualko c1bd08b3e4 minor style change 2014-09-08 06:31:41 -04:00
sualko f298364a37 fix message delivery (close #17)
- Show warning if we receive an encrypted message with unknown instance tag
- Enable ake on received otr error
2014-09-08 10:57:12 +02:00
sualko e061670880 add bouncing effect to notice 2014-09-08 10:29:02 +02:00
sualko 6680283cea minor window scrollbar improvement
- hide unneeded buttons
- update sb after window is closed
2014-09-08 10:05:21 +02:00
Klaus Herberth cb6b1345e0 fix cross-browser visible api
- test type of document.hidden
2014-09-07 11:38:28 +02:00
sualko 09a83236ab add scrollbar to window list 2014-09-05 15:40:03 +02:00
sualko a68bae3288 generate dsa key in background (close #45) 2014-09-04 15:52:39 +02:00
sualko a7f4073f0b fix wrong avatars 2014-09-04 11:11:06 +02:00
sualko 8248854ce7 make chat window resizable
- update jquery.slimscroll.js
- use jquery resizable
2014-09-02 16:16:40 +02:00
sualko 88f225f564 minor webrtc fixes
- fix incoming call window
- add information to chat window
- update strophe.jingle
2014-09-02 14:09:57 +02:00
sualko 8c1ba13449 fix caps node property 2014-09-02 13:18:46 +02:00
sualko eb7cef099b Display more information per user 2014-09-02 13:12:07 +02:00
sualko 8ae8d2f7bf add translation 2014-09-02 11:04:58 +02:00
sualko 33d41e2a84 build v0.8.2 2014-08-20 12:05:34 +02:00
sualko ca816760c8 add translation 2014-08-20 12:01:49 +02:00
sualko 31d6121273 update example 2014-08-19 13:39:39 +02:00
sualko 8bc299739d allow string|boolean as config param 2014-08-19 13:39:03 +02:00
sualko 263cb2ecb7 update grunt
abort if console.log is found or if no entry for current version exists in CHANGELOG.md
2014-08-19 12:54:53 +02:00
sualko c7e37147a7 write log to console only if debug flag is set 2014-08-19 12:48:48 +02:00
sualko 34c880aa5c use custom username (fix sualko/jsxc#58) 2014-08-19 12:16:31 +02:00
sualko 165dba73a4 build v0.8.1 2014-08-12 16:20:22 +02:00
sualko f2770d7a44 allow user to define xmpp & permanent settings 2014-08-12 15:42:17 +02:00
sualko b7c4cac550 generalize fieldset style & add readonly style 2014-08-12 15:32:38 +02:00
sualko 656a82cf17 remove pass-icon 2014-08-12 15:31:29 +02:00
sualko 3d4ece2561 remove trace call 2014-08-07 12:12:32 +02:00
sualko 52b16e9ef0 add example 2014-07-03 13:00:51 +02:00
sualko a07347cc22 fix login form without id submit 2014-07-03 12:59:43 +02:00
sualko aa8bcf52de build v0.8.0 2014-07-02 12:10:13 +02:00
sualko 2060b8ac69 add translation for vCard 2014-07-02 12:09:46 +02:00
sualko 8776ad565d add expand triangle 2014-07-02 11:34:45 +02:00
Klaus 2e94cf6ba0 Add missing spanish translation 2014-06-30 13:15:31 +02:00
sualko 89bd4cdc48 build v0.8.0-beta 2014-06-27 15:34:27 +02:00
sualko 9d87d90141 adjust jsxc root and add sound files 2014-06-27 12:26:14 +02:00
sualko b6e4a6baca fix priority issue (46116a3e8d) 2014-06-27 12:18:43 +02:00
sualko 4dc319502f looking for username and password field (fix #47) 2014-06-26 15:17:55 +02:00
sualko 98e9f77074 use browser input check for contact dialog 2014-06-26 15:00:22 +02:00
sualko 37ac46f55b Add hint if roster is empty 2014-06-26 13:15:44 +02:00
sualko 92309b90be Add fingerprint explanation 2014-06-26 12:36:50 +02:00
sualko dc1a79e294 Add hint to browser-allow-button 2014-06-26 11:49:59 +02:00
sualko 5813f336a2 add close button to verification 2014-06-25 15:18:48 +02:00
sualko 46116a3e8d add support for priorities (#48) 2014-06-25 15:13:02 +02:00
sualko cfc9d5a77d show notice if no vCard is available 2014-06-25 12:51:22 +02:00
sualko 08c660a1ae fix chat in video window 2014-06-25 12:40:01 +02:00
sualko 2140f8ad72 grayscale for one-side subscription 2014-06-25 12:14:15 +02:00
Klaus de2eb4c7ba Merge pull request #50 from sualko/expand_roster_item
Merge expandable roster
2014-06-25 12:00:55 +02:00
sualko 075f29b040 fix rename field 2014-06-25 11:54:26 +02:00
sualko 2ceb2ab3a6 gui fixes
- enable/disable video icon
- adjust window highlighting
- css clean up
2014-06-23 13:52:38 +02:00
sualko 21153db52d add icons to expand item 2014-06-12 14:18:33 +02:00
sualko 45ed711ad8 add expand icon 2014-06-12 13:01:51 +02:00
sualko bdf8ead441 clean up stylesheet 2014-06-12 12:09:48 +02:00
Klaus Herberth 73116b0b33 fix ie input field 2014-06-12 00:08:41 +02:00
sualko 995133c4d2 enhance window icons 2014-06-10 16:37:22 +02:00
sualko 4d396d4133 fix margin between sys and normal msg 2014-06-10 12:33:49 +02:00
sualko de1c264c2b minor window design changes 2014-06-06 15:18:42 +02:00
sualko c6e050ab7c fix multiple emoticon issues
- change default replacement according to XEP-0038
- handle multiple emoticons (prevent double replacement)
- add thumbsdown, rose, music
2014-06-06 10:22:10 +02:00
sualko 97555780c5 enhance window design 2014-06-05 14:51:40 +02:00
Klaus 14338ededa Merge pull request #41 from johangm90/master
Change chat message design
2014-06-04 18:38:45 +02:00
sualko e7b087e8fe Add function to display vCard 2014-06-04 17:33:38 +02:00
johangm90 94f49dabef New chat window design 2014-06-03 18:56:28 -05:00
Klaus c0cd443a3d Merge pull request #40 from johangm90/master
add spanish translation
2014-06-03 15:21:00 +02:00
johangm90 2f023cda05 spanish translation
spanish translation

spanish translation
2014-06-03 08:03:08 -05:00
Klaus 03ca06ce25 Remove redundant content (homepage) 2014-06-02 00:40:37 +02:00
219 arquivos alterados com 134451 adições e 15485 exclusões
+4
Ver Arquivo
@@ -0,0 +1,4 @@
{
"directory": "lib/",
"analytics": false
}
+12
Ver Arquivo
@@ -1 +1,13 @@
node_modules
*.zip
*.zip.sig
bower_components
archives/
/css/
dev/
.wti
*~
/tmp/
lib/favico.js/
lib/strophe.bookmarks/
lib/strophe.x/
+12 -3
Ver Arquivo
@@ -1,6 +1,15 @@
[submodule "lib/strophe.jingle"]
path = lib/strophe.jingle
url = https://github.com/sualko/strophe.jingle.git
[submodule "lib/otr"]
path = lib/otr
url = https://github.com/sualko/otr.git
[submodule "lib/i18next"]
path = lib/i18next
url = https://github.com/i18next/i18next.git
[submodule "lib/bootstrap"]
path = lib/bootstrap
url = https://github.com/twbs/bootstrap-sass/
[submodule "lib/magnific-popup"]
path = lib/magnific-popup
url = https://github.com/dimsemenov/Magnific-Popup
[submodule "lib/strophe.jinglejs"]
path = lib/strophe.jinglejs
url = https://github.com/sualko/strophe.jinglejs
+5
Ver Arquivo
@@ -0,0 +1,5 @@
{
"indent_size": 3,
"indent_char": " ",
"end_with_newline": true
}
+7 -2
Ver Arquivo
@@ -14,11 +14,15 @@
"multistr": true,
"devel": true,
"globals": {
"t":true,
"i18n":true,
"I18next":true,
"OTR":true,
"DSA":true,
"Worker":true,
"BigInt":true,
"Notification":true,
"$": true,
"jQuery":true,
"Strophe":true,
"localStorage":true,
@@ -29,6 +33,7 @@
"jsxc":true,
"getUserMediaWithConstraints":true,
"setupRTC":true,
"SDPUtil":true
"SDPUtil":true,
"getSelection":true
}
}
}
+171 -1
Ver Arquivo
@@ -1,3 +1,173 @@
v2.1.3 / 2015-09-08
===
- fix bookmark loading
- show unread notifications only if the chat window has no focus
v2.1.2 / 2015-08-12
===
- update grunt-sass (fix invalid css)
v2.1.1 / 2015-08-10
===
- update strophe.jingle (fix login with safari and older versions of ie, ff, chrome)
- update favico.js
- fix undefined error variable in ie
- fix handling of escaped jids (e.g. used in transports)
- fix placeholder replacement
- rearrange bootstrap import
- add option for custom online user manual
v2.1.0 / 2015-07-31
===
- add bookmark feature for rooms (XEP-0048)
- add reserved room feature for muc (XEP-0045#10.1.3)
- add counter of unread messages to roster, window and favicon
- add join as URI query type
- add ru language
- add roster resize hint
- make dialog responsive
- allow messages to persons without valid friendship
- replace video library for more stable connection
- fix dsa key generation in chrome > 42
- fix minor roster ui issues
- add jsbeautifier and prettysass
- improve example
- extract templates to single files
- replace colorbox with magnific popup
- use parts of bootstrap
- replace strophe.jingle with strophe.jinglejs (jingle.js)
- concatenate strings for better translatability
- add new option attach if login form was found
- add new option loginForm.startMinimized
- add new option loginForm.enable (deprecates xmpp.onlogin)
- add new option RTCPeerConfig.url (deprecates turnCredentialsPath)
- ICE servers can now be passed as init option
- loadSettings option is no longer required and supports now async requests
v2.0.1 / 2015-05-23
===
- improve login box
- fix browsers without CSPRNG generator
- fix ajax login after credential failure
- fix some webrtc issues
- fix login with different username after dirty logout
- remove ie (<11) gradient
- remove broken mitm detection
- fix temporary template 404
- fix login option
- add connecting event
v2.0.0 / 2015-05-08
===
- add multi-user chat (XEP-0045)
- add window resize handle
- add username autocomplete
- add offline state
- add Italian, French, Polish, Portuguese/Brazil
- use user avatar as notification icon
- show notifications if tabs has no focus
- split files into namespaces
- sass improvements
- replace own translation engine with i18next
- fix login from login box
- fix selection of chat messages
- fix video calls
- fix emoticons
- fix duplicated roster items
- fix notification request
- fix logout
v1.1.0a / 2015-02-25
===
- fix css url path
v1.1.0 / 2015-01-08
===
- move from plain css to sass
- show avatar also by EXTVAL (url), not only by BINVAL
- add XEP-0280 (Message Carbons)
- add XEP-0297 (Stanza Forwarding)
- add option to disable otr
- add timestamp to messages
- add ajax/prebind login
- fix offline subscription request
- fix hide offline contacts
- fix error with multiple own resources
- fix avatars with newlines
v1.0.0 / 2014-11-06
===
- add unread flag to roster and scroll to target window
- add XEP-0147 URI Scheme Query support
- add has-come-online notification
- add silent notification request
- add more information in vCard view
- add resizable function to chat window
- add vertical scrollbar to window list
- add call information to chat window
- add concatinated and uglified files
- add translations
- minor video call improvements
- minor style improvements
- generate dsa key complete in background
- update caps node property to jsxc.org
- update strophe.jingle
- update otr
- fix wrong avatars
- fix minor message delivery errors
- fix ff snapshot security error
- fix case sensitive resource handling
- fix non-square avatars
- fix several video issues
- fix messages from unknown (not in roster) jid
- fix vcard retrieval from unknown (not in roster) jid
- fix vcard in second tab
- fix jids with non-word characters (replace user identifier)
- improve video window design
- improve user info
- improve login box
- improve smp user interaction
- improve notifications (sync sound/message, icon)
- minor chat window improvements
- detect email in message
- detect uri scheme in message
- end all private conversations on logout
- remove email pattern from contact dialog
- disable video on second tab
- add/require disco dtls feature for webrtc
- move emoticons to css
- handle loadSettings failure
- change cursor for some elements
- prevent event bubbling for dialog
v0.8.2 / 2014-08-20
===
- fix use of custom username
- write to console only if debug flag is set
- allow string|boolean as config param
- add translations
v0.8.1 / 2014-08-12
===
- add user-defined xmpp options
- fix login form without id submit
v0.8.0 / 2014-07-02
===
- add spanish translation
- add vCard view
- add more emoticons
- add grayscale to buddies without subscription
- add settings for priorities
- add hint if roster is empty
- add sound files
- new chat window design
- enhanced roster design
- fix emoticon replacement (XEP-0038)
- fix some ui issues (explanations,...)
- fix issue with password only field
v0.7.2 / 2014-05-28
===
- fix login issue
@@ -69,4 +239,4 @@ v0.5.1 / 2014-01-27
- handle already attached submit events on login form
- style changes
- fix webrtc startup
- don't block application on dsa key generation
- don't block application on dsa key generation
+1
Ver Arquivo
@@ -0,0 +1 @@
You find all information in our [contributor guide](https://github.com/jsxc/jsxc/wiki/Contributor-Guide).
+330 -12
Ver Arquivo
@@ -1,12 +1,20 @@
/* global module:false */
module.exports = function(grunt) {
var dep = grunt.file.readJSON('dep.json');
var dep_files = dep.map(function(el) {
return '<%= target %>/' + el.file;
});
var git_cached = [];
// Project configuration.
grunt.initConfig({
app: grunt.file.readJSON('package.json'),
meta: {
banner: grunt.file.read('banner.js')
},
target: 'dev',
jshint: {
options: {
jshintrc: '.jshintrc'
@@ -14,18 +22,28 @@ module.exports = function(grunt) {
gruntfile: {
src: 'Gruntfile.js'
},
files: [ 'jsxc.lib.webrtc.js', 'jsxc.lib.js' ]
files: ['src/jsxc.lib.*.js']
},
copy: {
main: {
files: [ {
files: [{
expand: true,
src: [ 'lib/strophe.jingle/*.js', 'lib/otr/build/**', 'lib/otr/lib/dsa-webworker.js', 'lib/otr/lib/sm-webworker.js', 'lib/otr/lib/const.js', 'lib/otr/lib/helpers.js', 'lib/otr/lib/dsa.js', 'lib/otr/vendor/*.js', 'lib/*.js', 'jsxc.lib.js', 'jsxc.lib.webrtc.js', '*.css', 'LICENSE', 'img/**' ],
dest: 'build/'
} ]
src: ['lib/i18next/release/i18next-latest.min.js', 'lib/magnific-popup/dist/*.js', 'lib/favico.js/favico.js', 'lib/strophe.x/*.js', 'lib/strophe.bookmarks/*.js', 'lib/strophe.jinglejs/*-bundle.js', 'lib/otr/build/**', 'lib/otr/lib/dsa-webworker.js', 'lib/otr/lib/sm-webworker.js', 'lib/otr/lib/const.js', 'lib/otr/lib/helpers.js', 'lib/otr/lib/dsa.js', 'lib/otr/vendor/*.js', 'lib/*.js', 'LICENSE', 'img/**', 'sound/**'],
dest: '<%= target %>/'
}, {
expand: true,
cwd: 'lib/',
src: ['*.css'],
dest: '<%= target %>/css/'
}, {
expand: true,
cwd: 'lib/magnific-popup/dist/',
src: ['*.css'],
dest: '<%= target %>/css/'
}]
}
},
clean: [ 'build/' ],
clean: ['<%= target %>/'],
usebanner: {
dist: {
options: {
@@ -33,18 +51,284 @@ module.exports = function(grunt) {
banner: '<%= meta.banner %>'
},
files: {
src: [ 'build/*.js' ]
src: ['<%= target %>/*.js']
}
}
},
replace: {
version: {
src: [ 'build/jsxc.lib.js' ],
src: ['<%= target %>/jsxc.js'],
overwrite: true,
replacements: [ {
replacements: [{
from: '< $ app.version $ >',
to: "<%= app.version %>"
} ]
}]
},
libraries: {
src: ['<%= target %>/jsxc.js'],
overwrite: true,
replacements: [{
from: '<$ dep.libraries $>',
to: function() {
var i, d, libraries = '';
for (i = 0; i < dep.length; i++) {
d = dep[i];
if (typeof d.name === 'string') {
libraries += '<a href="' + d.url + '">' + d.name + '</a> (' + d.license + '), ';
}
}
return libraries.replace(/, $/, '');
}
}]
},
locales: {
src: ['<%= target %>/lib/translation.js'],
overwrite: true,
replacements: [{
from: /^{/g,
to: 'var I18next = {'
}, {
from: /}$/g,
to: '};'
}]
},
template: {
src: ['tmp/template.js'],
overwrite: true,
replacements: [{
from: 'var jsxc.gui.template = {};',
to: ''
}]
},
imageUrl: {
src: ['<%= target %>/css/*.css'],
overwrite: true,
replacements: [{
from: /image-url\(["'](.+)["']\)/g,
to: 'url(\'../img/$1\')'
}]
}
},
merge_data: {
target: {
src: ['locales/*.{json,y{,a}ml}'],
dest: '<%= target %>/lib/translation.js'
}
},
concat: {
dep: {
options: {
banner: '/*!\n' +
' * <%= app.name %> v<%= app.version %> - <%= grunt.template.today("yyyy-mm-dd") %>\n' +
' * \n' +
' * This file concatenates all dependencies of <%= app.name %>.\n' +
' * \n' +
' */\n\n',
process: function(src, filepath) {
filepath = filepath.replace(/^[a-z]+\//i, '');
if (filepath === 'lib/otr/build/dep/crypto.js') {
src += ';';
}
var data = dep[dep_files.indexOf('<%= target %>/' + filepath)];
if (data) {
return '\n/*!\n * Source: ' + filepath + ', license: ' + data.license + ', url: ' + data.url + '\n */\n' + src;
} else {
return src;
}
}
},
src: dep_files,
dest: '<%= target %>/lib/jsxc.dep.js'
},
jsxc: {
options: {
banner: '/*! This file is concatenated for the browser. */\n\n'
},
src: ['src/jsxc.intro.js', 'src/jsxc.lib.js', 'src/jsxc.lib.xmpp.js', 'src/jsxc.lib.*.js', 'tmp/template.js', 'src/jsxc.outro.js'],
dest: '<%= target %>/jsxc.js'
}
},
uglify: {
jsxc: {
options: {
mangle: false,
sourceMap: true,
preserveComments: 'some'
},
files: {
'<%= target %>/lib/jsxc.dep.min.js': ['<%= target %>/lib/jsxc.dep.js'],
'<%= target %>/jsxc.min.js': ['<%= target %>/jsxc.js']
}
}
},
search: {
console: {
files: {
src: ['src/*.js']
},
options: {
searchString: /console\.log\((?!'[<>]|msg)/g,
logFormat: 'console',
failOnMatch: true
}
},
changelog: {
files: {
src: ['CHANGELOG.md']
},
options: {
searchString: "<%= app.version %>",
logFormat: 'console',
onComplete: function(m) {
if (m.numMatches === 0) {
grunt.fail.fatal("No entry in CHANGELOG.md for current version found.");
}
}
}
}
},
compress: {
main: {
options: {
archive: "archives/jsxc-<%= app.version %>.zip"
},
files: [{
src: ['**'],
expand: true,
dest: 'jsxc/',
cwd: 'build/'
}]
}
},
dataUri: {
dist: {
src: '<%= target %>/css/*.css',
dest: '<%= target %>/css/',
options: {
target: ['<%= target %>/img/*.*', '<%= target %>/img/**/*.*'],
fixDirLevel: false,
maxBytes: 2048
}
}
},
jsdoc: {
dist: {
src: ['src/jsxc.lib.*'],
dest: 'doc'
}
},
autoprefixer: {
no_dest: {
src: '<%= target %>/css/*.css'
}
},
csslint: {
strict: {
options: {
import: 2
},
src: ['<%= target %>/css/*.css']
},
},
sass: {
dist: {
files: {
'<%= target %>/css/jsxc.css': 'scss/jsxc.scss',
'<%= target %>/css/jsxc.webrtc.css': 'scss/jsxc.webrtc.scss'
}
}
},
watch: {
locales: {
files: ['locales/*'],
tasks: ['merge_data', 'replace:locales', 'concat:dep']
},
css: {
files: ['scss/*'],
tasks: ['sass', 'autoprefixer']
},
js: {
files: ['src/jsxc.lib.*'],
tasks: ['concat:jsxc']
},
template: {
files: ['template/*.html'],
tasks: ['htmlConvert', 'replace:template', 'concat:jsxc']
}
},
jsbeautifier: {
files: ['Gruntfile.js', 'src/jsxc.lib.*', 'template/*.html', 'example/*.html', 'example/js/dev.js', 'example/js/example.js', 'example/css/example.css'],
options: {
config: '.jsbeautifyrc'
}
},
prettysass: {
options: {
alphabetize: false,
indent: 4
},
jsxc: {
src: ['scss/*.scss']
}
},
htmlConvert: {
options: {
target: 'js',
rename: function(name) {
return name.match(/([-_0-9a-z]+)\.html$/i)[1];
},
quoteChar: '\'',
indentString: '',
indentGlobal: ''
},
'jsxc.gui.template': {
src: 'template/*.html',
dest: 'tmp/template.js'
}
},
shell: {
'precommit-before': {
command: 'git diff --cached --name-only',
options: {
callback: function(err, stdout, stderr, cb) {
git_cached = stdout.trim().split(/\n/);
cb();
}
}
},
'precommit-after': {
command: 'git diff --name-only',
options: {
callback: function(err, stdout, stderr, cb) {
var git_diff = stdout.trim().split(/\n/);
var intersection = [];
var i;
for (i = 0; i < git_diff.length; i++) {
if (git_cached.indexOf(git_diff[i]) >= 0) {
intersection.push(git_diff[i]);
}
}
if (intersection.length > 0) {
grunt.log.writeln();
for (i = 0; i < intersection.length; i++) {
grunt.log.writeln('> ' + intersection[i]);
}
grunt.fail.warn('Some files changed during pre-commit hook!');
}
cb();
}
}
}
}
});
@@ -53,10 +337,44 @@ module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-banner');
grunt.loadNpmTasks('grunt-text-replace');
grunt.loadNpmTasks('grunt-search');
grunt.loadNpmTasks('grunt-contrib-compress');
grunt.loadNpmTasks('grunt-jsdoc');
grunt.loadNpmTasks('grunt-data-uri');
grunt.loadNpmTasks('grunt-merge-data');
grunt.loadNpmTasks('grunt-contrib-csslint');
grunt.loadNpmTasks('grunt-sass');
grunt.loadNpmTasks('grunt-autoprefixer');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-jsbeautifier');
grunt.loadNpmTasks('grunt-prettysass');
grunt.loadNpmTasks('grunt-html-convert');
grunt.loadNpmTasks('grunt-shell');
// Default task.
grunt.registerTask('default', [ 'jshint', 'clean', 'copy', 'usebanner', 'replace' ]);
//Default task
grunt.registerTask('default', ['build', 'watch']);
grunt.registerTask('build', ['jshint', 'clean', 'sass', 'replace:imageUrl', 'autoprefixer', 'copy', 'merge_data', 'replace:locales', 'htmlConvert', 'replace:template', 'concat']);
grunt.registerTask('build:prerelease', 'Build a new pre-release', function() {
grunt.config.set('target', 'build');
grunt.task.run(['search:console', 'build', 'dataUri', 'usebanner', 'replace:version', 'replace:libraries', 'uglify', 'compress']);
});
grunt.registerTask('build:release', 'Build a new release', function() {
grunt.config.set('target', 'build');
grunt.task.run(['search:changelog', 'build:prerelease', 'jsdoc']);
});
// Create alpha/beta build @deprecated
grunt.registerTask('pre', ['build:prerelease']);
// before commit
grunt.registerTask('commit', ['shell:precommit-before', 'search:console', 'jsbeautifier', 'prettysass', 'jshint', 'shell:precommit-after']);
};
+2 -55
Ver Arquivo
@@ -1,60 +1,7 @@
# JavaScript XMPP Client
__Beware! This is beta software.__
Real-time chat app. This app requires an external XMPP server (openfire, ejabberd etc.).
### Features
- integration into existing UI
- one-to-one conversation (XMPP)
- encrypted one-to-one conversation (OTR)
- use of whitespace tags to start a OTR session
- user verification (SMP)
- encrypted one-to-one video call (WebRTC)
- [TURN REST API](http://tools.ietf.org/html/draft-uberti-behave-turn-rest-00)
- fullscreen mode
- snapshots
- automatic link-detection
- emotions
- roster management
- multi-language support (de, en)
- multi-tab support
You find a list of features, supported protocols and browsers at the homepage of __[Javascript XMPP Client](http://www.jsxc.org)__.
### Supported protocols
- XMPP Core (RFC6120)
- XMPP IM (RFC6121)
- Bidirectional-streams Over Synchronous HTTP (XEP-0124)
- XMPP Over BOSH (XEP-0206)
- Service Discovery (XEP-0030)
- CAP (XEP-0127)
- Jingle (XEP-0166)
- Jingle RTP Sessions (XEP-0167)
### Supported browsers
- Full support for __Chrome__ and __Firefox__.
- __IE__ doesn't support multiple tabs, WebRTC, and Notifications.
- __Safari__ doesn't support WebRTC and (before Safari 7) Notifications.
### Planned features
- multi user chat
- video conference
- encrypted file transfer
## Developer notes
Please execute the following commands to get a copy of the code:
```
git clone https://github.com/sualko/jsxc/
git submodule update --init
```
### Libaries
- jQuery (http://jquery.com/)
- Strophe.js (http://strophe.im/strophejs/)
- Strophe.js Plugins (https://github.com/strophe/strophejs-plugins)
- OTR (https://github.com/arlolra/otr)
- strophe.jingle (https://github.com/ESTOS/strophe.jingle)
### Events
coming soon...
If you are looking for install instructions or developer notes, please also checkout our [wiki](https://github.com/jsxc/jsxc/wiki/).
+2 -1
Ver Arquivo
@@ -1,4 +1,4 @@
/**
/*!
* <%= app.name %> v<%= app.version %> - <%= grunt.template.today("yyyy-mm-dd") %>
*
* Copyright (c) <%= grunt.template.today("yyyy") %> <%= app.author %> <br>
@@ -8,4 +8,5 @@
*
* @author <%= app.author %>
* @version <%= app.version %>
* @license MIT
*/
+32
Ver Arquivo
@@ -0,0 +1,32 @@
{
"name": "jsxc",
"version": "2.1.2",
"homepage": "https://www.jsxc.org",
"authors": [
"sualko <klaus@jsxc.org>"
],
"description": "Real-time chat app",
"keywords": [
"javascript",
"xmpp",
"webrtc",
"otr",
"chat",
"realtime"
],
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"lib/",
"test",
"tests"
],
"private": true,
"dependencies": {
"favico.js": "~0.3.9",
"strophe.bookmarks": "https://raw.githubusercontent.com/sualko/strophejs-plugins/bookmarks/bookmarks/strophe.bookmarks.js",
"strophe.x": "https://raw.githubusercontent.com/strophe/strophejs-plugins/master/dataforms/src/strophe.x.js"
}
}
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
+189
Ver Arquivo
@@ -0,0 +1,189 @@
/* Remove close button from firstrunwizard */
#closeWizard {
display: none !important;
}
/*
Colorbox Core Style:
The following CSS is consistent between example themes and should not be altered.
*/
#colorbox,#cboxOverlay,#cboxWrapper {
position: absolute;
top: 0;
left: 0;
z-index: 9999;
overflow: hidden;
}
#cboxWrapper {
max-width: none;
}
#cboxOverlay {
position: fixed;
width: 100%;
height: 100%;
}
#cboxMiddleLeft,#cboxBottomLeft {
clear: left;
}
#cboxContent {
position: relative;
}
#cboxLoadedContent {
overflow: auto;
-webkit-overflow-scrolling: touch;
}
#cboxTitle {
margin: 0;
}
#cboxLoadingOverlay,#cboxLoadingGraphic {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
#cboxPrevious,#cboxNext,#cboxClose,#cboxSlideshow {
cursor: pointer;
}
.cboxPhoto {
float: left;
margin: auto;
border: 0;
display: block;
max-width: none;
-ms-interpolation-mode: bicubic;
}
.cboxIframe {
width: 100%;
height: 100%;
display: block;
border: 0;
}
#colorbox,#cboxContent,#cboxLoadedContent {
box-sizing: content-box;
-moz-box-sizing: content-box;
-webkit-box-sizing: content-box;
}
/*
User Style:
Change the following styles to modify the appearance of Colorbox. They are
ordered & tabbed in a way that represents the nesting of the generated HTML.
*/
#cboxOverlay {
background: #000;
}
#colorbox {
}
#cboxContent {
margin-top: 20px;
}
.cboxIframe {
background: #fff;
}
#cboxError {
padding: 50px;
border: 0px solid #ccc;
}
#cboxLoadedContent {
border: 0px solid #555;
background: #fff;
border-radius: 5px;
}
#cboxTitle {
position: absolute;
top: -20px;
left: 0;
color: #ccc;
}
#cboxCurrent {
position: absolute;
top: -20px;
right: 0px;
color: #ccc;
}
#cboxSlideshow {
position: absolute;
top: -20px;
right: 90px;
color: #fff;
}
#cboxPrevious:hover {
background-position: bottom left;
}
#cboxNext:hover {
background-position: bottom right;
}
#cboxLoadingOverlay {
background: #fff;
}
#cboxClose {
position: absolute;
top: 5px;
right: 5px;
display: block;
opacity: 0.5;
width: 19px !important;
height: 19px;
border: 0px;
text-indent: -9999px;
background-color: #fff;
}
#cboxClose:before {
content: '×';
position: absolute;
top: 0px;
left: 0px;
display: block;
width: 19px;
height: 19px;
opacity: 0.5;
text-indent: 0;
text-align: center;
line-height: 19px;
font-size: 19px;
}
#cboxClose:before:hover {
opacity: 1;
}
#cboxClose:hover {
background-position: right center !important;
opacity: 1.0;
}
/*
The following fixes a problem where IE7 and IE8 replace a PNG's alpha transparency with a black fill
when an alpha filter (opacity change) is set on the element or ancestor element. This style is not applied to or needed in IE9.
See: http://jacklmoore.com/notes/ie-transparency-problems/
*/
.cboxIE #cboxTopLeft,.cboxIE #cboxTopCenter,.cboxIE #cboxTopRight,.cboxIE #cboxBottomLeft,.cboxIE #cboxBottomCenter,.cboxIE #cboxBottomRight,.cboxIE #cboxMiddleLeft,.cboxIE #cboxMiddleRight
{
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#00FFFFFF,
endColorstr=#00FFFFFF);
}
+3527
Ver Arquivo
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+244
Ver Arquivo
@@ -0,0 +1,244 @@
.jsxc_remotevideo, .jsxc_noRemoteVideo {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
z-index: 9000;
background-color: #999999; }
.jsxc_webrtc {
width: 900px; }
.jsxc_webrtc .jsxc_status {
z-index: 9999;
border-radius: 20px;
display: none;
position: absolute;
top: 30px;
left: 50%;
background-color: rgba(0, 0, 0, 0.5);
color: #fff;
padding: 15px;
font-weight: bold;
text-align: center; }
.jsxc_webrtc .slimScrollDiv {
opacity: 1 !important; }
.jsxc_webrtc li .jsxc_name {
cursor: auto; }
.jsxc_webrtc li .jsxc_name:hover {
color: gray; }
.jsxc_videoContainer {
width: 640px;
height: 480px;
position: relative;
background-color: #999999; }
.jsxc_videoContainer video {
display: none; }
.jsxc_videoContainer .jsxc_noRemoteVideo {
display: none; }
.jsxc_noRemoteVideo p {
position: absolute;
bottom: 0;
left: 0;
text-align: center;
color: #fff;
width: 100%;
z-index: 100; }
.jsxc_noRemoteVideo > div {
width: 200px;
height: 200px;
overflow: hidden;
position: absolute;
top: 50%;
margin-top: -100px;
left: 50%;
margin-left: -100px; }
.jsxc_noRemoteVideo > div > div {
background-color: #4d4d4d; }
.jsxc_noRemoteVideo > div > div:first-child {
width: 50%;
height: 50%;
border-radius: 50%;
position: absolute;
left: 50%;
margin-left: -25%;
top: 10%; }
.jsxc_noRemoteVideo > div > div:last-child {
position: absolute;
bottom: -50%;
width: 100%;
height: 100%;
border-radius: 50%; }
.jsxc_localvideo {
width: 160px;
height: 120px;
position: absolute;
right: 10px;
bottom: 10px;
z-index: 9990;
background-color: #000;
cursor: pointer; }
div:full-screen {
width: 100%;
height: 100%;
background-color: #000; }
div:full-screen.jsxc_localvideo {
border: 1px solid #fff; }
div:-webkit-full-screen {
width: 100%;
height: 100%;
background-color: #000; }
div:-moz-full-screen {
width: 100%;
height: 100%;
background-color: #000; }
div:-ms-fullscreen {
width: 100%;
height: 100%;
background-color: #000; }
div:fullscreen {
width: 100%;
height: 100%;
background-color: #000; }
div:-webkit-full-screen.jsxc_localvideo {
border: 1px solid #fff; }
div:-moz-full-screen.jsxc_localvideo {
border: 1px solid #fff; }
div:-ms-fullscreen.jsxc_localvideo {
border: 1px solid #fff; }
div:fullscreen.jsxc_localvideo {
border: 1px solid #fff; }
div.jsxc_video {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgdmVyc2lvbj0iMS4xIgogICBpZD0ic3ZnMiIKICAgd2lkdGg9IjIwIgogICBoZWlnaHQ9IjIwIj4KICA8bWV0YWRhdGEKICAgICBpZD0ibWV0YWRhdGExMCI+CiAgICA8cmRmOlJERj4KICAgICAgPGNjOldvcmsKICAgICAgICAgcmRmOmFib3V0PSIiPgogICAgICAgIDxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PgogICAgICAgIDxkYzp0eXBlCiAgICAgICAgICAgcmRmOnJlc291cmNlPSJodHRwOi8vcHVybC5vcmcvZGMvZGNtaXR5cGUvU3RpbGxJbWFnZSIgLz4KICAgICAgICA8ZGM6dGl0bGU+PC9kYzp0aXRsZT4KICAgICAgPC9jYzpXb3JrPgogICAgPC9yZGY6UkRGPgogIDwvbWV0YWRhdGE+CiAgPGRlZnMKICAgICBpZD0iZGVmczgiIC8+CiAgPGcKICAgICBpZD0ibGF5ZXIxIgogICAgIHRyYW5zZm9ybT0ibWF0cml4KDAuMDM3ODg1OTQsMCwwLDAuMDM3ODg1OTQsLTAuNDEzNDA3OTMsLTIuNjMxMDcxNikiPgogICAgPHBhdGgKICAgICAgIGlkPSJwYXRoMzkwNiIKICAgICAgIHN0eWxlPSJmaWxsOiM4MDgwODA7c3Ryb2tlOm5vbmUiCiAgICAgICBkPSJtIDM2MS42NTE0OCwzMTMuNTE3NjggMTc3LjE2MDc0LC0xMzEuNzg1MTYgMCwzMDIuMjI5OTkgTCAzNTguOTczMzgsMzUwLjE4NTE3IFogTSAxMC45MTE5MjIsMTgyLjQwNjM0IGwgMzc4LjM3MjY3OCwwIDAsMzAyLjY1NTgyIC0zNzguMzcyNjc4LDAgeiIgLz4KICA8L2c+Cjwvc3ZnPgo=');
background-repeat: no-repeat;
background-position: center center;
background-size: 15px 15px; }
div.jsxc_video:not(.jsxc_disabled):hover {
background-image: url('../img/camera_icon_white.svg'); }
.jsxc_controlbar {
width: 640px;
margin-top: 10px; }
.jsxc_controlbar .jsxc_showchat {
float: right; }
.jsxc_multi > div {
display: none; }
.jsxc_snapshotbar {
width: 100%;
display: none; }
.jsxc_snapshotbar img {
height: 50px; }
.jsxc_buttongroup {
display: inline; }
.jsxc_buttongroup button:first-child {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
margin-right: 0; }
.jsxc_buttongroup button:last-child {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
margin-left: 0; }
.jsxc_chatarea {
position: relative;
float: right;
height: 480px;
width: 250px;
background-color: #999999; }
.jsxc_chatarea .jsxc_settings {
display: none !important; }
.jsxc_chatarea .jsxc_close {
display: none !important; }
.jsxc_chatarea .jsxc_video {
display: none !important; }
.jsxc_chatarea .jsxc_window {
bottom: 0;
box-shadow: none; }
.jsxc_chatarea > ul {
width: 250px;
height: 480px;
list-style: none;
padding: 0; }
.bubblingG {
text-align: center;
width: 129px;
height: 80px;
position: absolute;
top: 40%;
left: 50%;
margin-left: -64px; }
.bubblingG span {
display: inline-block;
vertical-align: middle;
width: 16px;
height: 16px;
margin: 40px auto;
background: #000;
border-radius: 81px;
-webkit-animation: bubblingG 1.3s infinite alternate;
animation: bubblingG 1.3s infinite alternate; }
#bubblingG_1 {
-webkit-animation-delay: 0s;
animation-delay: 0s; }
#bubblingG_2 {
-webkit-animation-delay: 0.39s;
animation-delay: 0.39s; }
#bubblingG_3 {
-webkit-animation-delay: 0.78s;
animation-delay: 0.78s; }
@-webkit-keyframes bubblingG {
0% {
width: 16px;
height: 16px;
background-color: #000;
-webkit-transform: translateY(0);
transform: translateY(0); }
100% {
width: 39px;
height: 39px;
background-color: #fff;
-webkit-transform: translateY(-34px);
transform: translateY(-34px); } }
@keyframes bubblingG {
0% {
width: 16px;
height: 16px;
background-color: #000;
-webkit-transform: translateY(0);
transform: translateY(0); }
100% {
width: 39px;
height: 39px;
background-color: #fff;
-webkit-transform: translateY(-34px);
transform: translateY(-34px); } }
.jsxc_fullscreen.jsxc_localvideo {
border: 1px solid #fff; }
.jsxc_videoSuitable .jsxc_name {
font-style: italic; }
#jsxc_buddylist .jsxc_options .jsxc_video {
background-image: url('../img/camera_icon_white.svg'); }
#jsxc_buddylist .jsxc_options .jsxc_video.jsxc_disabled {
opacity: 0.2; }
+374
Ver Arquivo
@@ -0,0 +1,374 @@
/* Magnific Popup CSS */
.mfp-bg {
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1042;
overflow: hidden;
position: fixed;
background: #0b0b0b;
opacity: 0.8;
filter: alpha(opacity=80); }
.mfp-wrap {
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1043;
position: fixed;
outline: none !important;
-webkit-backface-visibility: hidden; }
.mfp-container {
text-align: center;
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
padding: 0 8px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box; }
.mfp-container:before {
content: '';
display: inline-block;
height: 100%;
vertical-align: middle; }
.mfp-align-top .mfp-container:before {
display: none; }
.mfp-content {
position: relative;
display: inline-block;
vertical-align: middle;
margin: 0 auto;
text-align: left;
z-index: 1045; }
.mfp-inline-holder .mfp-content, .mfp-ajax-holder .mfp-content {
width: 100%;
cursor: auto; }
.mfp-ajax-cur {
cursor: progress; }
.mfp-zoom-out-cur, .mfp-zoom-out-cur .mfp-image-holder .mfp-close {
cursor: -moz-zoom-out;
cursor: -webkit-zoom-out;
cursor: zoom-out; }
.mfp-zoom {
cursor: pointer;
cursor: -webkit-zoom-in;
cursor: -moz-zoom-in;
cursor: zoom-in; }
.mfp-auto-cursor .mfp-content {
cursor: auto; }
.mfp-close, .mfp-arrow, .mfp-preloader, .mfp-counter {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none; }
.mfp-loading.mfp-figure {
display: none; }
.mfp-hide {
display: none !important; }
.mfp-preloader {
color: #CCC;
position: absolute;
top: 50%;
width: auto;
text-align: center;
margin-top: -0.8em;
left: 8px;
right: 8px;
z-index: 1044; }
.mfp-preloader a {
color: #CCC; }
.mfp-preloader a:hover {
color: #FFF; }
.mfp-s-ready .mfp-preloader {
display: none; }
.mfp-s-error .mfp-content {
display: none; }
button.mfp-close, button.mfp-arrow {
overflow: visible;
cursor: pointer;
background: transparent;
border: 0;
-webkit-appearance: none;
display: block;
outline: none;
padding: 0;
z-index: 1046;
-webkit-box-shadow: none;
box-shadow: none; }
button::-moz-focus-inner {
padding: 0;
border: 0; }
.mfp-close {
width: 44px;
height: 44px;
line-height: 44px;
position: absolute;
right: 0;
top: 0;
text-decoration: none;
text-align: center;
opacity: 0.65;
filter: alpha(opacity=65);
padding: 0 0 18px 10px;
color: #FFF;
font-style: normal;
font-size: 28px;
font-family: Arial, Baskerville, monospace; }
.mfp-close:hover, .mfp-close:focus {
opacity: 1;
filter: alpha(opacity=100); }
.mfp-close:active {
top: 1px; }
.mfp-close-btn-in .mfp-close {
color: #333; }
.mfp-image-holder .mfp-close, .mfp-iframe-holder .mfp-close {
color: #FFF;
right: -6px;
text-align: right;
padding-right: 6px;
width: 100%; }
.mfp-counter {
position: absolute;
top: 0;
right: 0;
color: #CCC;
font-size: 12px;
line-height: 18px;
white-space: nowrap; }
.mfp-arrow {
position: absolute;
opacity: 0.65;
filter: alpha(opacity=65);
margin: 0;
top: 50%;
margin-top: -55px;
padding: 0;
width: 90px;
height: 110px;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0); }
.mfp-arrow:active {
margin-top: -54px; }
.mfp-arrow:hover, .mfp-arrow:focus {
opacity: 1;
filter: alpha(opacity=100); }
.mfp-arrow:before, .mfp-arrow:after, .mfp-arrow .mfp-b, .mfp-arrow .mfp-a {
content: '';
display: block;
width: 0;
height: 0;
position: absolute;
left: 0;
top: 0;
margin-top: 35px;
margin-left: 35px;
border: medium inset transparent; }
.mfp-arrow:after, .mfp-arrow .mfp-a {
border-top-width: 13px;
border-bottom-width: 13px;
top: 8px; }
.mfp-arrow:before, .mfp-arrow .mfp-b {
border-top-width: 21px;
border-bottom-width: 21px;
opacity: 0.7; }
.mfp-arrow-left {
left: 0; }
.mfp-arrow-left:after, .mfp-arrow-left .mfp-a {
border-right: 17px solid #FFF;
margin-left: 31px; }
.mfp-arrow-left:before, .mfp-arrow-left .mfp-b {
margin-left: 25px;
border-right: 27px solid #3F3F3F; }
.mfp-arrow-right {
right: 0; }
.mfp-arrow-right:after, .mfp-arrow-right .mfp-a {
border-left: 17px solid #FFF;
margin-left: 39px; }
.mfp-arrow-right:before, .mfp-arrow-right .mfp-b {
border-left: 27px solid #3F3F3F; }
.mfp-iframe-holder {
padding-top: 40px;
padding-bottom: 40px; }
.mfp-iframe-holder .mfp-content {
line-height: 0;
width: 100%;
max-width: 900px; }
.mfp-iframe-holder .mfp-close {
top: -40px; }
.mfp-iframe-scaler {
width: 100%;
height: 0;
overflow: hidden;
padding-top: 56.25%; }
.mfp-iframe-scaler iframe {
position: absolute;
display: block;
top: 0;
left: 0;
width: 100%;
height: 100%;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.6);
background: #000; }
/* Main image in popup */
img.mfp-img {
width: auto;
max-width: 100%;
height: auto;
display: block;
line-height: 0;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
padding: 40px 0 40px;
margin: 0 auto; }
/* The shadow behind the image */
.mfp-figure {
line-height: 0; }
.mfp-figure:after {
content: '';
position: absolute;
left: 0;
top: 40px;
bottom: 40px;
display: block;
right: 0;
width: auto;
height: auto;
z-index: -1;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.6);
background: #444; }
.mfp-figure small {
color: #BDBDBD;
display: block;
font-size: 12px;
line-height: 14px; }
.mfp-figure figure {
margin: 0; }
.mfp-bottom-bar {
margin-top: -36px;
position: absolute;
top: 100%;
left: 0;
width: 100%;
cursor: auto; }
.mfp-title {
text-align: left;
line-height: 18px;
color: #F3F3F3;
word-wrap: break-word;
padding-right: 36px; }
.mfp-image-holder .mfp-content {
max-width: 100%; }
.mfp-gallery .mfp-image-holder .mfp-figure {
cursor: pointer; }
@media screen and (max-width: 800px) and (orientation: landscape), screen and (max-height: 300px) {
/**
* Remove all paddings around the image on small screen
*/
.mfp-img-mobile .mfp-image-holder {
padding-left: 0;
padding-right: 0; }
.mfp-img-mobile img.mfp-img {
padding: 0; }
.mfp-img-mobile .mfp-figure:after {
top: 0;
bottom: 0; }
.mfp-img-mobile .mfp-figure small {
display: inline;
margin-left: 5px; }
.mfp-img-mobile .mfp-bottom-bar {
background: rgba(0, 0, 0, 0.6);
bottom: 0;
margin: 0;
top: auto;
padding: 3px 5px;
position: fixed;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box; }
.mfp-img-mobile .mfp-bottom-bar:empty {
padding: 0; }
.mfp-img-mobile .mfp-counter {
right: 5px;
top: 3px; }
.mfp-img-mobile .mfp-close {
top: 0;
right: 0;
width: 35px;
height: 35px;
line-height: 35px;
background: rgba(0, 0, 0, 0.6);
position: fixed;
text-align: center;
padding: 0; }
}
@media all and (max-width: 900px) {
.mfp-arrow {
-webkit-transform: scale(0.75);
transform: scale(0.75); }
.mfp-arrow-left {
-webkit-transform-origin: 0;
transform-origin: 0; }
.mfp-arrow-right {
-webkit-transform-origin: 100%;
transform-origin: 100%; }
.mfp-container {
padding-left: 6px;
padding-right: 6px; }
}
.mfp-ie7 .mfp-img {
padding: 0; }
.mfp-ie7 .mfp-bottom-bar {
width: 600px;
left: 50%;
margin-left: -300px;
margin-top: 5px;
padding-bottom: 5px; }
.mfp-ie7 .mfp-container {
padding: 0; }
.mfp-ie7 .mfp-content {
padding-top: 44px; }
.mfp-ie7 .mfp-close {
top: 0;
right: 0;
padding-top: 0; }
Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 9.3 KiB

+105
Ver Arquivo
@@ -0,0 +1,105 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="Layer_1"
xml:space="preserve"
height="147.22015"
viewBox="0 0 192.89149 147.21771"
width="192.89587"
version="1.1"
y="0px"
x="0px"
enable-background="new 0 0 176.486 181.437"
inkscape:version="0.91pre2 r"
sodipodi:docname="XMPP_logo.svg"><metadata
id="metadata41"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs39" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="640"
inkscape:window-height="480"
id="namedview37"
showgrid="false"
fit-margin-top="10"
fit-margin-left="10"
fit-margin-right="10"
fit-margin-bottom="10"
inkscape:zoom="1.3007054"
inkscape:cx="71.332001"
inkscape:cy="72.501142"
inkscape:window-x="75"
inkscape:window-y="34"
inkscape:window-maximized="0"
inkscape:current-layer="Layer_1" /><linearGradient
id="SVGID_1_"
y2="0.00048828"
gradientUnits="userSpaceOnUse"
x2="-1807.2"
gradientTransform="translate(1925.9953,9.9988343)"
y1="125.86"
x1="-1807.2"><stop
stop-color="#1b3967"
offset=".011"
id="stop4" /><stop
stop-color="#13b5ea"
offset=".467"
id="stop6" /><stop
stop-color="#002b5c"
offset=".9945"
id="stop8" /></linearGradient><path
d="m 146.28531,24.187835 c 0.077,1.313 -1.786,0.968 -1.786,2.293 0,38.551 -44.720002,96.831035 -89.847002,108.190035 l 0,1.182 C 114.60931,130.34287 181.38231,69.052835 182.89231,10.002834 l -36.6,14.189001 z"
id="path10"
style="fill:url(#SVGID_1_)"
inkscape:connector-curvature="0" /><path
d="m 130.22531,27.958835 c 0.077,1.313 0.121,2.633 0.121,3.958 0,38.551 -30.700002,90.497035 -75.827002,101.860035 l 0,1.637 c 59.065002,-3.823 105.810002,-63.023035 105.810002,-109.200035 0,-2.375 -0.125,-4.729 -0.371,-7.056 l -29.73,8.796 z"
id="path12"
inkscape:connector-curvature="0"
style="fill:#e96d1f" /><linearGradient
id="SVGID_2_"
y2="1.279e-13"
gradientUnits="userSpaceOnUse"
x2="-1073.2"
gradientTransform="matrix(-1,0,0,1,-998.20465,9.9988343)"
y1="126.85"
x1="-1073.2"><stop
stop-color="#1b3967"
offset=".011"
id="stop15" /><stop
stop-color="#13b5ea"
offset=".467"
id="stop17" /><stop
stop-color="#002b5c"
offset=".9945"
id="stop19" /></linearGradient><path
d="m 46.594308,24.187835 c -0.077,1.313 1.787,0.968 1.787,2.293 0,38.551 46.558,97.366035 91.688002,108.730035 l 0,1.639 C 80.116308,131.32987 11.509308,69.049835 9.9993079,9.9998343 L 46.598308,24.188835 Z"
id="path21"
style="fill:url(#SVGID_2_)"
inkscape:connector-curvature="0" /><path
d="m 64.726308,28.930835 c -0.076,1.313 -0.12,2.63 -0.12,3.957 0,38.551 30.699,90.497035 75.827002,101.860035 l 0,1.639 C 81.389308,133.59687 34.623308,73.362835 34.623308,27.186835 c 0,-2.375 0.128,-4.729 0.371,-7.056 l 29.73,8.798 z"
id="path23"
inkscape:connector-curvature="0"
style="fill:#a0ce67" /><path
d="m 34.708308,19.581835 7.617,2.722 c -0.041,0.962 -0.066,2.254 -0.066,3.225 0,41.219 37.271,98.204035 87.272002,107.120035 3.245,1.088 7.538,2.077 10.932,2.931 l 0,1.638 C 75.209308,131.65787 29.363308,65.351835 34.703308,19.577835 Z"
id="path25"
inkscape:connector-curvature="0"
style="fill:#439639" /><path
d="m 160.33531,18.758835 -7.833,2.625 c 0.041,0.963 0.191,2.203 0.191,3.173 0,41.219 -37.272,98.205035 -87.274002,107.120035 -3.243,1.089 -7.538,2.077 -10.93,2.932 l 0,1.639 C 122.83331,127.58787 165.66931,64.528835 160.32931,18.757835 Z"
id="path27"
inkscape:connector-curvature="0"
style="fill:#d9541e" /></svg>

Depois

Largura:  |  Altura:  |  Tamanho: 4.5 KiB

+74
Ver Arquivo
@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="12.923695"
height="19.551229"
viewBox="0 0 3.4193941 5.1729296"
id="svg2"
version="1.1"
inkscape:version="0.91+devel r"
sodipodi:docname="bookmark_red.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="22.4"
inkscape:cx="-1.621067"
inkscape:cy="11.999492"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1855"
inkscape:window-height="1056"
inkscape:window-x="65"
inkscape:window-y="24"
inkscape:window-maximized="1" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-0.88782864,-291.84497)">
<path
style="fill:none;fill-rule:evenodd;stroke:#800000;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 1.0201203,291.84497 0,4.85355 1.5774055,-1.5774 1.5774053,1.5774 0,-4.83839"
id="path4141"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
inkscape:connector-curvature="0"
id="path4162"
d="m 1.0201203,291.84497 0,4.85355 1.5774055,-1.5774 1.5774053,1.5774 0,-4.83839"
style="fill:#ff0000;fill-rule:evenodd;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
sodipodi:nodetypes="ccccc" />
</g>
</svg>

Depois

Largura:  |  Altura:  |  Tamanho: 2.5 KiB

+9 -72
Ver Arquivo
@@ -1,97 +1,34 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="535.00458"
height="510.4368"
id="svg3896"
version="1.1"
inkscape:version="0.48+devel r"
sodipodi:docname="camera_icon_grey.svg">
<defs
id="defs3898" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.35"
inkscape:cx="369.28572"
inkscape:cy="50.436783"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="954"
inkscape:window-height="711"
inkscape:window-x="129"
inkscape:window-y="144"
inkscape:window-maximized="0" />
id="svg2"
width="20"
height="20">
<metadata
id="metadata3901">
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-5.7142771,-72.362177)">
<rect
style="fill:#808080;stroke:none;stroke-width:1.6172694;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="rect3904"
width="290.51404"
height="294.08438"
x="86.054779"
y="292.97778" />
transform="matrix(0.03788594,0,0,0.03788594,-0.41340793,-2.6310716)">
<path
style="fill:#808080;stroke:none"
d="m 292.28572,420.35915 229.57599,-101.39986 0,232.54576 -233.04644,-102.93271 z"
id="path3906"
inkscape:connector-curvature="0" />
<path
sodipodi:type="arc"
style="fill:#808080;stroke:none"
id="path3908"
sodipodi:cx="242.85715"
sodipodi:cy="315.21933"
sodipodi:rx="117.14286"
sodipodi:ry="117.14286"
d="M 360.00001,315.21933 A 117.14286,117.14286 0 0 1 242.85715,432.36219 117.14286,117.14286 0 0 1 125.71429,315.21933 117.14286,117.14286 0 0 1 242.85715,198.07647 117.14286,117.14286 0 0 1 360.00001,315.21933 Z"
transform="matrix(1.1334136,0,0,1.1663886,-136.76164,-155.82534)" />
<a
id="a3912"
style="fill:#808080;stroke:none"
transform="matrix(0.86859739,0,0,0.89386794,47.913668,10.526572)">
<path
sodipodi:type="arc"
style="fill:#808080;stroke:none"
id="path3910"
sodipodi:cx="242.85715"
sodipodi:cy="315.21933"
sodipodi:rx="117.14286"
sodipodi:ry="117.14286"
d="M 360.00001,315.21933 A 117.14286,117.14286 0 0 1 242.85715,432.36219 117.14286,117.14286 0 0 1 125.71429,315.21933 117.14286,117.14286 0 0 1 242.85715,198.07647 117.14286,117.14286 0 0 1 360.00001,315.21933 Z"
transform="matrix(1.304878,0,0,1.304878,3.67247,-186.10345)" />
</a>
d="m 361.65148,313.51768 177.16074,-131.78516 0,302.22999 L 358.97338,350.18517 Z M 10.911922,182.40634 l 378.372678,0 0,302.65582 -378.372678,0 z" />
</g>
</svg>

Antes

Largura:  |  Altura:  |  Tamanho: 3.3 KiB

Depois

Largura:  |  Altura:  |  Tamanho: 1010 B

+16 -41
Ver Arquivo
@@ -13,8 +13,8 @@
height="510.4368"
id="svg3896"
version="1.1"
inkscape:version="0.48.3.1 r9886"
sodipodi:docname="camera_icon.svg">
inkscape:version="0.48+devel r"
sodipodi:docname="camera_icon_white.svg">
<defs
id="defs3898" />
<sodipodi:namedview
@@ -24,9 +24,9 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.35"
inkscape:cx="369.28572"
inkscape:cy="50.436783"
inkscape:zoom="0.98994949"
inkscape:cx="353.91934"
inkscape:cy="233.8456"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
@@ -34,11 +34,11 @@
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="954"
inkscape:window-height="711"
inkscape:window-x="833"
inkscape:window-y="106"
inkscape:window-maximized="0" />
inkscape:window-width="1855"
inkscape:window-height="1056"
inkscape:window-x="65"
inkscape:window-y="24"
inkscape:window-maximized="1" />
<metadata
id="metadata3901">
<rdf:RDF>
@@ -57,41 +57,16 @@
id="layer1"
transform="translate(-5.7142771,-72.362177)">
<rect
style="fill:#ffffff;stroke:#ffffff;stroke-width:1.61726940000000008;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
style="fill:#ffffff;stroke:none;stroke-width:1.6172694;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect3904"
width="290.51404"
height="294.08438"
x="86.054779"
y="292.97778" />
width="378.37268"
height="302.65582"
x="10.911922"
y="182.40634" />
<path
style="fill:#ffffff;stroke:none"
d="m 292.28572,420.35915 229.57599,-101.39986 0,232.54576 -233.04644,-102.93271 z"
d="m 361.65148,313.51768 177.16074,-131.78516 0,302.22999 -179.83884,-133.77734 z"
id="path3906"
inkscape:connector-curvature="0" />
<path
sodipodi:type="arc"
style="fill:#ffffff;stroke:none"
id="path3908"
sodipodi:cx="242.85715"
sodipodi:cy="315.21933"
sodipodi:rx="117.14286"
sodipodi:ry="117.14286"
d="m 360.00001,315.21933 a 117.14286,117.14286 0 1 1 -234.28572,0 117.14286,117.14286 0 1 1 234.28572,0 z"
transform="matrix(1.1334136,0,0,1.1663886,-136.76164,-155.82534)" />
<a
id="a3912"
style="fill:#ffffff"
transform="matrix(0.86859739,0,0,0.89386794,47.913668,10.526572)">
<path
sodipodi:type="arc"
style="fill:#ffffff;stroke:none"
id="path3910"
sodipodi:cx="242.85715"
sodipodi:cy="315.21933"
sodipodi:rx="117.14286"
sodipodi:ry="117.14286"
d="m 360.00001,315.21933 c 0,64.69622 -52.44665,117.14286 -117.14286,117.14286 -64.69622,0 -117.14286,-52.44664 -117.14286,-117.14286 0,-64.69622 52.44664,-117.14286 117.14286,-117.14286 64.69621,0 117.14286,52.44664 117.14286,117.14286 z"
transform="matrix(1.304878,0,0,1.304878,3.67247,-186.10345)" />
</a>
</g>
</svg>

Antes

Largura:  |  Altura:  |  Tamanho: 3.2 KiB

Depois

Largura:  |  Altura:  |  Tamanho: 2.1 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 1.5 KiB

+59
Ver Arquivo
@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
viewBox="0 0 1000 1000"
preserveAspectRatio="xMinYMin meet"
width="100%"
height="100%"
style="width: 512px; height: 512px;"
id="svg2"
version="1.1"
inkscape:version="0.91+devel r"
sodipodi:docname="group_grey.svg">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="980"
inkscape:window-height="888"
id="namedview6"
showgrid="false"
inkscape:zoom="0.6675088"
inkscape:cx="512.17823"
inkscape:cy="480.21903"
inkscape:window-x="889"
inkscape:window-y="85"
inkscape:window-maximized="0"
inkscape:current-layer="svg2" />
<path
d="m 0.94630456,763.0963 c 0,22.21203 9.08673644,33.31804 27.26020844,33.31804 l 112.069747,0 0,-142.35887 c 0,-18.17347 4.54363,-34.83222 13.63088,-49.97627 9.08724,-15.14405 21.70797,-26.75512 37.86216,-34.83326 l 115.09866,-54.52042 c 10.09637,-6.05782 18.17347,-13.12528 24.23129,-21.20238 -12.11564,-18.17347 -22.21202,-39.37586 -30.28912,-63.60715 -8.0771,-24.2313 -12.11564,-49.47223 -12.11564,-75.7228 0,-16.1542 2.01927,-32.3084 6.05782,-48.46259 4.03855,-16.1542 9.08674,-31.29876 15.14456,-45.43368 -20.19275,-14.13493 -41.39513,-21.20239 -63.60715,-21.20239 -38.36622,2.01928 -68.65534,17.66839 -90.86736,46.94736 -22.21201,29.27897 -33.31803,62.09244 -33.31803,98.44042 2.01928,62.59751 24.2313,107.02155 66.63606,133.27212 L 16.092416,596.50615 C 5.9960421,602.56397 0.94785546,612.66034 0.94785546,626.79527 l 0,136.30103 z M 191.76775,796.41434 c -2.01927,42.40476 10.09637,64.61678 36.34695,66.63606 l 542.17524,0 c 12.11565,-4.03855 20.69783,-10.09637 25.74653,-18.17347 5.04869,-8.0771 7.57305,-14.63948 7.57305,-19.68716 l 0,-171.13275 c 0,-18.17347 -7.06746,-30.28912 -21.20238,-36.34694 L 637.01936,545.01619 573.41221,514.72707 c 38.36622,-22.21202 63.60715,-60.57824 75.7228,-115.09865 8.0771,-30.28912 8.0771,-61.58788 0,-93.89627 -10.09637,-36.34695 -28.7744,-67.14115 -56.0341,-92.38259 -27.25969,-25.24145 -59.06352,-38.87182 -95.4115,-40.89109 -36.34694,2.01927 -67.6457,15.64964 -93.89627,40.89109 -26.25057,25.24144 -44.42404,55.02601 -54.52042,89.35368 -12.11564,46.44331 -8.07709,93.89627 12.11565,142.35886 16.1542,30.28912 37.35658,54.52041 63.60715,72.69389 l -57.54932,27.2602 -151.4456,69.66498 c -16.1542,8.0771 -24.2313,21.20238 -24.2313,39.37585 l 0,142.35887 z m 475.53918,-302.8912 c 8.0771,8.0771 18.17347,16.1542 30.28912,24.23129 12.11565,8.0771 23.22166,14.13493 33.31803,18.17348 10.09638,4.03855 23.22166,9.59181 39.37586,16.65979 16.1542,7.06797 28.26984,12.62124 36.34694,16.65979 16.1542,8.0771 28.77493,19.68819 37.86218,34.83326 9.08724,15.14507 13.63088,31.80384 13.63088,49.97627 l 0,142.35887 115.09865,0 c 18.17347,-2.01928 27.26021,-13.12529 27.26021,-33.31803 l 0,-136.30104 c 0,-14.13493 -5.04819,-24.2313 -15.14456,-30.28912 L 815.72517,514.72707 c 42.40477,-30.28912 63.60715,-73.70352 63.60715,-130.24321 0,-38.36622 -12.11565,-72.18881 -36.34694,-101.46778 -24.2313,-29.27897 -53.51078,-43.91896 -87.83845,-43.92 -22.21202,0 -44.42404,7.06747 -66.63606,21.20239 12.11564,30.28912 18.17347,61.58787 18.17347,93.89627 0,50.48187 -13.12529,96.92518 -39.37586,139.32995 z"
id="path4"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cscsscccsssccscccscccccssscccccscscccccscccssssssccssccssccscc"
style="fill:#999999;stroke-width:1.55090213;fill-opacity:1" />
</svg>

Depois

Largura:  |  Altura:  |  Tamanho: 4.2 KiB

+58
Ver Arquivo
@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
viewBox="0 0 1000 1000"
preserveAspectRatio="xMinYMin meet"
width="100%"
height="100%"
style="width: 512px; height: 512px;"
id="svg2"
version="1.1"
inkscape:version="0.91+devel r"
sodipodi:docname="group_white.svg">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1855"
inkscape:window-height="1056"
id="namedview6"
showgrid="false"
inkscape:zoom="0.6675088"
inkscape:cx="538.39511"
inkscape:cy="480.21903"
inkscape:window-x="65"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<path
d="m 0.94630456,763.0963 c 0,22.21203 9.08673644,33.31804 27.26020844,33.31804 l 112.069747,0 0,-142.35887 c 0,-18.17347 4.54363,-34.83222 13.63088,-49.97627 9.08724,-15.14405 21.70797,-26.75512 37.86216,-34.83326 l 115.09866,-54.52042 c 10.09637,-6.05782 18.17347,-13.12528 24.23129,-21.20238 -12.11564,-18.17347 -22.21202,-39.37586 -30.28912,-63.60715 -8.0771,-24.2313 -12.11564,-49.47223 -12.11564,-75.7228 0,-16.1542 2.01927,-32.3084 6.05782,-48.46259 4.03855,-16.1542 9.08674,-31.29876 15.14456,-45.43368 -20.19275,-14.13493 -41.39513,-21.20239 -63.60715,-21.20239 -38.36622,2.01928 -68.65534,17.66839 -90.86736,46.94736 -22.21201,29.27897 -33.31803,62.09244 -33.31803,98.44042 2.01928,62.59751 24.2313,107.02155 66.63606,133.27212 L 16.092416,596.50615 C 5.9960421,602.56397 0.94785546,612.66034 0.94785546,626.79527 l 0,136.30103 z M 191.76775,796.41434 c -2.01927,42.40476 10.09637,64.61678 36.34695,66.63606 l 542.17524,0 c 12.11565,-4.03855 20.69783,-10.09637 25.74653,-18.17347 5.04869,-8.0771 7.57305,-14.63948 7.57305,-19.68716 l 0,-171.13275 c 0,-18.17347 -7.06746,-30.28912 -21.20238,-36.34694 L 637.01936,545.01619 573.41221,514.72707 c 38.36622,-22.21202 63.60715,-60.57824 75.7228,-115.09865 8.0771,-30.28912 8.0771,-61.58788 0,-93.89627 -10.09637,-36.34695 -28.7744,-67.14115 -56.0341,-92.38259 -27.25969,-25.24145 -59.06352,-38.87182 -95.4115,-40.89109 -36.34694,2.01927 -67.6457,15.64964 -93.89627,40.89109 -26.25057,25.24144 -44.42404,55.02601 -54.52042,89.35368 -12.11564,46.44331 -8.07709,93.89627 12.11565,142.35886 16.1542,30.28912 37.35658,54.52041 63.60715,72.69389 l -57.54932,27.2602 -151.4456,69.66498 c -16.1542,8.0771 -24.2313,21.20238 -24.2313,39.37585 l 0,142.35887 z m 475.53918,-302.8912 c 8.0771,8.0771 18.17347,16.1542 30.28912,24.23129 12.11565,8.0771 23.22166,14.13493 33.31803,18.17348 10.09638,4.03855 23.22166,9.59181 39.37586,16.65979 16.1542,7.06797 28.26984,12.62124 36.34694,16.65979 16.1542,8.0771 28.77493,19.68819 37.86218,34.83326 9.08724,15.14507 13.63088,31.80384 13.63088,49.97627 l 0,142.35887 115.09865,0 c 18.17347,-2.01928 27.26021,-13.12529 27.26021,-33.31803 l 0,-136.30104 c 0,-14.13493 -5.04819,-24.2313 -15.14456,-30.28912 L 815.72517,514.72707 c 42.40477,-30.28912 63.60715,-73.70352 63.60715,-130.24321 0,-38.36622 -12.11565,-72.18881 -36.34694,-101.46778 -24.2313,-29.27897 -53.51078,-43.91896 -87.83845,-43.92 -22.21202,0 -44.42404,7.06747 -66.63606,21.20239 12.11564,30.28912 18.17347,61.58787 18.17347,93.89627 0,50.48187 -13.12529,96.92518 -39.37586,139.32995 z"
id="path4"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cscsscccsssccscccscccccssscccccscscccccscccssssssccssccssccscc"
style="fill:#ffffff;stroke-width:1.55090213" />
</svg>

Depois

Largura:  |  Altura:  |  Tamanho: 4.2 KiB

+30 -10
Ver Arquivo
@@ -14,7 +14,7 @@
inkscape:version="0.48+devel r"
width="15"
height="15"
sodipodi:docname="padlock_open-white.svg">
sodipodi:docname="padlock_close_green.svg">
<metadata
id="metadata3047">
<rdf:RDF>
@@ -42,25 +42,45 @@
inkscape:window-height="1056"
id="namedview3043"
showgrid="false"
inkscape:zoom="44.500587"
inkscape:cx="6.292871"
inkscape:cy="6.4926565"
inkscape:zoom="32"
inkscape:cx="12.823367"
inkscape:cy="8.9449238"
inkscape:window-x="65"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:current-layer="svg3041"
borderlayer="true" />
<rect
style="fill:#009800;stroke:#009800;stroke-width:0.92522794"
style="fill:#44aa00;stroke:#44aa00;stroke-width:0.92522794"
id="rect3051"
width="10.232394"
height="6.4687548"
x="2.5534275"
y="8.074255" />
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-color:currentColor;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;color-interpolation:sRGB;color-interpolation-filters:linearRGB;fill:#009800;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.90384686;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="M 7.5078125,2.6797098 C 5.0260054,2.6797098 3.491603,3.472493 2.75,4.621116 2.008397,5.7697391 2.0878906,7.0238438 2.0878906,7.699241 l 1.9042969,0 c 0,-0.7329344 0.013699,-1.5125503 0.3574219,-2.0449218 0.3437231,-0.5323715 1.0433343,-1.0703125 3.1582031,-1.0703125 2.0264219,0 2.9669635,0.6265545 3.4326915,1.3827484 0.465728,0.7561939 0.400333,1.7142789 0.400333,1.7142789 0.04517,1.7732263 -0.06599,4.303173 0.0049,5.535784 l 0.05274,0.898438 0.898437,0 0.945445,-0.0031 0.01,-6.4361369 c 0,0 0.06201,-1.6621328 -0.685321,-2.8754827 C 11.819768,3.587152 10.078064,2.6797098 7.5078125,2.6797098 Z"
id="path3848"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ssccssscccccccs" />
style="fill:none;fill-opacity:1;stroke:#44aa00;stroke-width:2.08827519;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4101"
sodipodi:type="arc"
sodipodi:cx="7.6713805"
sodipodi:cy="6.7928491"
sodipodi:rx="4.534133"
sodipodi:ry="4.5301714"
sodipodi:start="3.1415927"
sodipodi:end="0"
d="M 3.1372476,6.7928489 A 4.534133,4.5301714 0 0 1 7.6713806,2.2626777 4.534133,4.5301714 0 0 1 12.205513,6.7928491"
sodipodi:open="true" />
<rect
style="fill:#44aa00;fill-opacity:1;stroke:none;stroke-width:1.39526081;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4153"
width="2.0906768"
height="1.0984892"
x="2.0913804"
y="6.7554431" />
<rect
y="6.7632556"
x="11.157786"
height="1.0984892"
width="2.0906768"
id="rect4155"
style="fill:#44aa00;fill-opacity:1;stroke:none;stroke-width:1.39526081;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</svg>

Antes

Largura:  |  Altura:  |  Tamanho: 3.3 KiB

Depois

Largura:  |  Altura:  |  Tamanho: 2.7 KiB

+38 -10
Ver Arquivo
@@ -14,7 +14,7 @@
inkscape:version="0.48+devel r"
width="15"
height="15"
sodipodi:docname="padlock_open-white.svg">
sodipodi:docname="padlock_close_grey.svg">
<metadata
id="metadata3047">
<rdf:RDF>
@@ -42,9 +42,9 @@
inkscape:window-height="1056"
id="namedview3043"
showgrid="false"
inkscape:zoom="44.500587"
inkscape:cx="6.292871"
inkscape:cy="6.4926565"
inkscape:zoom="32"
inkscape:cx="12.792117"
inkscape:cy="8.9449238"
inkscape:window-x="65"
inkscape:window-y="24"
inkscape:window-maximized="1"
@@ -57,10 +57,38 @@
height="6.4687548"
x="2.5534275"
y="8.074255" />
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-color:currentColor;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;color-interpolation:sRGB;color-interpolation-filters:linearRGB;fill:#808080;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.90384686;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="M 7.5078125,2.6797098 C 5.0260054,2.6797098 3.491603,3.472493 2.75,4.621116 2.008397,5.7697391 2.0878906,7.0238438 2.0878906,7.699241 l 1.9042969,0 c 0,-0.7329344 0.013699,-1.5125503 0.3574219,-2.0449218 0.3437231,-0.5323715 1.0433343,-1.0703125 3.1582031,-1.0703125 2.0264219,0 2.9669635,0.6265545 3.4326915,1.3827484 0.465728,0.7561939 0.400333,1.7142789 0.400333,1.7142789 0.04517,1.7732263 -0.06599,4.303173 0.0049,5.535784 l 0.05274,0.898438 0.898437,0 0.945445,-0.0031 0.01,-6.4361369 c 0,0 0.06201,-1.6621328 -0.685321,-2.8754827 C 11.819768,3.587152 10.078064,2.6797098 7.5078125,2.6797098 Z"
id="path3848"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ssccssscccccccs" />
<a
id="a4157"
style="fill:none;stroke:#808080">
<path
sodipodi:open="true"
d="M 3.1372476,6.7928489 A 4.534133,4.5301714 0 0 1 7.6713806,2.2626777 4.534133,4.5301714 0 0 1 12.205513,6.7928491"
sodipodi:end="0"
sodipodi:start="3.1415927"
sodipodi:ry="4.5301714"
sodipodi:rx="4.534133"
sodipodi:cy="6.7928491"
sodipodi:cx="7.6713805"
sodipodi:type="arc"
id="path4101"
style="fill:none;fill-opacity:1;stroke:#808080;stroke-width:2.08827519;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</a>
<g
id="g4170"
style="fill:#808080">
<rect
y="6.7554431"
x="2.0913804"
height="1.0984892"
width="2.0906768"
id="rect4153"
style="fill:#808080;fill-opacity:1;stroke:none;stroke-width:1.39526081;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
style="fill:#808080;fill-opacity:1;stroke:none;stroke-width:1.39526081;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4155"
width="2.0906768"
height="1.0984892"
x="11.157786"
y="6.7632556" />
</g>
</svg>

Antes

Largura:  |  Altura:  |  Tamanho: 3.3 KiB

Depois

Largura:  |  Altura:  |  Tamanho: 2.8 KiB

+39 -11
Ver Arquivo
@@ -14,7 +14,7 @@
inkscape:version="0.48+devel r"
width="15"
height="15"
sodipodi:docname="padlock_open-white.svg">
sodipodi:docname="padlock_close_orange.svg">
<metadata
id="metadata3047">
<rdf:RDF>
@@ -42,25 +42,53 @@
inkscape:window-height="1056"
id="namedview3043"
showgrid="false"
inkscape:zoom="44.500587"
inkscape:cx="6.292871"
inkscape:cy="6.4926565"
inkscape:zoom="32"
inkscape:cx="12.792117"
inkscape:cy="8.9449238"
inkscape:window-x="65"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:current-layer="svg3041"
borderlayer="true" />
<rect
style="fill:#ff9955;stroke:#ff9955;stroke-width:0.92522794"
style="fill:#ff7f2a;stroke:#ff7f2a;stroke-width:0.92522794"
id="rect3051"
width="10.232394"
height="6.4687548"
x="2.5534275"
y="8.074255" />
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-color:currentColor;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;color-interpolation:sRGB;color-interpolation-filters:linearRGB;fill:#ff9955;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.90384686;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="M 7.5078125,2.6797098 C 5.0260054,2.6797098 3.491603,3.472493 2.75,4.621116 2.008397,5.7697391 2.0878906,7.0238438 2.0878906,7.699241 l 1.9042969,0 c 0,-0.7329344 0.013699,-1.5125503 0.3574219,-2.0449218 0.3437231,-0.5323715 1.0433343,-1.0703125 3.1582031,-1.0703125 2.0264219,0 2.9669635,0.6265545 3.4326915,1.3827484 0.465728,0.7561939 0.400333,1.7142789 0.400333,1.7142789 0.04517,1.7732263 -0.06599,4.303173 0.0049,5.535784 l 0.05274,0.898438 0.898437,0 0.945445,-0.0031 0.01,-6.4361369 c 0,0 0.06201,-1.6621328 -0.685321,-2.8754827 C 11.819768,3.587152 10.078064,2.6797098 7.5078125,2.6797098 Z"
id="path3848"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ssccssscccccccs" />
<a
id="a4157"
style="fill:none;stroke:#ff7f2a">
<path
sodipodi:open="true"
d="M 3.1372476,6.7928489 A 4.534133,4.5301714 0 0 1 7.6713806,2.2626777 4.534133,4.5301714 0 0 1 12.205513,6.7928491"
sodipodi:end="0"
sodipodi:start="3.1415927"
sodipodi:ry="4.5301714"
sodipodi:rx="4.534133"
sodipodi:cy="6.7928491"
sodipodi:cx="7.6713805"
sodipodi:type="arc"
id="path4101"
style="fill:none;fill-opacity:1;stroke:#ff7f2a;stroke-width:2.08827519;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</a>
<g
id="g4170"
style="fill:#ff7f2a">
<rect
y="6.7554431"
x="2.0913804"
height="1.0984892"
width="2.0906768"
id="rect4153"
style="fill:#ff7f2a;fill-opacity:1;stroke:none;stroke-width:1.39526081;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
style="fill:#ff7f2a;fill-opacity:1;stroke:none;stroke-width:1.39526081;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect4155"
width="2.0906768"
height="1.0984892"
x="11.157786"
y="6.7632556" />
</g>
</svg>

Antes

Largura:  |  Altura:  |  Tamanho: 3.3 KiB

Depois

Largura:  |  Altura:  |  Tamanho: 2.8 KiB

Arquivo binário não exibido.

Antes

Largura:  |  Altura:  |  Tamanho: 783 B

+76
Ver Arquivo
@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="15"
height="15"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="resize_gray.svg">
<defs
id="defs4">
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath3803">
<rect
style="stroke:none"
id="rect3805"
width="16.09375"
height="14.71875"
x="0.84375"
y="1038.1434" />
</clipPath>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="32"
inkscape:cx="6.9909088"
inkscape:cy="6.5564812"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1865"
inkscape:window-height="1056"
inkscape:window-x="55"
inkscape:window-y="24"
inkscape:window-maximized="1" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1037.3622)">
<path
style="fill:none;stroke:#bfbfbf;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 10.46875,1032.1747 -14.5,14.2813 z m 3.5,1.2501 -17.3125,17.3124 z"
id="path2985"
inkscape:connector-curvature="0"
clip-path="url(#clipPath3803)"
transform="translate(0.8125,0.6875)"
sodipodi:nodetypes="cccccc" />
</g>
</svg>

Depois

Largura:  |  Altura:  |  Tamanho: 2.2 KiB

Arquivo binário não exibido.

Depois

Largura:  |  Altura:  |  Tamanho: 560 B

+66
Ver Arquivo
@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="25"
height="25"
id="svg2"
version="1.1"
inkscape:version="0.48+devel r"
viewBox="0 0 25 25.000001"
sodipodi:docname="speech_balloon_white.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="22.4"
inkscape:cx="25.186628"
inkscape:cy="14.479999"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1855"
inkscape:window-height="1056"
inkscape:window-x="65"
inkscape:window-y="24"
inkscape:window-maximized="1" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-228.24219,-320.66798)">
<path
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 240.77627,324.02578 a 12.489309,7.9254426 0 0 0 -12.48944,7.92538 12.489309,7.9254426 0 0 0 5.26146,6.45637 c -0.17862,1.91196 -1.06119,3.95363 -3.14604,4.64437 2.54121,-0.11444 5.60026,-1.93057 7.47209,-3.40137 a 12.489309,7.9254426 0 0 0 2.90193,0.22616 12.489309,7.9254426 0 0 0 12.48928,-7.92553 12.489309,7.9254426 0 0 0 -12.48928,-7.92538 z"
id="path4101"
inkscape:connector-curvature="0" />
</g>
</svg>

Depois

Largura:  |  Altura:  |  Tamanho: 2.3 KiB

-655
Ver Arquivo
@@ -1,655 +0,0 @@
.jsxc_online,.jsxc_chat {
border-left: 4px solid #00BFFF !important;
}
.jsxc_away,.jsxc_xa {
border-left: 4px solid orange !important;
}
.jsxc_dnd {
border-left: 4px solid red !important;
}
.jsxc_offline {
border-left: 4px solid #A4A4A4 !important;
}
.jsxc_hidden {
display: none;
}
.jsxc_invalid {
border: 2px solid red !important;
}
p.jsxc_right {
text-align: right;
}
p.jsxc_center {
text-align: center;
}
/*############################
*########## Dialog ##########
*############################*/
#jsxc_dialog {
padding: 10px;
min-width: 300px;
}
#jsxc_dialog h3 {
font-size: 120%;
font-weight: bold;
margin-bottom: 10px;
margin-top: 20px;
}
#jsxc_dialog p input {
margin-bottom: 5px;
width: 60%;
outline: none;
}
#jsxc_dialog p label {
display: block;
width: 30%;
float: left;
padding: 6px 0px;
}
#jsxc_dialog .jsxc_right {
margin-top: 20px;
}
#jsxc_dialog p.jsxc_maxWidth {
max-width: 500px;
}
/*############################
*########## Overall #########
*############################*/
li .jsxc_name {
overflow: hidden;
height: 30px;
cursor: pointer;
text-overflow: ellipsis;
white-space: nowrap;
}
.jsxc_avatar, ul#jsxc_buddylist li:hover .jsxc_avatar {
width: 25px;
height: 25px;
line-height: 25px;
margin-top: 2px;
margin-right: 4px;
background-color: #a3a3a3;
border-radius: 2px;
float: left;
text-align: center;
font-weight: bold;
font-size: 30px;
color: #b1b1b1;
overflow: hidden;
position: relative;
font-family: Arial;
}
.jsxc_avatar img {
display: block;
width: 25px;
height: 25px;
position: absolute;
top: 0px;
left: 0px;
}
/*############################
*########## Roster ##########
*############################*/
div#jsxc_roster {
position: fixed;
top: 0px;
bottom: 0px;
right: 0px;
width: 200px;
overflow: visible;
border-left: 4px solid #A4A4A4;
z-index: 80;
margin-left: 10px;
box-shadow: 0px 0px 7px #000000;
}
div#jsxc_roster .slimScrollDiv {
left: -4px;
margin-bottom: 30px;
z-index: 40;
}
div#jsxc_roster .jsxc_wait {
position: absolute;
top: 0px;
left: 0px;
bottom: 0px;
width: 160px;
padding: 20px;
background-color: #fff;
z-index: 60;
}
div#jsxc_roster .jsxc_wait img {
padding: 5px;
}
div#jsxc_roster .jsxc_wait h3 {
margin-bottom: 5px;
font-size: 1.13em;
font-weight: bold;
}
/** Input field for alias renaming */
#jsxc_roster input {
position: absolute;
left: 31px;
top: 2px;
width: 157px;
height: 22px;
padding: 2px;
border: 0px;
background-image: none;
background-color: #fff;
border-radius: 3px;
-moz-box-shadow: inset 0 0 5px #888;
-webkit-box-shadow: inset 0 0 5px #888;
box-shadow: inner 0 0 5px #888;
outline: none;
}
div#jsxc_roster p {
color: #939393;
}
div#jsxc_roster>.jsxc_bottom {
position: absolute;
left: -4px;
bottom: 0px;
height: 30px;
width: 200px;
border-left: 4px solid #A4A4A4;
border-top: 1px solid #939393;
padding-left: 0px;
background-color: #282323;
color: #939393;
cursor: pointer;
line-height: 30px;
z-index: 50;
}
div#jsxc_roster>.jsxc_bottom>div:hover {
color: #FAFAFA;
}
div#jsxc_roster>.jsxc_bottom>div>span {
cursor: pointer;
}
div#jsxc_roster>.jsxc_bottom ul {
width: 190px;
position: absolute;
bottom: 30px;
left: 0px;
display: none;
border-top: 1px solid #939393;
padding-left: 10px;
background-color: #282323;
margin: 0;
}
div#jsxc_roster>.jsxc_bottom li {
height: 30px;
background-color: #282323;
color: #939393;
cursor: pointer;
width: 180px;
padding-left: 10px;
line-height: 30px;
text-align: left;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
div#jsxc_roster>.jsxc_bottom li:hover:not(.jsxc_disabled) {
color: #fff;
background-color: #3F8FBA;
}
div#jsxc_roster>.jsxc_bottom li.jsxc_disabled {
color: #595959;
cursor: default;
}
div#jsxc_roster>.jsxc_bottom ul li:last-child {
border-bottom: 1px solid #939393;
}
#jsxc_menu,#jsxc_avatar,#jsxc_notice {
height: 30px;
width: 30px;
}
#jsxc_avatar {
float: left;
margin: 0px 2px;
width: 25px;
}
#jsxc_menu {
cursor: pointer;
float: right;
text-align: center;
width: 25px;
}
#jsxc_menu>span {
opacity: 0.5;
display: block;
width: 25px;
height: 30px;
background-image: url('img/gear_white.svg');
background-size: 18px 18px;
background-repeat: no-repeat;
background-position: center center;
}
#jsxc_menu:hover>span {
opacity: 1;
}
#jsxc_notice {
float: right;
text-align: center;
line-height: 30px;
}
#jsxc_notice>span:empty {
display: none;
}
#jsxc_notice span {
background-color: #fbc14c;
border-radius: 11px;
color: black;
font-size: 80%;
padding: 2px;
}
#jsxc_presence {
cursor: pointer;
padding-left: 2px;
overflow: hidden;
}
/** List of all buddies inside the roster */
ul#jsxc_buddylist {
list-style: none;
padding: 0px;
margin: 0px;
width: 204px;
}
ul#jsxc_buddylist li {
padding: 0px;
margin: 0px;
height: 30px;
border-bottom: 1px solid #939393;
cursor: pointer;
width: 200px;
position: relative;
color: #939393;
font-family: Arial;
line-height: 30px;
padding-left: 3px;
z-index: 85;
}
ul#jsxc_buddylist li:hover {
color: #FAFAFA;
}
ul#jsxc_buddylist li.jsxc_oneway {
opacity: 0.7;
}
ul#jsxc_buddylist .jsxc_options {
height: 30px;
float: right;
overflow: hidden;
transition: width 2s;
width: 0px;
-webkit-transition: width .5s; /* Safari */
white-space: nowrap;
}
ul#jsxc_buddylist .jsxc_options div {
line-height: 30px;
height: 30px;
width: 20px;
cursor: pointer;
opacity: 0.7;
display: inline-block;
font-weight: bold;
text-align: center;
font-size: 17px;
overflow: hidden;
}
ul#jsxc_buddylist li[data-type="chat"]:hover .jsxc_options {
width: 50px;
}
ul#jsxc_buddylist .jsxc_options div:hover {
opacity: 1.0;
}
ul#jsxc_buddylist .jsxc_rename {
/* background-image: url('../img/edit.png'); */
/* background-repeat: no-repeat; */
/* background-position: center center; */
/* background-size: 15px 15px; */
transform: scaleX(-1);
}
ul#jsxc_buddylist .jsxc_delete {
/* text-transform: lowercase; */
/* font-weight: bold; */
/* vertical-align: middle; */
/* font-size: 17px; */
}
div#jsxc_toggleRoster {
width: 14px;
height: 100%;
position: absolute;
left: -14px !important;
top: 0px;
z-index: 110;
background-color: transparent;
cursor: pointer;
}
#jsxc_toggleRoster:hover {
background-color: #a4a4a4;
opacity: 0.5;
}
/*############################
*###### Window List #########
*############################*/
div#jsxc_windowList {
position: fixed;
bottom: 0px;
right: 0px;
width: 100%;
z-index: 50;
}
div#jsxc_windowList>ul {
list-style: none;
padding: 0px;
margin: 0px;
padding-right: 210px;
height: 30px;
overflow: visible;
}
div#jsxc_windowList>ul>li {
padding: 0px;
margin: 0px;
display: block;
float: right;
width: 200px;
background-color: #282323;
height: 30px;
position: relative;
overflow: visible;
margin-right: 5px;
box-shadow: 0px 0px 5px #000;
cursor: pointer;
}
/*############################
*######### Window ###########
*############################*/
div.jsxc_bar {
cursor: pointer;
height: 30px;
line-height: 30px;
margin-left: 2px;
color: #939393;
}
div.jsxc_bar:hover {
color: #FAFAFA;
}
div.jsxc_cycle {
position: absolute;
bottom: 9px;
right: 5px;
height: 12px;
width: 12px;
border-radius: 6px;
}
div#jsxc_windowList>ul>li.jsxc_unreadMsg .jsxc_name {
font-style: italic;
}
div#jsxc_windowList>ul>li.jsxc_unreadMsg .jsxc_cycle {
background-color: orange;
}
/** Contains text area */
div.jsxc_window {
display: none;
width: 200px;
height: 255px;
position: absolute;
bottom: 30px;
right: 0px;
background-color: #A4A4A4;
box-shadow: 0px 0px 5px #000;
z-index: 80;
cursor: default;
}
div.jsxc_window .jsxc_tools {
position: absolute;
top: 0px;
left: 0px;
width: 200px;
height: 23px;
background-color: #282323;
box-shadow: 0px 5px 5px -5px #000;
z-index: 100;
}
div.jsxc_window .jsxc_textarea {
width: 200px;
height: 200px;
overflow: hidden;
}
div.jsxc_window .slimScrollDiv {
position: absolute;
top: 22px;
left: 0px;
}
div.jsxc_chatmessage,input.jsxc_chatmessage {
margin: 5px;
border-radius: 5px !important;
padding: 3px;
width: 157px;
word-wrap: break-word;
background-color: #fff;
position: relative;
outline: none;
}
div.jsxc_chatmessage.jsxc_received {
}
div.jsxc_chatmessage.jsxc_received:before {
content: '✓';
position: absolute;
bottom: 2px;
left: 4px;
font-size: 10px;
line-height: 10px;
color: green;
}
div.jsxc_chatmessage a {
color: blue;
text-decoration: underline;
}
div.jsxc_chatmessage img {
width: 19px;
height: 19px;
}
/** incoming message */
div.jsxc_in,input.jsxc_in {
text-align: left;
margin-right: 30px;
border: 1px solid blue;
}
/** outgoing message */
div.jsxc_out,input.jsxc_out {
text-align: right;
margin-left: 30px;
border: 1px solid green !important;
}
/** system message */
div.jsxc_sys {
width: 182px;
border: 1px solid black;
}
.jsxc_window input.jsxc_textinput {
position: absolute;
top: 226px;
left: 30px;
width: 157px;
height: 16px;
margin: 0px;
line-height: 16px;
outline:none;
}
.jsxc_window .jsxc_close {
text-transform: uppercase;
color: #939393;
font-family: Arial;
font-weight: bold;
line-height: 17px;
cursor: pointer;
float: right;
padding: 3px;
}
.jsxc_window .jsxc_close:hover {
color: #FAFAFA;
}
div.jsxc_settings {
color: #939393;
font-family: Arial;
line-height: 17px;
cursor: pointer;
background-image: url('img/gear_grey.svg');
background-size: 15px 15px;
background-repeat: no-repeat;
background-position: center center;
width: 17px;
height: 17px;
display: block;
float: left;
overflow: visible;
padding: 3px;
}
div.jsxc_settings:hover,div.jsxc_settings.hover {
background-image: url('img/gear_white.svg');
}
div.jsxc_settings ul {
list-style: none;
padding: 0px;
margin: 0px;
position: absolute;
top: 23px;
left: 0px;
box-shadow: 0px 5px 5px -5px #000;
z-index: 90;
overflow: visible;
background-color: #282323;
display: none;
}
div.jsxc_settings li {
width: 170px;
margin-left: 20px;
padding-left: 10px;
height: 30px;
line-height: 30px;
}
div.jsxc_settings li:first-child {
border-top: 1px solid #ccc;
}
div.jsxc_settings li:hover:not(.jsxc_disabled){
color: #fff;
background-color: #3F8FBA;
}
div.jsxc_settings li.jsxc_disabled {
color: #595959;
cursor: default;
}
div.jsxc_transfer {
padding: 3px;
width: 17px;
height: 17px;
background-image: url('img/padlock_open_grey.svg');
background-repeat: no-repeat;
background-position: center center;
background-size: 15px 15px;
cursor: pointer;
float: left;
}
div.jsxc_transfer.jsxc_fin {
background-image: url('img/padlock_close_grey.svg');
}
div.jsxc_transfer.jsxc_enc {
background-image: url('img/padlock_close_orange.svg');
}
div.jsxc_transfer.jsxc_enc.jsxc_trust {
background-image: url('img/padlock_close_green.svg');
}
#colorbox, #cboxWrapper {
outline: none;
}
+9696
Ver Arquivo
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
-4501
Ver Arquivo
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
-848
Ver Arquivo
@@ -1,848 +0,0 @@
/**
* jsxc v0.7.2 - 2014-05-28
*
* Copyright (c) 2014 Klaus Herberth <klaus@jsxc.org> <br>
* Released under the MIT license
*
* Please see http://www.jsxc.org/
*
* @author Klaus Herberth <klaus@jsxc.org>
* @version 0.7.2
*/
/* jsxc, Strophe, SDPUtil, getUserMediaWithConstraints, setupRTC, jQuery */
var RTC = null, RTCPeerconnection = null;
jsxc.gui.template.incomingCall = '<h3>%%Incoming_call%%</h3>\
<p>%%Do_you_want_to_accept_the_call_from%% {{cid_name}}?</p>\
<p class="jsxc_right">\
<a href="#" class="button jsxc_reject">%%Reject%%</a> <a href="#" class="button creation jsxc_accept">%%Accept%%</a>\
</p>';
jsxc.gui.template.allowMediaAccess = '<p>%%Please_allow_access_to_microphone_and_camera%%</p>';
jsxc.gui.template.videoWindow = '<div class="jsxc_webrtc">\
<div class="jsxc_videoContainer">\
<video class="jsxc_localvideo" autoplay></video>\
<video class="jsxc_remotevideo" autoplay></video>\
<div class="jsxc_status"></div>\
</div>\
<div class="jsxc_controlbar">\
<button type="button" class="jsxc_hangUp">%%hang_up%%</button>\
<input type="range" class="jsxc_volume" min="0.0" max="1.0" step="0.05" value="0.5" />\
<div class="jsxc_buttongroup">\
<button type="button" class="jsxc_snapshot">%%snapshot%%</button><button type="button" class="jsxc_snapshots">&#9660;</button>\
</div>\
<!-- <button type="button" class="jsxc_mute_local">%%mute_my_audio%%</button>\
<button type="button" class="jsxc_pause_local">%%pause_my_video%%</button> --> \
<button type="button" class="jsxc_showchat">%%chat%%</button>\
<button type="button" class="jsxc_fullscreen">%%fullscreen%%</button>\
<button type="button" class="jsxc_info">%%Info%%</button>\
</div>\
<div class="jsxc_multi">\
<div class="jsxc_snapshotbar">\
<p>No pictures yet!</p>\
</div>\n\
<div class="jsxc_chatarea">\
<ul></ul>\
</div>\
<div class="jsxc_infobar"></div>\
</div>\
</div>';
(function($) {
"use strict";
/**
* WebRTC namespace for jsxc.
*
* @namespace jsxc.webrtc
*/
jsxc.webrtc = {
/** strophe connection */
conn: null,
/** local video stream */
localStream: null,
/** remote video stream */
remoteStream: null,
/** jid of the last caller */
last_caller: null,
/** should we auto accept incoming calls? */
AUTO_ACCEPT: false,
/** required disco features */
reqVideoFeatures: [ 'urn:xmpp:jingle:apps:rtp:video', 'urn:xmpp:jingle:apps:rtp:audio', 'urn:xmpp:jingle:transports:ice-udp:1' ],
/** bare jid to current jid mapping */
chatJids: {},
/**
* Initialize webrtc plugin.
*
* @private
* @memberOf jsxc.webrtc
*/
init: function() {
var self = jsxc.webrtc;
// shortcut
self.conn = jsxc.xmpp.conn;
if (RTC.browser === 'firefox') {
self.conn.jingle.media_constraints.mandatory.MozDontOfferDataChannel = true;
}
if (!self.conn.jingle) {
jsxc.error('No jingle plugin found!');
return;
}
// jingle configuration
self.conn.jingle.PRANSWER = false;
self.conn.jingle.AUTOACCEPT = false;
self.conn.jingle.ice_config = jsxc.storage.getUserItem('iceConfig');
self.conn.jingle.MULTIPARTY = false;
self.conn.jingle.pc_constraints = RTC.pc_constraints;
$(document).on('message.jsxc', $.proxy(self.onMessage, self));
$(document).on('mediaready.jingle', $.proxy(self.onMediaReady, self));
$(document).on('mediafailure.jingle', $.proxy(self.onMediaFailure, self));
$(document).on('callincoming.jingle', $.proxy(self.onCallIncoming, self));
$(document).on('callterminated.jingle', $.proxy(self.onCallTerminated, self));
$(document).on('ringing.jingle', $.proxy(self.onCallRinging, self));
$(document).on('remotestreamadded.jingle', $.proxy(self.onRemoteStreamAdded, self));
$(document).on('remotestreamremoved.jingle', $.proxy(self.onRemoteStreamRemoved, self));
$(document).on('iceconnectionstatechange.jingle', $.proxy(self.onIceConnectionStateChanged, self));
$(document).on('nostuncandidates.jingle', $.proxy(self.noStunCandidates, self));
$(document).on('error.jingle', function(ev, sid, error) {
jsxc.error('[JINGLE]', error);
});
if (self.conn.caps) {
$(document).on('caps.strophe', $.proxy(self.onCaps, self));
}
self.getTurnCrendentials();
},
/**
* Checks if cached configuration is valid and if necessary update it.
*
* @memberOf jsxc.webrtc
*/
getTurnCrendentials: function() {
if (!jsxc.options.turnCredentialsPath) {
jsxc.debug('No path for TURN credentials defined!');
return;
}
var ttl = (jsxc.storage.getUserItem('iceValidity') || 0) - (new Date()).getTime();
if (ttl > 0) {
// credentials valid
window.setTimeout(jsxc.webrtc.getTurnCrendentials, ttl + 500);
return;
}
$.ajax(jsxc.options.turnCredentialsPath, {
async: true,
success: function(data) {
var iceConfig = {
iceServers: [ {
url: 'turn:' + data.url,
credential: data.credential,
username: data.username
} ]
};
jsxc.webrtc.conn.jingle.ice_config = iceConfig;
jsxc.storage.setUserItem('iceConfig', iceConfig);
jsxc.storage.setUserItem('iceValidity', (new Date()).getTime() + 1000 * data.ttl);
},
dataType: 'json'
});
},
/**
* Add "video" button to window menu.
*
* @private
* @memberOf jsxc.webrtc
* @param event
* @param win jQuery window object
*/
initWindow: function(event, win) {
var self = jsxc.webrtc;
if (!self.conn) {
$(document).one('connectionReady.jsxc', function() {
self.initWindow(null, win);
});
return;
}
var div = $('<div>').addClass('jsxc_video');
win.find('.jsxc_transfer:eq(1)').after(div);
self.updateWindow(win);
},
/**
* Enable or disable "video" button and assign full jid.
*
* @memberOf jsxc.webrtc
* @param win jQuery window object
*/
updateWindow: function(win) {
if (!win || win.length === 0) {
return;
}
var self = jsxc.webrtc;
var jid = win.data('jid');
var li = win.find('.jsxc_video');
// only start video call to a full jid
if (Strophe.getResourceFromJid(jid) === null) {
var cid = jsxc.jidToCid(jid);
var res = jsxc.storage.getUserItem('buddy_' + cid).res;
if (Array.isArray(res) && res.length === 1) {
jid += '/' + res[0];
}
}
li.off('click');
if (self.conn.caps.hasFeatureByJid(jid, self.reqVideoFeatures)) {
li.click(function() {
self.startCall(jid);
});
li.removeClass('jsxc_disabled');
li.attr('title', jsxc.translate('%%Start video call%%'));
} else {
li.addClass('jsxc_disabled');
li.attr('title', jsxc.translate('%%Video call not possible.%%'));
}
},
/**
* Check if full jid changed.
*
* @private
* @memberOf jsxc.webrtc
* @param e
* @param from full jid
*/
onMessage: function(e, from) {
var self = jsxc.webrtc;
var bJid = Strophe.getBareJidFromJid(from);
if (self.chatJids[bJid] !== from) {
self.updateWindow(jsxc.gui.getWindow(jsxc.jidToCid(bJid)));
self.chatJids[bJid] = from;
}
},
/**
* Display status message to user.
*
* @memberOf jsxc.webrtc
* @param txt message
* @param d duration in ms
*/
setStatus: function(txt, d) {
var status = $('.jsxc_webrtc .jsxc_status');
var duration = (typeof d === 'undefined' || d === null) ? 4000 : d;
jsxc.debug('[Webrtc]', txt);
if (status.html()) {
// attach old messages
txt = status.html() + '<br />' + txt;
}
status.html(txt);
status.css({
'margin-left': '-' + (status.width() / 2) + 'px',
opacity: 0,
display: 'block'
});
status.stop().animate({
opacity: 1
});
clearTimeout(status.data('timeout'));
if (duration === 0) {
return;
}
var to = setTimeout(function() {
status.stop().animate({
opacity: 0
}, function() {
status.html('');
});
}, duration);
status.data('timeout', to);
},
/**
* Update "video" button if we receive cap information.
*
* @private
* @memberOf jsxc.webrtc
* @param event
* @param jid
*/
onCaps: function(event, jid) {
var self = jsxc.webrtc;
var win = jsxc.gui.getWindow(jsxc.jidToCid(jid));
if (win.length > 0) {
self.updateWindow(win);
}
},
/**
* Called if video/audio is ready. Open window and display some messages.
*
* @private
* @memberOf jsxc.webrtc
* @param event
* @param stream
*/
onMediaReady: function(event, stream) {
jsxc.debug('media ready');
var self = jsxc.webrtc;
self.localStream = stream;
self.conn.jingle.localStream = stream;
jsxc.gui.showVideoWindow(self.last_caller);
var i;
for (i = 0; i < stream.getAudioTracks().length; i++) {
self.setStatus((stream.getAudioTracks().length > 0) ? 'Use local audio device.' : 'No local audio device.');
jsxc.debug('using audio device "' + stream.getAudioTracks()[i].label + '"');
}
for (i = 0; i < stream.getVideoTracks().length; i++) {
self.setStatus((stream.getVideoTracks().length > 0) ? 'Use local video device.' : 'No local video device.');
jsxc.debug('using video device "' + stream.getVideoTracks()[i].label + '"');
}
$(document).one('cleanup.dialog.jsxc', $.proxy(self.hangUp, self));
$(document).trigger('finish.mediaready.jsxc');
},
/**
* Called if media failes.
*
* @private
* @memberOf jsxc.webrtc
*/
onMediaFailure: function() {
this.setStatus('media failure');
},
/**
* Called on incoming call.
*
* @private
* @memberOf jsxc.webrtc
* @param event
* @param sid Session id
*/
onCallIncoming: function(event, sid) {
jsxc.debug('incoming call' + sid);
var self = this;
var sess = this.conn.jingle.sessions[sid];
var jid = jsxc.jidToCid(sess.peerjid);
// display notification
jsxc.notification.notify(jsxc.translate('%%Incoming call%%'), jsxc.translate('%%from%% ' + jid));
// send signal to partner
sess.sendRinging();
jsxc.webrtc.last_caller = sess.peerjid;
jsxc.switchEvents({
'mediaready.jingle': function(event, stream) {
self.setStatus('Accept call');
sess.localStream = stream;
sess.peerconnection.addStream(stream);
sess.sendAnswer();
sess.accept();
},
'mediafailure.jingle': function() {
sess.sendTerminate('decline');
sess.terminate();
}
});
if (jsxc.webrtc.AUTO_ACCEPT) {
self.reqUserMedia();
return;
}
var dialog = jsxc.gui.dialog.open(jsxc.gui.template.get('incomingCall', jsxc.jidToCid(jid)));
dialog.find('.jsxc_accept').click(function() {
$(document).trigger('accept.call.jsxc');
self.reqUserMedia();
});
dialog.find('.jsxc_reject').click(function() {
jsxc.gui.dialog.close();
$(document).trigger('reject.call.jsxc');
sess.sendTerminate('decline');
sess.terminate();
});
},
/**
* Called if call is terminated.
*
* @private
* @memberOf jsxc.webrtc
* @param event
* @param sid Session id
* @param reason Reason for termination
* @param [text] Optional explanation
*/
onCallTerminated: function(event, sid, reason, text) {
this.setStatus('call terminated ' + sid + (reason ? (': ' + reason + ' ' + text) : ''));
if (this.localStream) {
this.localStream.stop();
}
$('.jsxc_remotevideo')[0].src = "";
$('.jsxc_localvideo')[0].src = "";
this.conn.jingle.localStream = null;
this.localStream = null;
this.remoteStream = null;
$('#jsxc_windowList > ul').prepend($('#jsxc_dialog .jsxc_chatarea > ul > li').detach());
$(document).off('cleanup.dialog.jsxc');
$(document).off('error.jingle');
jsxc.gui.dialog.close();
},
/**
* Remote station is ringing.
*
* @private
* @memberOf jsxc.webrtc
*/
onCallRinging: function() {
this.setStatus('ringing...', 0);
},
/**
* Called if we receive a remote stream.
*
* @private
* @memberOf jsxc.webrtc
* @param event
* @param data
* @param sid Session id
*/
onRemoteStreamAdded: function(event, data, sid) {
this.setStatus('Remote stream for session ' + sid + ' added.');
var stream = data.stream;
this.remoteStream = stream;
var sess = this.conn.jingle.sessions[sid];
var isVideoDevice = stream.getVideoTracks().length > 0;
var isAudioDevice = stream.getAudioTracks().length > 0;
sess.remoteDevices = {
video: isVideoDevice,
audio: isAudioDevice
};
this.setStatus(isVideoDevice ? 'Use remote video device.' : 'No remote video device');
this.setStatus(isAudioDevice ? 'Use remote audio device.' : 'No remote audio device');
if ($('.jsxc_remotevideo').length) {
RTC.attachMediaStream($('.jsxc_remotevideo'), stream);
}
},
/**
* Called if the remote stream was removed.
*
* @private
* @meberOf jsxc.webrtc
* @param event
* @param data
* @param sid Session id
*/
onRemoteStreamRemoved: function(event, data, sid) {
this.setStatus('Remote stream for session ' + sid + ' removed.');
},
/**
* Extracts local and remote ip and display it to the user.
*
* @private
* @memberOf jsxc.webrtc
* @param event
* @param sid session id
* @param sess
*/
onIceConnectionStateChanged: function(event, sid, sess) {
var sigState = sess.peerconnection.signalingState;
var iceCon = sess.peerconnection.iceConnectionState;
jsxc.debug('iceGat state for ' + sid, sess.peerconnection.iceGatheringState);
jsxc.debug('iceCon state for ' + sid, iceCon);
jsxc.debug('sig state for ' + sid, sigState);
if (sigState === 'stable' && iceCon === 'connected') {
var localSDP = sess.peerconnection.localDescription.sdp;
var remoteSDP = sess.peerconnection.remoteDescription.sdp;
sess.local_fp = SDPUtil.parse_fingerprint(SDPUtil.find_line(localSDP, 'a=fingerprint:')).fingerprint;
sess.remote_fp = SDPUtil.parse_fingerprint(SDPUtil.find_line(remoteSDP, 'a=fingerprint:')).fingerprint;
var ip_regex = "(\\d{1,3}\\.\\d{1,3}.\\d{1,3}\\.\\d{1,3}) \\d+ typ host";
sess.remote_ip = remoteSDP.match(new RegExp(ip_regex))[1];
sess.local_ip = localSDP.match(new RegExp(ip_regex))[1];
var regex = new RegExp(ip_regex, 'g');
var match;
while ((match = regex.exec(remoteSDP)) !== null) {
if (match[1] !== sess.remote_ip) {
alert('!!! WARNING !!!\n\nPossible Man-in-the-middle attack detected!\n\nYou should close the connection.');
return;
}
}
var text = '<p>';
text += '<b>' + jsxc.translate('%%Local IP%%: ') + '</b>' + sess.local_ip + '<br />';
text += '<b>' + jsxc.translate('%%Remote IP%%: ') + '</b>' + sess.remote_ip + '<br />';
text += '<b>' + jsxc.translate('%%Local Fingerprint%%: ') + '</b>' + sess.local_fp + '<br />';
text += '<b>' + jsxc.translate('%%Remote Fingerprint%%: ') + '</b>' + sess.remote_fp;
text += '</p>';
$('#jsxc_dialog .jsxc_infobar').html(text);
}
},
/**
* No STUN candidates found
*
* @private
* @memberOf jsxc.webrtc
*/
noStunCandidates: function() {
},
/**
* Start a call to the specified jid.
*
* @memberOf jsxc.webrtc
* @param jid full jid
*/
startCall: function(jid) {
var self = this;
if (Strophe.getResourceFromJid(jid) === null) {
jsxc.debug('We need a full jid');
return;
}
self.last_caller = jid;
jsxc.switchEvents({
'finish.mediaready.jsxc': function() {
self.setStatus('Initiate call');
$(document).one('error.jingle', function(e, sid, error) {
if (error.source !== 'offer') {
return;
}
$(document).off('cleanup.dialog.jsxc');
setTimeout(function() {
jsxc.gui.showAlert("Sorry, we couldn't establish a connection. Maybe your buddy is offline.");
}, 500);
});
self.conn.jingle.initiate(jid, self.conn.jid.toLowerCase());
},
'mediafailure.jingle': function() {
jsxc.gui.dialog.close();
}
});
this.reqUserMedia();
},
/**
* Hang up the current call.
*
* @memberOf jsxc.webrtc
*/
hangUp: function() {
$(document).off('cleanup.dialog.jsxc');
jsxc.webrtc.conn.jingle.terminate(null);
$(document).trigger('callterminated.jingle');
},
/**
* Request video and audio from local user.
*
* @memberOf jsxc.webrtc
*/
reqUserMedia: function() {
if (this.localStream) {
$(document).trigger('mediaready.jingle', [ this.localStream ]);
return;
}
jsxc.gui.dialog.open(jsxc.gui.template.get('allowMediaAccess'), {
noClose: true
});
this.setStatus('please allow access to microphone and camera');
getUserMediaWithConstraints([ 'video', 'audio' ]);
},
/**
* Make a snapshot from a video stream and display it.
*
* @memberOf
* @param video Video stream
*/
snapshot: function(video) {
if (!video) {
jsxc.debug('Missing video element');
}
$('.jsxc_snapshotbar p').remove();
var canvas = $('<canvas/>').css('display', 'none').appendTo('body').attr({
width: video.width(),
height: video.height()
}).get(0);
var ctx = canvas.getContext('2d');
ctx.drawImage(video[0], 0, 0);
var img = $('<img/>');
var url = canvas.toDataURL('image/jpeg');
img[0].src = url;
var link = $('<a/>').attr({
target: '_blank',
href: url
});
link.append(img);
$('.jsxc_snapshotbar').append(link);
canvas.remove();
}
};
/**
* Display window for video call.
*
* @memberOf jsxc.gui
*/
jsxc.gui.showVideoWindow = function(jid) {
var self = jsxc.webrtc;
$(document).one('complete.dialog.jsxc', function() {
// mute own video element to avoid echoes
$('#jsxc_dialog .jsxc_localvideo')[0].muted = true;
$('#jsxc_dialog .jsxc_localvideo')[0].volume = 0;
var rv = $('#jsxc_dialog .jsxc_remotevideo');
var lv = $('#jsxc_dialog .jsxc_localvideo');
lv.draggable({
containment: "parent"
});
RTC.attachMediaStream(lv, self.localStream);
var w_dialog = $('#jsxc_dialog').width();
var w_remote = rv.width();
// fit in video
if (w_remote > w_dialog) {
var scale = w_dialog / w_remote;
var new_h = rv.height() * scale;
var new_w = w_dialog;
var vc = $('#jsxc_dialog .jsxc_videoContainer');
rv.height(new_h);
rv.width(new_w);
vc.height(new_h);
vc.width(new_w);
lv.height(lv.height() * scale);
lv.width(lv.width() * scale);
}
if (self.remoteStream) {
RTC.attachMediaStream(rv, self.remoteStream);
}
var toggleMulti = function(elem, open) {
$('#jsxc_dialog .jsxc_multi > div').not(elem).slideUp();
var opt = {
complete: jsxc.gui.dialog.resize
};
if (open) {
elem.slideDown(opt);
} else {
elem.slideToggle(opt);
}
};
var win = jsxc.gui.window.open(jsxc.jidToCid(jid));
$('#jsxc_dialog .jsxc_chatarea ul').append(win.detach());
$('#jsxc_dialog .jsxc_hangUp').click(function() {
jsxc.webrtc.hangUp();
});
$('#jsxc_dialog .jsxc_snapshot').click(function() {
jsxc.webrtc.snapshot(rv);
toggleMulti($('#jsxc_dialog .jsxc_snapshotbar'), true);
});
$('#jsxc_dialog .jsxc_snapshots').click(function() {
toggleMulti($('#jsxc_dialog .jsxc_snapshotbar'));
});
$('#jsxc_dialog .jsxc_showchat').click(function() {
toggleMulti($('#jsxc_dialog .jsxc_chatarea'));
});
$('#jsxc_dialog .jsxc_info').click(function() {
toggleMulti($('#jsxc_dialog .jsxc_infobar'));
});
$('#jsxc_dialog .jsxc_fullscreen').click(function() {
if ($.support.fullscreen) {
// Reset position of localvideo
$(document).one('disabled.fullscreen', function() {
lv.removeAttr('style');
});
$('#jsxc_dialog .jsxc_videoContainer').fullscreen();
}
});
$('#jsxc_dialog .jsxc_volume').change(function() {
rv[0].volume = $(this).val();
});
$('#jsxc_dialog .jsxc_volume').dblclick(function() {
$(this).val(0.5);
});
});
jsxc.gui.dialog.open(jsxc.gui.template.get('videoWindow'), {
noClose: true
});
};
$.extend(jsxc.CONST, {
KEYCODE_ENTER: 13,
KEYCODE_ESC: 27
});
$(document).ready(function() {
RTC = setupRTC();
if (RTC !== null) {
RTCPeerconnection = RTC.peerconnection;
$(document).on('init.window.jsxc', jsxc.webrtc.initWindow);
$(document).on('attached.jsxc', jsxc.webrtc.init);
}
});
$.extend(jsxc.l10n.en, {
Please_allow_access_to_microphone_and_camera: 'Please allow access to microphone and camera.',
Incoming_call: 'Incoming call',
from: 'from',
Do_you_want_to_accept_the_call_from: 'Do you want to accept the call from',
Reject: 'Reject',
Accept: 'Accept',
hang_up: 'hang up',
snapshot: 'snapshot',
mute_my_audio: 'mute my audio',
pause_my_video: 'pause my video',
fullscreen: 'fullscreen',
Info: 'Info',
Local_IP: 'Local IP',
Remote_IP: 'Remote IP',
Local_Fingerprint: 'Local fingerprint',
Remote_Fingerprint: 'Remote fingerprint',
Video_call_not_possible: 'Video call not possible',
Start_video_call: 'Start video call'
});
$.extend(jsxc.l10n.de, {
Please_allow_access_to_microphone_and_camera: 'Bitte erlaube den Zugriff auf Kamera und Mikrofon.',
Incoming_call: 'Eingehender Anruf',
from: 'von',
Do_you_want_to_accept_the_call_from: 'Möchtest Du den Anruf annehmen von',
Reject: 'Ablehnen',
Accept: 'Annehmen',
hang_up: 'Auflegen',
snapshot: 'Schnappschuss',
mute_my_audio: 'Mein Ton aus',
pause_my_video: 'Mein Video pausieren',
fullscreen: 'Vollbild',
Info: 'Info',
Local_IP: 'Lokale IP',
Remote_IP: 'Remote IP',
Local_Fingerprint: 'Lokaler Fingerprint',
Remote_Fingerprint: 'Remote Fingerprint',
Video_call_not_possible: 'Videoanruf nicht verfügbar',
Start_video_call: 'Starte Videoanruf'
});
}(jQuery));
+20
Ver Arquivo
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
-170
Ver Arquivo
@@ -1,170 +0,0 @@
.jsxc_videoContainer {
width: 640px;
height: 480px;
position: relative;
}
.jsxc_remotevideo {
width: 100%;
height: 100%;
position: absolute;
top: 0px;
left: 0px;
z-index: 9000;
background-color: grey;
}
.jsxc_localvideo {
width: 160px;
height: 120px;
position: absolute;
right: 10px;
bottom: 10px;
z-index: 9990;
background-color: black;
cursor: pointer;
}
.jsxc_webrtc .jsxc_status {
z-index: 9999;
border-radius: 20px;
display: none;
position: absolute;
top: 30px;
left: 50%;
background-color: lightgrey;
background-color: rgba(0, 0, 0, 0.5);
color: white;
padding: 15px;
font-weight: bold;
text-align: center;
}
div:-moz-full-screen {
width: 100%;
height: 100%;
background-color: black;
}
div:-ms-full-screen {
width: 100%;
height: 100%;
background-color: black;
}
div:-webkit-full-screen {
width: 100%;
height: 100%;
background-color: black;
}
div:fullscreen {
width: 100%;
height: 100%;
background-color: black;
}
div:-moz-full-screen.jsxc_localvideo {
border: 1px solid white;
}
div:-webkit-full-screen.jsxc_localvideo {
border: 1px solid white;
}
div:-ms-full-screen.jsxc_localvideo {
border: 1px solid white;
}
div:fullscreen.jsxc_localvideo {
border: 1px solid white;
}
.jsxc_fullscreen.jsxc_localvideo {
border: 1px solid white;
}
.jsxc_multi>div {
display: none;
}
.jsxc_snapshotbar {
width: 100%;
display: none;
}
.jsxc_snapshotbar img {
height: 50px;
}
.jsxc_buttongroup {
display: inline;
}
.jsxc_buttongroup button:first-child {
border-top-right-radius: 0px;
border-bottom-right-radius: 0px;
margin-right: 0px;
}
.jsxc_buttongroup button:last-child {
border-top-left-radius: 0px;
border-bottom-left-radius: 0px;
margin-left: 0px;
}
.jsxc_chatarea {
position: relative;
height: 255px;
display: none;
background-color: #A4A4A4;
}
.jsxc_chatarea ul {
position: absolute;
left: 50%;
top: 0px;
width: 200px;
height: 255px;
list-style: none;
padding: 0px;
margin: 0px 0px 0px -100px;
}
.jsxc_chatarea .jsxc_settings {
display: none;
}
.jsxc_chatarea .jsxc_close {
display: none;
}
.jsxc_chatarea .jsxc_bar {
display: none;
}
.jsxc_chatarea .jsxc_window {
bottom: 0px;
box-shadow: none;
}
.jsxc_videoSuitable .jsxc_name {
font-style: italic;
}
div.jsxc_video {
padding: 3px;
width: 17px;
height: 17px;
background-image: url('img/camera_icon_grey.svg');
background-repeat: no-repeat;
background-position: center center;
background-size: 15px 15px;
cursor: pointer;
float: left;
}
div.jsxc_video.jsxc_disabled {
opacity: 0.5;
cursor: default;
}
+851
Ver Arquivo
@@ -0,0 +1,851 @@
/**
* @license MIT
* @fileOverview Favico animations
* @author Miroslav Magda, http://blog.ejci.net
* @version 0.3.9
*/
/**
* Create new favico instance
* @param {Object} Options
* @return {Object} Favico object
* @example
* var favico = new Favico({
* bgColor : '#d00',
* textColor : '#fff',
* fontFamily : 'sans-serif',
* fontStyle : 'bold',
* position : 'down',
* type : 'circle',
* animation : 'slide',
* dataUrl: function(url){},
* win: top
* });
*/
(function() {
var Favico = (function(opt) {
'use strict';
opt = (opt) ? opt : {};
var _def = {
bgColor : '#d00',
textColor : '#fff',
fontFamily : 'sans-serif', //Arial,Verdana,Times New Roman,serif,sans-serif,...
fontStyle : 'bold', //normal,italic,oblique,bold,bolder,lighter,100,200,300,400,500,600,700,800,900
type : 'circle',
position : 'down', // down, up, left, leftup (upleft)
animation : 'slide',
elementId : false,
dataUrl : false,
win: window
};
var _opt, _orig, _h, _w, _canvas, _context, _img, _ready, _lastBadge, _running, _readyCb, _stop, _browser, _animTimeout, _drawTimeout, _doc;
_browser = {};
_browser.ff = typeof InstallTrigger != 'undefined';
_browser.chrome = !!window.chrome;
_browser.opera = !!window.opera || navigator.userAgent.indexOf('Opera') >= 0;
_browser.ie = /*@cc_on!@*/false;
_browser.safari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;
_browser.supported = (_browser.chrome || _browser.ff || _browser.opera);
var _queue = [];
_readyCb = function() {
};
_ready = _stop = false;
/**
* Initialize favico
*/
var init = function() {
//merge initial options
_opt = merge(_def, opt);
_opt.bgColor = hexToRgb(_opt.bgColor);
_opt.textColor = hexToRgb(_opt.textColor);
_opt.position = _opt.position.toLowerCase();
_opt.animation = (animation.types['' + _opt.animation]) ? _opt.animation : _def.animation;
_doc = _opt.win.document;
var isUp = _opt.position.indexOf('up') > -1;
var isLeft = _opt.position.indexOf('left') > -1;
//transform animation
if (isUp || isLeft) {
for (var i = 0; i < animation.types['' + _opt.animation].length; i++) {
var step = animation.types['' + _opt.animation][i];
if (isUp) {
if (step.y < 0.6) {
step.y = step.y - 0.4;
} else {
step.y = step.y - 2 * step.y + (1 - step.w);
}
}
if (isLeft) {
if (step.x < 0.6) {
step.x = step.x - 0.4;
} else {
step.x = step.x - 2 * step.x + (1 - step.h);
}
}
animation.types['' + _opt.animation][i] = step;
}
}
_opt.type = (type['' + _opt.type]) ? _opt.type : _def.type;
_orig = link.getIcon();
//create temp canvas
_canvas = document.createElement('canvas');
//create temp image
_img = document.createElement('img');
if (_orig.hasAttribute('href')) {
_img.setAttribute('crossOrigin', 'anonymous');
_img.setAttribute('src', _orig.getAttribute('href'));
//get width/height
_img.onload = function() {
_h = (_img.height > 0) ? _img.height : 32;
_w = (_img.width > 0) ? _img.width : 32;
_canvas.height = _h;
_canvas.width = _w;
_context = _canvas.getContext('2d');
icon.ready();
};
} else {
_img.setAttribute('src', '');
_h = 32;
_w = 32;
_img.height = _h;
_img.width = _w;
_canvas.height = _h;
_canvas.width = _w;
_context = _canvas.getContext('2d');
icon.ready();
}
};
/**
* Icon namespace
*/
var icon = {};
/**
* Icon is ready (reset icon) and start animation (if ther is any)
*/
icon.ready = function() {
_ready = true;
icon.reset();
_readyCb();
};
/**
* Reset icon to default state
*/
icon.reset = function() {
//reset
if (!_ready) {
return;
}
_queue = [];
_lastBadge = false;
_running = false;
_context.clearRect(0, 0, _w, _h);
_context.drawImage(_img, 0, 0, _w, _h);
//_stop=true;
link.setIcon(_canvas);
//webcam('stop');
//video('stop');
window.clearTimeout(_animTimeout);
window.clearTimeout(_drawTimeout);
};
/**
* Start animation
*/
icon.start = function() {
if (!_ready || _running) {
return;
}
var finished = function() {
_lastBadge = _queue[0];
_running = false;
if (_queue.length > 0) {
_queue.shift();
icon.start();
} else {
}
};
if (_queue.length > 0) {
_running = true;
var run = function() {
// apply options for this animation
['type', 'animation', 'bgColor', 'textColor', 'fontFamily', 'fontStyle'].forEach(function(a) {
if ( a in _queue[0].options) {
_opt[a] = _queue[0].options[a];
}
});
animation.run(_queue[0].options, function() {
finished();
}, false);
};
if (_lastBadge) {
animation.run(_lastBadge.options, function() {
run();
}, true);
} else {
run();
}
}
};
/**
* Badge types
*/
var type = {};
var options = function(opt) {
opt.n = (( typeof opt.n) === 'number') ? Math.abs(opt.n | 0) : opt.n;
opt.x = _w * opt.x;
opt.y = _h * opt.y;
opt.w = _w * opt.w;
opt.h = _h * opt.h;
opt.len = ("" + opt.n).length;
return opt;
};
/**
* Generate circle
* @param {Object} opt Badge options
*/
type.circle = function(opt) {
opt = options(opt);
var more = false;
if (opt.len === 2) {
opt.x = opt.x - opt.w * 0.4;
opt.w = opt.w * 1.4;
more = true;
} else if (opt.len >= 3) {
opt.x = opt.x - opt.w * 0.65;
opt.w = opt.w * 1.65;
more = true;
}
_context.clearRect(0, 0, _w, _h);
_context.drawImage(_img, 0, 0, _w, _h);
_context.beginPath();
_context.font = _opt.fontStyle + " " + Math.floor(opt.h * (opt.n > 99 ? 0.85 : 1)) + "px " + _opt.fontFamily;
_context.textAlign = 'center';
if (more) {
_context.moveTo(opt.x + opt.w / 2, opt.y);
_context.lineTo(opt.x + opt.w - opt.h / 2, opt.y);
_context.quadraticCurveTo(opt.x + opt.w, opt.y, opt.x + opt.w, opt.y + opt.h / 2);
_context.lineTo(opt.x + opt.w, opt.y + opt.h - opt.h / 2);
_context.quadraticCurveTo(opt.x + opt.w, opt.y + opt.h, opt.x + opt.w - opt.h / 2, opt.y + opt.h);
_context.lineTo(opt.x + opt.h / 2, opt.y + opt.h);
_context.quadraticCurveTo(opt.x, opt.y + opt.h, opt.x, opt.y + opt.h - opt.h / 2);
_context.lineTo(opt.x, opt.y + opt.h / 2);
_context.quadraticCurveTo(opt.x, opt.y, opt.x + opt.h / 2, opt.y);
} else {
_context.arc(opt.x + opt.w / 2, opt.y + opt.h / 2, opt.h / 2, 0, 2 * Math.PI);
}
_context.fillStyle = 'rgba(' + _opt.bgColor.r + ',' + _opt.bgColor.g + ',' + _opt.bgColor.b + ',' + opt.o + ')';
_context.fill();
_context.closePath();
_context.beginPath();
_context.stroke();
_context.fillStyle = 'rgba(' + _opt.textColor.r + ',' + _opt.textColor.g + ',' + _opt.textColor.b + ',' + opt.o + ')';
//_context.fillText((more) ? '9+' : opt.n, Math.floor(opt.x + opt.w / 2), Math.floor(opt.y + opt.h - opt.h * 0.15));
if (( typeof opt.n) === 'number' && opt.n > 999) {
_context.fillText(((opt.n > 9999) ? 9 : Math.floor(opt.n / 1000) ) + 'k+', Math.floor(opt.x + opt.w / 2), Math.floor(opt.y + opt.h - opt.h * 0.2));
} else {
_context.fillText(opt.n, Math.floor(opt.x + opt.w / 2), Math.floor(opt.y + opt.h - opt.h * 0.15));
}
_context.closePath();
};
/**
* Generate rectangle
* @param {Object} opt Badge options
*/
type.rectangle = function(opt) {
opt = options(opt);
var more = false;
if (opt.len === 2) {
opt.x = opt.x - opt.w * 0.4;
opt.w = opt.w * 1.4;
more = true;
} else if (opt.len >= 3) {
opt.x = opt.x - opt.w * 0.65;
opt.w = opt.w * 1.65;
more = true;
}
_context.clearRect(0, 0, _w, _h);
_context.drawImage(_img, 0, 0, _w, _h);
_context.beginPath();
_context.font = _opt.fontStyle + " " + Math.floor(opt.h * (opt.n > 99 ? 0.9 : 1)) + "px " + _opt.fontFamily;
_context.textAlign = 'center';
_context.fillStyle = 'rgba(' + _opt.bgColor.r + ',' + _opt.bgColor.g + ',' + _opt.bgColor.b + ',' + opt.o + ')';
_context.fillRect(opt.x, opt.y, opt.w, opt.h);
_context.fillStyle = 'rgba(' + _opt.textColor.r + ',' + _opt.textColor.g + ',' + _opt.textColor.b + ',' + opt.o + ')';
//_context.fillText((more) ? '9+' : opt.n, Math.floor(opt.x + opt.w / 2), Math.floor(opt.y + opt.h - opt.h * 0.15));
if (( typeof opt.n) === 'number' && opt.n > 999) {
_context.fillText(((opt.n > 9999) ? 9 : Math.floor(opt.n / 1000) ) + 'k+', Math.floor(opt.x + opt.w / 2), Math.floor(opt.y + opt.h - opt.h * 0.2));
} else {
_context.fillText(opt.n, Math.floor(opt.x + opt.w / 2), Math.floor(opt.y + opt.h - opt.h * 0.15));
}
_context.closePath();
};
/**
* Set badge
*/
var badge = function(number, opts) {
opts = (( typeof opts) === 'string' ? {
animation : opts
} : opts) || {};
_readyCb = function() {
try {
if ( typeof (number) === 'number' ? (number > 0) : (number !== '')) {
var q = {
type : 'badge',
options : {
n : number
}
};
if ('animation' in opts && animation.types['' + opts.animation]) {
q.options.animation = '' + opts.animation;
}
if ('type' in opts && type['' + opts.type]) {
q.options.type = '' + opts.type;
}
['bgColor', 'textColor'].forEach(function(o) {
if ( o in opts) {
q.options[o] = hexToRgb(opts[o]);
}
});
['fontStyle', 'fontFamily'].forEach(function(o) {
if ( o in opts) {
q.options[o] = opts[o];
}
});
_queue.push(q);
if (_queue.length > 100) {
throw new Error('Too many badges requests in queue.');
}
icon.start();
} else {
icon.reset();
}
} catch(e) {
throw new Error('Error setting badge. Message: ' + e.message);
}
};
if (_ready) {
_readyCb();
}
};
/**
* Set image as icon
*/
var image = function(imageElement) {
_readyCb = function() {
try {
var w = imageElement.width;
var h = imageElement.height;
var newImg = document.createElement('img');
var ratio = (w / _w < h / _h) ? (w / _w) : (h / _h);
newImg.setAttribute('crossOrigin', 'anonymous');
newImg.setAttribute('src', imageElement.getAttribute('src'));
newImg.height = (h / ratio);
newImg.width = (w / ratio);
_context.clearRect(0, 0, _w, _h);
_context.drawImage(newImg, 0, 0, _w, _h);
link.setIcon(_canvas);
} catch(e) {
throw new Error('Error setting image. Message: ' + e.message);
}
};
if (_ready) {
_readyCb();
}
};
/**
* Set video as icon
*/
var video = function(videoElement) {
_readyCb = function() {
try {
if (videoElement === 'stop') {
_stop = true;
icon.reset();
_stop = false;
return;
}
//var w = videoElement.width;
//var h = videoElement.height;
//var ratio = (w / _w < h / _h) ? (w / _w) : (h / _h);
videoElement.addEventListener('play', function() {
drawVideo(this);
}, false);
} catch(e) {
throw new Error('Error setting video. Message: ' + e.message);
}
};
if (_ready) {
_readyCb();
}
};
/**
* Set video as icon
*/
var webcam = function(action) {
//UR
if (!window.URL || !window.URL.createObjectURL) {
window.URL = window.URL || {};
window.URL.createObjectURL = function(obj) {
return obj;
};
}
if (_browser.supported) {
var newVideo = false;
navigator.getUserMedia = navigator.getUserMedia || navigator.oGetUserMedia || navigator.msGetUserMedia || navigator.mozGetUserMedia || navigator.webkitGetUserMedia;
_readyCb = function() {
try {
if (action === 'stop') {
_stop = true;
icon.reset();
_stop = false;
return;
}
newVideo = document.createElement('video');
newVideo.width = _w;
newVideo.height = _h;
navigator.getUserMedia({
video : true,
audio : false
}, function(stream) {
newVideo.src = URL.createObjectURL(stream);
newVideo.play();
drawVideo(newVideo);
}, function() {
});
} catch(e) {
throw new Error('Error setting webcam. Message: ' + e.message);
}
};
if (_ready) {
_readyCb();
}
}
};
/**
* Draw video to context and repeat :)
*/
function drawVideo(video) {
if (video.paused || video.ended || _stop) {
return false;
}
//nasty hack for FF webcam (Thanks to Julian Ćwirko, kontakt@redsunmedia.pl)
try {
_context.clearRect(0, 0, _w, _h);
_context.drawImage(video, 0, 0, _w, _h);
} catch(e) {
}
_drawTimeout = setTimeout(drawVideo, animation.duration, video);
link.setIcon(_canvas);
}
var link = {};
/**
* Get icon from HEAD tag or create a new <link> element
*/
link.getIcon = function() {
var elm = false;
//get link element
var getLink = function() {
var link = _doc.getElementsByTagName('head')[0].getElementsByTagName('link');
for (var l = link.length, i = (l - 1); i >= 0; i--) {
if ((/(^|\s)icon(\s|$)/i).test(link[i].getAttribute('rel'))) {
return link[i];
}
}
return false;
};
if (_opt.element) {
elm = _opt.element;
} else if (_opt.elementId) {
//if img element identified by elementId
elm = _doc.getElementById(_opt.elementId);
elm.setAttribute('href', elm.getAttribute('src'));
} else {
//if link element
elm = getLink();
if (elm === false) {
elm = _doc.createElement('link');
elm.setAttribute('rel', 'icon');
_doc.getElementsByTagName('head')[0].appendChild(elm);
}
}
elm.setAttribute('type', 'image/png');
return elm;
};
link.setIcon = function(canvas) {
var url = canvas.toDataURL('image/png');
if (_opt.dataUrl) {
//if using custom exporter
_opt.dataUrl(url);
}
if (_opt.element) {
_opt.element.setAttribute('href', url);
_opt.element.setAttribute('src', url);
} else if (_opt.elementId) {
//if is attached to element (image)
var elm = _doc.getElementById(_opt.elementId);
elm.setAttribute('href', url);
elm.setAttribute('src', url);
} else {
//if is attached to fav icon
if (_browser.ff || _browser.opera) {
//for FF we need to "recreate" element, atach to dom and remove old <link>
//var originalType = _orig.getAttribute('rel');
var old = _orig;
_orig = _doc.createElement('link');
//_orig.setAttribute('rel', originalType);
if (_browser.opera) {
_orig.setAttribute('rel', 'icon');
}
_orig.setAttribute('rel', 'icon');
_orig.setAttribute('type', 'image/png');
_doc.getElementsByTagName('head')[0].appendChild(_orig);
_orig.setAttribute('href', url);
if (old.parentNode) {
old.parentNode.removeChild(old);
}
} else {
_orig.setAttribute('href', url);
}
}
};
//http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb#answer-5624139
//HEX to RGB convertor
function hexToRgb(hex) {
var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
hex = hex.replace(shorthandRegex, function(m, r, g, b) {
return r + r + g + g + b + b;
});
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r : parseInt(result[1], 16),
g : parseInt(result[2], 16),
b : parseInt(result[3], 16)
} : false;
}
/**
* Merge options
*/
function merge(def, opt) {
var mergedOpt = {};
var attrname;
for (attrname in def) {
mergedOpt[attrname] = def[attrname];
}
for (attrname in opt) {
mergedOpt[attrname] = opt[attrname];
}
return mergedOpt;
}
/**
* Cross-browser page visibility shim
* http://stackoverflow.com/questions/12536562/detect-whether-a-window-is-visible
*/
function isPageHidden() {
return _doc.hidden || _doc.msHidden || _doc.webkitHidden || _doc.mozHidden;
}
/**
* @namespace animation
*/
var animation = {};
/**
* Animation "frame" duration
*/
animation.duration = 40;
/**
* Animation types (none,fade,pop,slide)
*/
animation.types = {};
animation.types.fade = [{
x : 0.4,
y : 0.4,
w : 0.6,
h : 0.6,
o : 0.0
}, {
x : 0.4,
y : 0.4,
w : 0.6,
h : 0.6,
o : 0.1
}, {
x : 0.4,
y : 0.4,
w : 0.6,
h : 0.6,
o : 0.2
}, {
x : 0.4,
y : 0.4,
w : 0.6,
h : 0.6,
o : 0.3
}, {
x : 0.4,
y : 0.4,
w : 0.6,
h : 0.6,
o : 0.4
}, {
x : 0.4,
y : 0.4,
w : 0.6,
h : 0.6,
o : 0.5
}, {
x : 0.4,
y : 0.4,
w : 0.6,
h : 0.6,
o : 0.6
}, {
x : 0.4,
y : 0.4,
w : 0.6,
h : 0.6,
o : 0.7
}, {
x : 0.4,
y : 0.4,
w : 0.6,
h : 0.6,
o : 0.8
}, {
x : 0.4,
y : 0.4,
w : 0.6,
h : 0.6,
o : 0.9
}, {
x : 0.4,
y : 0.4,
w : 0.6,
h : 0.6,
o : 1.0
}];
animation.types.none = [{
x : 0.4,
y : 0.4,
w : 0.6,
h : 0.6,
o : 1
}];
animation.types.pop = [{
x : 1,
y : 1,
w : 0,
h : 0,
o : 1
}, {
x : 0.9,
y : 0.9,
w : 0.1,
h : 0.1,
o : 1
}, {
x : 0.8,
y : 0.8,
w : 0.2,
h : 0.2,
o : 1
}, {
x : 0.7,
y : 0.7,
w : 0.3,
h : 0.3,
o : 1
}, {
x : 0.6,
y : 0.6,
w : 0.4,
h : 0.4,
o : 1
}, {
x : 0.5,
y : 0.5,
w : 0.5,
h : 0.5,
o : 1
}, {
x : 0.4,
y : 0.4,
w : 0.6,
h : 0.6,
o : 1
}];
animation.types.popFade = [{
x : 0.75,
y : 0.75,
w : 0,
h : 0,
o : 0
}, {
x : 0.65,
y : 0.65,
w : 0.1,
h : 0.1,
o : 0.2
}, {
x : 0.6,
y : 0.6,
w : 0.2,
h : 0.2,
o : 0.4
}, {
x : 0.55,
y : 0.55,
w : 0.3,
h : 0.3,
o : 0.6
}, {
x : 0.50,
y : 0.50,
w : 0.4,
h : 0.4,
o : 0.8
}, {
x : 0.45,
y : 0.45,
w : 0.5,
h : 0.5,
o : 0.9
}, {
x : 0.4,
y : 0.4,
w : 0.6,
h : 0.6,
o : 1
}];
animation.types.slide = [{
x : 0.4,
y : 1,
w : 0.6,
h : 0.6,
o : 1
}, {
x : 0.4,
y : 0.9,
w : 0.6,
h : 0.6,
o : 1
}, {
x : 0.4,
y : 0.9,
w : 0.6,
h : 0.6,
o : 1
}, {
x : 0.4,
y : 0.8,
w : 0.6,
h : 0.6,
o : 1
}, {
x : 0.4,
y : 0.7,
w : 0.6,
h : 0.6,
o : 1
}, {
x : 0.4,
y : 0.6,
w : 0.6,
h : 0.6,
o : 1
}, {
x : 0.4,
y : 0.5,
w : 0.6,
h : 0.6,
o : 1
}, {
x : 0.4,
y : 0.4,
w : 0.6,
h : 0.6,
o : 1
}];
/**
* Run animation
* @param {Object} opt Animation options
* @param {Object} cb Callabak after all steps are done
* @param {Object} revert Reverse order? true|false
* @param {Object} step Optional step number (frame bumber)
*/
animation.run = function(opt, cb, revert, step) {
var animationType = animation.types[isPageHidden() ? 'none' : _opt.animation];
if (revert === true) {
step = ( typeof step !== 'undefined') ? step : animationType.length - 1;
} else {
step = ( typeof step !== 'undefined') ? step : 0;
}
cb = (cb) ? cb : function() {
};
if ((step < animationType.length) && (step >= 0)) {
type[_opt.type](merge(opt, animationType[step]));
_animTimeout = setTimeout(function() {
if (revert) {
step = step - 1;
} else {
step = step + 1;
}
animation.run(opt, cb, revert, step);
}, animation.duration);
link.setIcon(_canvas);
} else {
cb();
return;
}
};
//auto init
init();
return {
badge : badge,
video : video,
image : image,
webcam : webcam,
reset : icon.reset,
browser : {
supported : _browser.supported
}
};
});
// AMD / RequireJS
if ( typeof define !== 'undefined' && define.amd) {
define([], function() {
return Favico;
});
}
// CommonJS
else if ( typeof module !== 'undefined' && module.exports) {
module.exports = Favico;
}
// included directly via <script> tag
else {
this.Favico = Favico;
}
})();
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
+186 -73
Ver Arquivo
@@ -2,35 +2,81 @@
* Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
* and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
*
* Version: 1.0.0
*
* Version: 1.3.3 + pr#94
*
*/
(function($) {
jQuery.fn.extend({
$.fn.extend({
slimScroll: function(options) {
var defaults = {
wheelStep : 20,
// width in pixels of the visible scroll area
width : 'auto',
// height in pixels of the visible scroll area
height : '250px',
// width in pixels of the scrollbar and rail
size : '7px',
// scrollbar color, accepts any hex/color value
color: '#000',
// scrollbar position - left/right
position : 'right',
// distance in pixels between the side edge and the scrollbar
distance : '1px',
// default scroll position on load - top / bottom / $('selector')
start : 'top',
// sets scrollbar opacity
opacity : .4,
// enables always-on mode for the scrollbar
alwaysVisible : false,
disableFadeOut: false,
// check if we should hide the scrollbar when user is hovering over
disableFadeOut : false,
// sets visibility of the rail
railVisible : false,
// sets rail color
railColor : '#333',
railOpacity : '0.2',
// sets rail opacity
railOpacity : .2,
// whether we should use jQuery UI Draggable to enable bar dragging
railDraggable : true,
// defautlt CSS class of the slimscroll rail
railClass : 'slimScrollRail',
// defautlt CSS class of the slimscroll bar
barClass : 'slimScrollBar',
// defautlt CSS class of the slimscroll wrapper
wrapperClass : 'slimScrollDiv',
// check if mousewheel should scroll the window if we reach top/bottom
allowPageScroll : false,
scroll : 0,
touchScrollStep : 200
// scroll amount applied to each mouse wheel step
wheelStep : 20,
// scroll amount applied when user is using gestures
touchScrollStep : 200,
// sets border radius
borderRadius: '7px',
// sets border radius of the rail
railBorderRadius : '7px'
};
var o = $.extend(defaults, options);
@@ -38,7 +84,7 @@
// do it for every element that matches selector
this.each(function(){
var isOverPanel, isOverBar, isDragg, queueHide, touchDif,
var isOverPanel, isOverBar, isDragg, queueHide, touchDif,
barHeight, percentScroll, lastScroll,
divS = '<div></div>',
minBarHeight = 30,
@@ -48,20 +94,33 @@
var me = $(this);
// ensure we are not binding it again
if (me.parent().hasClass('slimScrollDiv'))
{
if (me.parent().hasClass(o.wrapperClass))
{
// start from last bar position
var offset = me.scrollTop();
// find bar and rail
bar = me.parent().find('.slimScrollBar');
rail = me.parent().find('.slimScrollRail');
bar = me.parent().find('.' + o.barClass);
rail = me.parent().find('.' + o.railClass);
getBarHeight();
// check if we should scroll existing instance
if (options)
if ($.isPlainObject(options))
{
// Pass height: auto to an existing slimscroll object to force a resize after contents have changed
if ( 'height' in options && options.height == 'auto' ) {
me.parent().css('height', 'auto');
me.css('height', 'auto');
var height = me.parent().parent().height();
me.parent().css('height', height);
me.css('height', height);
} else if ('height' in options) {
var h = options.height;
me.parent().css('height', h);
me.css('height', h);
}
if ('scrollTo' in options)
{
// jump to a static point
@@ -72,6 +131,14 @@
// jump by value pixels
offset += parseInt(o.scrollBy);
}
else if ('destroy' in options)
{
// remove slimscroll elements
bar.remove();
rail.remove();
me.unwrap();
return;
}
// scroll content by the given offset
scrollContent(offset, false, true);
@@ -79,9 +146,16 @@
return;
}
else if ($.isPlainObject(options))
{
if ('destroy' in options)
{
return;
}
}
// optionally set height to the parent's height
o.height = (o.height == 'auto') ? me.parent().innerHeight() : o.height;
o.height = (o.height == 'auto') ? me.parent().height() : o.height;
// wrap content
var wrapper = $(divS)
@@ -101,7 +175,7 @@
});
// create scrollbar rail
var rail = $(divS)
var rail = $(divS)
.addClass(o.railClass)
.css({
width: o.size,
@@ -109,7 +183,7 @@
position: 'absolute',
top: 0,
display: (o.alwaysVisible && o.railVisible) ? 'block' : 'none',
'border-radius': o.size,
'border-radius': o.railBorderRadius,
background: o.railColor,
opacity: o.railOpacity,
zIndex: 90
@@ -125,10 +199,10 @@
top: 0,
opacity: o.opacity,
display: o.alwaysVisible ? 'block' : 'none',
'border-radius' : o.size,
BorderRadius: o.size,
MozBorderRadius: o.size,
WebkitBorderRadius: o.size,
'border-radius' : o.borderRadius,
BorderRadius: o.borderRadius,
MozBorderRadius: o.borderRadius,
WebkitBorderRadius: o.borderRadius,
zIndex: 99
});
@@ -144,18 +218,31 @@
me.parent().append(bar);
me.parent().append(rail);
// make it draggable
bar.draggable({
axis: 'y',
containment: 'parent',
start: function() { isDragg = true; },
stop: function() { isDragg = false; hideBar(); },
drag: function(e)
{
// scroll content
scrollContent(0, $(this).position().top, false);
}
});
// make it draggable and no longer dependent on the jqueryUI
if (o.railDraggable){
bar.bind("mousedown", function(e) {
var $doc = $(document);
isDragg = true;
t = parseFloat(bar.css('top'));
pageY = e.pageY;
$doc.bind("mousemove.slimscroll", function(e){
currTop = t + e.pageY - pageY;
bar.css('top', currTop);
scrollContent(0, bar.position().top, false);// scroll content
});
$doc.bind("mouseup.slimscroll", function(e) {
isDragg = false;hideBar();
$doc.unbind('.slimscroll');
});
return false;
}).bind("selectstart.slimscroll", function(e){
e.stopPropagation();
e.preventDefault();
return false;
});
}
// on rail over
rail.hover(function(){
@@ -191,18 +278,44 @@
});
me.bind('touchmove', function(e){
// prevent scrolling the page
e.originalEvent.preventDefault();
// prevent scrolling the page if necessary
if(!releaseScroll)
{
e.originalEvent.preventDefault();
}
if (e.originalEvent.touches.length)
{
// see how far user swiped
var diff = (touchDif - e.originalEvent.touches[0].pageY) / o.touchScrollStep;
// scroll content
scrollContent(diff, true);
touchDif = e.originalEvent.touches[0].pageY;
}
});
var _onWheel = function(e)
// set up initial height
getBarHeight();
// check start position
if (o.start === 'bottom')
{
// scroll content to bottom
bar.css({ top: me.outerHeight() - bar.outerHeight() });
scrollContent(0, true);
}
else if (o.start !== 'top')
{
// assume jQuery selector
scrollContent($(o.start).position().top, null, true);
// make sure bar stays hidden
if (!o.alwaysVisible) { bar.hide(); }
}
// attach scroll events
attachWheel();
function _onWheel(e)
{
// use mouse wheel only when mouse is over
if (!isOverPanel) { return; }
@@ -213,8 +326,11 @@
if (e.wheelDelta) { delta = -e.wheelDelta/120; }
if (e.detail) { delta = e.detail / 3; }
// scroll content
scrollContent(delta, true);
var target = e.target || e.srcTarget || e.srcElement;
if ($(target).closest('.' + o.wrapperClass).is(me.parent())) {
// scroll content
scrollContent(delta, true);
}
// stop window scroll
if (e.preventDefault && !releaseScroll) { e.preventDefault(); }
@@ -223,16 +339,24 @@
function scrollContent(y, isWheel, isJump)
{
releaseScroll = false;
var delta = y;
var maxTop = me.outerHeight() - bar.outerHeight();
if (isWheel)
{
// move bar with mouse wheel
delta = parseInt(bar.css('top')) + y * parseInt(o.wheelStep) / 100 * bar.outerHeight();
// move bar, make sure it doesn't go out
// move bar, make sure it doesn't go out
delta = Math.min(Math.max(delta, 0), maxTop);
// if scrolling down, make sure a fractional change to the
// scroll position isn't rounded away when the scrollbar's CSS is set
// this flooring of delta would happened automatically when
// bar.css is set below, but we floor here for clarity
delta = (y > 0) ? Math.ceil(delta) : Math.floor(delta);
// scroll the scrollbar
bar.css({ top: delta + 'px' });
}
@@ -245,7 +369,6 @@
{
delta = y;
var offsetTop = delta / me[0].scrollHeight * me.outerHeight();
offsetTop = Math.min(Math.max(offsetTop, 0), maxTop);
bar.css({ top: offsetTop + 'px' });
}
@@ -253,6 +376,9 @@
// scroll content
me.scrollTop(delta);
// fire scrolling event
me.trigger('slimscrolling', ~~delta);
// ensure bar is visible
showBar();
@@ -260,31 +386,29 @@
hideBar();
}
var attachWheel = function()
function attachWheel()
{
if (window.addEventListener)
{
this.addEventListener('DOMMouseScroll', _onWheel, false );
this.addEventListener('mousewheel', _onWheel, false );
}
}
else
{
document.attachEvent("onmousewheel", _onWheel)
}
}
// attach scroll events
attachWheel();
function getBarHeight()
{
// calculate scrollbar height and make sure it is not too small
barHeight = Math.max((me.outerHeight() / me[0].scrollHeight) * me.outerHeight(), minBarHeight);
bar.css({ height: barHeight + 'px' });
}
// set up initial height
getBarHeight();
// hide scrollbar if content is not long enough
var display = barHeight == me.outerHeight() ? 'none' : 'block';
bar.css({ display: display });
}
function showBar()
{
@@ -293,18 +417,22 @@
clearTimeout(queueHide);
// when bar reached top or bottom
if (percentScroll == ~~ percentScroll)
if (percentScroll == ~~percentScroll)
{
//release wheel
//release wheel
releaseScroll = o.allowPageScroll;
// publish approporiate event
if (lastScroll != percentScroll)
{
var msg = (~~percentScroll == 0) ? 'top' : 'bottom';
var msg = (~~percentScroll == 0) ? 'top' : 'bottom';
me.trigger('slimscroll', msg);
}
}
else
{
releaseScroll = false;
}
lastScroll = percentScroll;
// show only when required
@@ -324,7 +452,7 @@
{
queueHide = setTimeout(function(){
if (!(o.disableFadeOut && isOverPanel) && !isOverBar && !isDragg)
{
{
bar.fadeOut('slow');
rail.fadeOut('slow');
}
@@ -332,30 +460,15 @@
}
}
// check start position
if (o.start == 'bottom')
{
// scroll content to bottom
bar.css({ top: me.outerHeight() - bar.outerHeight() });
scrollContent(0, true);
}
else if (typeof o.start == 'object')
{
// scroll content
scrollContent($(o.start).position().top, null, true);
// make sure bar stays hidden
if (!o.alwaysVisible) { bar.hide(); }
}
});
// maintain chainability
return this;
}
});
jQuery.fn.extend({
slimscroll: jQuery.fn.slimScroll
$.fn.extend({
slimscroll: $.fn.slimScroll
});
})(jQuery);
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
+139
Ver Arquivo
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
+5 -1
Ver Arquivo
@@ -5,7 +5,11 @@
} else if (typeof module !== 'undefined' && module.exports) {
module.exports = factory(require('crypto'))
} else {
root.BigInt = factory(root.crypto || root.msCrypto)
try {
root.BigInt = factory(root.crypto || root.msCrypto)
} catch(e) {
console.warn(e.message);
}
}
}(this, function (crypto) {
+96 -58
Ver Arquivo
@@ -1,7 +1,7 @@
/*!
otr.js v0.2.11 - 2014-03-24
(c) 2014 - Arlo Breault <arlolra@gmail.com>
otr.js v0.2.15 - 2015-05-04
(c) 2015 - Arlo Breault <arlolra@gmail.com>
Freely distributed under the MPL v2.0 license.
This file is concatenated for the browser.
@@ -29,7 +29,9 @@
} else {
root.OTR = {}
root.DSA = {}
factory.call(root)
if (typeof root.BigInt !== 'undefined') {
factory.call(root)
}
}
}(this, function () {
@@ -141,6 +143,17 @@
child.__super__ = parent.prototype
}
// assumes 32-bit
function intCompare(x, y) {
var z = ~(x ^ y)
z &= z >> 16
z &= z >> 8
z &= z >> 4
z &= z >> 2
z &= z >> 1
return z & 1
}
// constant-time string comparison
HLP.compare = function (str1, str2) {
if (str1.length !== str2.length)
@@ -148,7 +161,7 @@
var i = 0, result = 0
for (; i < str1.length; i++)
result |= str1[i].charCodeAt(0) ^ str2[i].charCodeAt(0)
return result === 0
return intCompare(result, 0)
}
HLP.randomExponent = function () {
@@ -1160,7 +1173,7 @@
HLP.debug.call(this.otr, 'success')
if (BigInt.equals(this.their_y, this.our_dh.publicKey))
return this.otr.error('equal keys - we have a problem.', true)
return this.otr.error('equal keys - we have a problem.')
this.otr.our_old_dh = this.our_dh
this.otr.their_priv_pk = this.their_priv_pk
@@ -1267,7 +1280,7 @@
// verify gy is legal 2 <= gy <= N-2
if (!HLP.checkGroup(this.their_y, N_MINUS_2))
return this.otr.error('Illegal g^y.', true)
return this.otr.error('Illegal g^y.')
this.createKeys(this.their_y)
@@ -1303,11 +1316,11 @@
var hash = CryptoJS.SHA256(CryptoJS.enc.Latin1.parse(gxmpi))
if (!HLP.compare(this.hashed, hash.toString(CryptoJS.enc.Latin1)))
return this.otr.error('Hashed g^x does not match.', true)
return this.otr.error('Hashed g^x does not match.')
// verify gx is legal 2 <= g^x <= N-2
if (!HLP.checkGroup(this.their_y, N_MINUS_2))
return this.otr.error('Illegal g^x.', true)
return this.otr.error('Illegal g^x.')
this.createKeys(this.their_y)
@@ -1321,7 +1334,7 @@
, this.m1
, HLP.packCtr(0)
)
if (vsm[0]) return this.otr.error(vsm[0], true)
if (vsm[0]) return this.otr.error(vsm[0])
// store their key
this.their_keyid = vsm[1]
@@ -1363,7 +1376,7 @@
, this.m1_prime
, HLP.packCtr(0)
)
if (vsm[0]) return this.otr.error(vsm[0], true)
if (vsm[0]) return this.otr.error(vsm[0])
// store their key
this.their_keyid = vsm[1]
@@ -1609,10 +1622,12 @@
this.smpstate = CONST.SMPSTATE_EXPECT0
// assume utf8 question
question = CryptoJS.enc.Latin1
.parse(question)
.toString(CryptoJS.enc.Utf8)
if (question) {
// assume utf8 question
question = CryptoJS.enc.Latin1
.parse(question)
.toString(CryptoJS.enc.Utf8)
}
// invoke question
this.trigger('question', [question])
@@ -1920,6 +1935,11 @@
var MAX_INT = Math.pow(2, 53) - 1 // doubles
var MAX_UINT = Math.pow(2, 31) - 1 // bitwise operators
// an internal callback
function OTRCB(cb) {
this.cb = cb
}
// OTR contructor
function OTR(options) {
if (!(this instanceof OTR)) return new OTR(options)
@@ -2090,17 +2110,22 @@
})
})
this.sm.on('send', function (ssid, send) {
if (self.ssid === ssid)
if (self.ssid === ssid) {
send = self.prepareMsg(send)
self.io(send)
}
})
}
OTR.prototype.io = function (msg, meta) {
// buffer
msg = ([].concat(msg)).map(function(m){
return { msg: m, meta: meta }
msg = ([].concat(msg)).map(function(m, i, arr) {
var obj = { msg: m }
if (!(meta instanceof OTRCB) ||
i === (arr.length - 1) // only cb after last fragment is sent
) obj.meta = meta
return obj
})
this.outgoing = this.outgoing.concat(msg)
@@ -2108,8 +2133,13 @@
;(function send(first) {
if (!first) {
if (!self.outgoing.length) return
var elem = self.outgoing.shift()
var elem = self.outgoing.shift(), cb = null
if (elem.meta instanceof OTRCB) {
cb = elem.meta.cb
elem.meta = null
}
self.trigger('io', [elem.msg, elem.meta])
if (cb) cb()
}
setTimeout(send, first ? 0 : self.send_interval)
}(true))
@@ -2142,7 +2172,7 @@
this.sendenc = HLP.mask(HLP.h1(sendbyte, secbytes), 0, 128) // f16 bytes
this.sendmac = CryptoJS.SHA1(CryptoJS.enc.Latin1.parse(this.sendenc))
this.sendmac = this.sendmac.toString(CryptoJS.enc.Latin1)
this.sendmacused = false
this.rcvenc = HLP.mask(HLP.h1(rcvbyte, secbytes), 0, 128)
this.rcvmac = CryptoJS.SHA1(CryptoJS.enc.Latin1.parse(this.rcvenc))
this.rcvmac = this.rcvmac.toString(CryptoJS.enc.Latin1)
@@ -2161,7 +2191,6 @@
// reveal old mac keys
var self = this
this.sessKeys[1].forEach(function (sk) {
if (sk && sk.sendmacused) self.oldMacKeys.push(sk.sendmac)
if (sk && sk.rcvmacused) self.oldMacKeys.push(sk.rcvmac)
})
@@ -2189,7 +2218,6 @@
// reveal old mac keys
var self = this
this.sessKeys.forEach(function (sk) {
if (sk[1] && sk[1].sendmacused) self.oldMacKeys.push(sk[1].sendmac)
if (sk[1] && sk[1].rcvmacused) self.oldMacKeys.push(sk[1].rcvmac)
})
@@ -2207,12 +2235,12 @@
OTR.prototype.prepareMsg = function (msg, esk) {
if (this.msgstate !== CONST.MSGSTATE_ENCRYPTED || this.their_keyid === 0)
return this.error('Not ready to encrypt.')
return this.notify('Not ready to encrypt.')
var sessKeys = this.sessKeys[1][0]
if (sessKeys.send_counter >= MAX_INT)
return this.error('Should have rekeyed by now.')
return this.notify('Should have rekeyed by now.')
sessKeys.send_counter += 1
@@ -2233,7 +2261,7 @@
send += ctr.substring(0, 8)
if (Math.ceil(msg.length / 8) >= MAX_UINT) // * 16 / 128
return this.error('Message is too long.')
return this.notify('Message is too long.')
var aes = HLP.encryptAes(
CryptoJS.enc.Latin1.parse(msg)
@@ -2245,8 +2273,6 @@
send += HLP.make1Mac(send, sessKeys.sendmac)
send += HLP.packData(this.oldMacKeys.splice(0).join(''))
sessKeys.sendmacused = true
send = HLP.wrapMsg(
send
, this.fragment_size
@@ -2254,7 +2280,7 @@
, this.our_instance_tag
, this.their_instance_tag
)
if (send[0]) return this.error(send[0])
if (send[0]) return this.notify(send[0])
// emit extra symmetric key
if (esk) this.trigger('file', ['send', sessKeys.extra_symkey, esk])
@@ -2275,7 +2301,7 @@
var ign = (msg[0] === '\x01')
if (this.msgstate !== CONST.MSGSTATE_ENCRYPTED || msg.length !== 8) {
if (!ign) this.error('Received an unreadable encrypted message.', true)
if (!ign) this.error('Received an unreadable encrypted message.')
return
}
@@ -2283,12 +2309,12 @@
var their_keyid = this.their_keyid - HLP.readLen(msg[1])
if (our_keyid < 0 || our_keyid > 1) {
if (!ign) this.error('Not of our latest keys.', true)
if (!ign) this.error('Not of our latest keys.')
return
}
if (their_keyid < 0 || their_keyid > 1) {
if (!ign) this.error('Not of your latest keys.', true)
if (!ign) this.error('Not of your latest keys.')
return
}
@@ -2383,16 +2409,17 @@
OTR.prototype.smpSecret = function (secret, question) {
if (this.msgstate !== CONST.MSGSTATE_ENCRYPTED)
return this.error('Must be encrypted for SMP.')
return this.notify('Must be encrypted for SMP.')
if (typeof secret !== 'string' || secret.length < 1)
return this.error('Secret is required.')
return this.notify('Secret is required.')
if (!this.sm) this._smInit()
// utf8 inputs
secret = CryptoJS.enc.Utf8.parse(secret).toString(CryptoJS.enc.Latin1)
question = CryptoJS.enc.Utf8.parse(question).toString(CryptoJS.enc.Latin1)
if (question)
question = CryptoJS.enc.Utf8.parse(question).toString(CryptoJS.enc.Latin1)
this.sm.rcvSecret(secret, question)
}
@@ -2443,7 +2470,7 @@
break
case CONST.MSGSTATE_FINISHED:
this.storedMgs.push({msg: msg, meta: meta})
this.error('Message cannot be sent at this time.')
this.notify('Message cannot be sent at this time.', 'warn')
return
case CONST.MSGSTATE_ENCRYPTED:
msg = this.prepareMsg(msg)
@@ -2455,7 +2482,7 @@
if (msg) this.io(msg, meta)
}
OTR.prototype.receiveMsg = function (msg) {
OTR.prototype.receiveMsg = function (msg, meta) {
// parse type
msg = Parse.parseMsg(this, msg)
@@ -2464,18 +2491,26 @@
switch (msg.cls) {
case 'error':
this.error(msg.msg)
this.notify(msg.msg)
return
case 'ake':
if ( msg.version === CONST.OTR_VERSION_3 &&
this.checkInstanceTags(msg.instance_tags)
) return // ignore
) {
this.notify(
'Received a message intended for a different session.', 'warn')
return // ignore
}
this.ake.handleAKE(msg)
return
case 'data':
if ( msg.version === CONST.OTR_VERSION_3 &&
this.checkInstanceTags(msg.instance_tags)
) return // ignore
) {
this.notify(
'Received a message intended for a different session.', 'warn')
return // ignore
}
msg.msg = this.handleDataMsg(msg)
msg.encrypted = true
break
@@ -2487,7 +2522,7 @@
// check for encrypted
if ( this.REQUIRE_ENCRYPTION ||
this.msgstate !== CONST.MSGSTATE_PLAINTEXT
) this.error('Received an unencrypted message.')
) this.notify('Received an unencrypted message.', 'warn')
// received a plaintext message
// stop sending the whitespace tag
@@ -2498,7 +2533,7 @@
this.doAKE(msg)
}
if (msg.msg) this.trigger('ui', [msg.msg, !!msg.encrypted])
if (msg.msg) this.trigger('ui', [msg.msg, !!msg.encrypted, meta])
}
OTR.prototype.checkInstanceTags = function (it) {
@@ -2522,20 +2557,19 @@
} else if (this.ALLOW_V2 && ~msg.ver.indexOf(CONST.OTR_VERSION_2)) {
this.ake.initiateAKE(CONST.OTR_VERSION_2)
} else {
// is this an error?
this.error('OTR conversation requested, ' +
'but no compatible protocol version found.')
this.notify('OTR conversation requested, ' +
'but no compatible protocol version found.', 'warn')
}
}
OTR.prototype.error = function (err, send) {
if (send) {
if (!this.debug) err = "An OTR error has occurred."
err = '?OTR Error:' + err
this.io(err)
return
}
this.trigger('error', [err])
OTR.prototype.error = function (err) {
if (!this.debug) err = 'An OTR error has occurred.'
this.io('?OTR Error:' + err)
this.notify(err)
}
OTR.prototype.notify = function (err, severity) {
this.trigger('error', [err, severity || 'error'])
}
OTR.prototype.sendStored = function () {
@@ -2548,18 +2582,18 @@
OTR.prototype.sendFile = function (filename) {
if (this.msgstate !== CONST.MSGSTATE_ENCRYPTED)
return this.error('Not ready to encrypt.')
return this.notify('Not ready to encrypt.')
if (this.ake.otr_version !== CONST.OTR_VERSION_3)
return this.error('Protocol v3 required.')
return this.notify('Protocol v3 required.')
if (!filename) return this.error('Please specify a filename.')
if (!filename) return this.notify('Please specify a filename.')
// utf8 filenames
var l1name = CryptoJS.enc.Utf8.parse(filename)
l1name = l1name.toString(CryptoJS.enc.Latin1)
if (l1name.length >= 65532) return this.error('filename is too long.')
if (l1name.length >= 65532) return this.notify('Filename is too long.')
var msg = '\x00' // null byte
msg += '\x00\x08' // type 8 tlv
@@ -2571,14 +2605,18 @@
this.io(msg)
}
OTR.prototype.endOtr = function () {
OTR.prototype.endOtr = function (cb) {
if (this.msgstate === CONST.MSGSTATE_ENCRYPTED) {
this.sendMsg('\x00\x00\x01\x00\x00')
if (typeof cb === 'function')
cb = new OTRCB(cb)
this.sendMsg('\x00\x00\x01\x00\x00', cb)
if (this.sm) {
if (this.smw) this.sm.worker.terminate() // destroy webworker
this.sm = null
}
}
} else if (typeof cb === 'function')
setTimeout(cb, 0)
this.msgstate = CONST.MSGSTATE_PLAINTEXT
this.receivedPlaintext = false
this.trigger('status', [CONST.STATUS_END_OTR])
+4 -4
Ver Arquivo
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
+15 -8
Ver Arquivo
@@ -3,11 +3,16 @@
root.OTR = {}
root.DSA = {}
root.crypto = {
randomBytes: function () {
throw new Error("Haven't seeded yet.")
var hasCrypto = false
if (root.crypto)
hasCrypto = true
else
root.crypto = {
randomBytes: function () {
throw new Error("Haven't seeded yet.")
}
}
}
// default imports
var imports = [
@@ -30,10 +35,12 @@
if (data.imports) imports = data.imports
importScripts.apply(root, imports);
// use salsa20 since there's no prng in webworkers
var state = new root.Salsa20(data.seed.slice(0, 32), data.seed.slice(32))
root.crypto.randomBytes = function (n) {
return state.getBytes(n)
if (!hasCrypto) {
// use salsa20 when there's no prng in webworkers
var state = new root.Salsa20(data.seed.slice(0, 32), data.seed.slice(32))
root.crypto.randomBytes = function (n) {
return state.getBytes(n)
}
}
if (data.debug) sendMsg('debug', 'DSA key creation started')
+12 -1
Ver Arquivo
@@ -50,6 +50,17 @@
child.__super__ = parent.prototype
}
// assumes 32-bit
function intCompare(x, y) {
var z = ~(x ^ y)
z &= z >> 16
z &= z >> 8
z &= z >> 4
z &= z >> 2
z &= z >> 1
return z & 1
}
// constant-time string comparison
HLP.compare = function (str1, str2) {
if (str1.length !== str2.length)
@@ -57,7 +68,7 @@
var i = 0, result = 0
for (; i < str1.length; i++)
result |= str1[i].charCodeAt(0) ^ str2[i].charCodeAt(0)
return result === 0
return intCompare(result, 0)
}
HLP.randomExponent = function () {
+13 -5
Ver Arquivo
@@ -2,11 +2,16 @@
"use strict";
root.OTR = {}
root.crypto = {
randomBytes: function () {
throw new Error("Haven't seeded yet.")
var hasCrypto = false
if (root.crypto)
hasCrypto = true
else
root.crypto = {
randomBytes: function () {
throw new Error("Haven't seeded yet.")
}
}
}
// default imports
var imports = [
@@ -36,7 +41,10 @@
if (data.imports) imports = data.imports
importScripts.apply(root, imports)
// use salsa20 since there's no prng in webworkers
if (hasCrypto)
break
// use salsa20 when there's no prng in webworkers
var state = new root.Salsa20(
data.seed.slice(0, 32),
data.seed.slice(32)
+116
Ver Arquivo
@@ -0,0 +1,116 @@
Strophe.addConnectionPlugin('bookmarks', {
init : function(connection) {
this.connection = connection;
Strophe.addNamespace('PRIVATE', 'jabber:iq:private');
Strophe.addNamespace('BOOKMARKS', 'storage:bookmarks');
Strophe.addNamespace('PRIVACY', 'jabber:iq:privacy');
Strophe.addNamespace('DELAY', 'jabber:x:delay');
Strophe.addNamespace('PUBSUB', 'http://jabber.org/protocol/pubsub');
},
/**
* Create private bookmark node.
*
* @param {function} [success] - Callback after success
* @param {function} [error] - Callback after error
*/
createBookmarksNode : function(success, error) {
// We do this instead of using publish-options because this is not
// mandatory to implement according to XEP-0060
this.connection.sendIQ($iq({
type : 'set'
}).c('pubsub', {
xmlns : Strophe.NS.PUBSUB
}).c('create', {
node : 'storage:bookmarks'
}).up().c('configure').c('x', {
xmlns : 'jabber:x:data',
type : 'submit'
}).c('field', {
'var' : 'FORM_TYPE',
type : 'hidden'
}).c('value').t('http://jabber.org/protocol/pubsub#node_config').up()
.up().c('field', {
'var' : 'pubsub#persist_items'
}).c('value').t('1').up().up().c('field', {
'var' : 'pubsub#access_model'
}).c('value').t('whitelist'), success, error);
return true;
},
/**
* Add bookmark to storage.
*
* @param {string} roomJid - The JabberID of the chat roomJid
* @param {string} [alias] - A friendly name for the bookmark
* @param {string} [nick] - The users's preferred roomnick for the chatroom
* @param {boolean} [autojoin=false] - Whether the client should automatically join
* the conference room on login.
* @param {function} [success] - Callback after success
* @param {function} [error] - Callback after error
*/
add : function(roomJid, alias, nick, autojoin, success, error) {
var conferenceAttr = {
jid: roomJid,
autojoin: autojoin || false
};
if (alias) {
conferenceAttr.name = alias;
}
var stanza = $iq({
type : 'set'
}).c('pubsub', {
xmlns : Strophe.NS.PUBSUB
}).c('publish', {
node : Strophe.NS.BOOKMARKS
}).c('item', {
id : roomJid
}).c('storage', {
xmlns : Strophe.NS.BOOKMARKS
}).c('conference', conferenceAttr);
if (nick) {
stanza.c('nick').t(nick);
}
this.connection.sendIQ(stanza, success, error);
},
/**
* Retrieve all stored bookmarks.
*
* @param {function} [success] - Callback after success
* @param {function} [error] - Callback after error
*/
get: function(success, error) {
this.connection.sendIQ($iq({
type : 'get'
}).c('pubsub', {
xmlns : Strophe.NS.PUBSUB
}).c('items', {
node : Strophe.NS.BOOKMARKS
}), success, error);
},
/**
* Delete the given entry for roomJid.
*
* @param {string} roomJid - The JabberID of the chat roomJid you want to remove
* @param {function} [success] - Callback after success
* @param {function} [error] - Callback after error
* @param {boolean} [notify=false] - True: notify all subscribers
*/
delete: function(roomJid, success, error, notify) {
this.connection.sendIQ($iq({
type : 'set'
}).c('pubsub', {
xmlns : Strophe.NS.PUBSUB
}).c('retract', {
node : Strophe.NS.BOOKMARKS,
notify: notify || false
}).c('item', {
id: roomJid
}), success, error);
}
});
+22 -9
Ver Arquivo
@@ -7,6 +7,8 @@
*
* Authors: - Michael Weibel <michael.weibel@gmail.com> - Klaus Herberth <klaus@jsxc.org>
* Copyright: - Michael Weibel <michael.weibel@gmail.com>
*
* @license MIT
*/
(function($) {
@@ -122,12 +124,17 @@
if (this._jidVerIndex[jid] && feature !== null && typeof feature !== 'undefined') {
if(!$.isArray(feature)){
feature = $.makeArray(feature);
};
}
var i;
var i, knownCapabilities;
knownCapabilities = this._knownCapabilities[this._jidVerIndex[jid]];
if (!knownCapabilities) {
return null;
}
for (i = 0; i < feature.length; i++) {
if (this._knownCapabilities[this._jidVerIndex[jid]]['features'].indexOf(feature[i]) < 0)
if (knownCapabilities['features'].indexOf(feature[i]) < 0) {
return false;
}
}
return true;
}
@@ -154,7 +161,7 @@
}
localStorage.setItem('strophe.caps._jidVerIndex', JSON.stringify(this._jidVerIndex));
$(document).trigger('caps.strophe', [ from ]);
$(document).trigger('caps.strophe', [ from, this._knownCapabilities[ver], ver]);
return true;
},
@@ -189,13 +196,18 @@
* Returns: (Boolean) - false, to automatically remove the handler.
*/
_handleDiscoInfoReply: function(stanza) {
var query = stanza.querySelector('query'), node = query.getAttribute('node').split('#'), ver = node[1], from = stanza.getAttribute('from');
var query = stanza.querySelector('query');
var from = stanza.getAttribute('from');
var node = query.getAttribute('node');
var ver = (node)? node.split('#')[1] : this._jidVerIndex[from]; //fix open prosody issue
if (!this._knownCapabilities[ver]) {
var childNodes = query.childNodes, childNodesLen = childNodes.length;
this._knownCapabilities[ver] = {
features: [],
identities: []
};
for (var i = 0; i < childNodesLen; i++) {
var node = childNodes[i];
if (node.nodeName == 'feature') {
@@ -203,10 +215,11 @@
} else if (node.nodeName == 'identity') {
this._knownCapabilities[ver]['identities'].push(this._attributesToJsObject(node.attributes));
} else {
if (_knownCapabilities[ver][node.nodeName])
_knownCapabilities[ver][node.nodeName] = [];
if (typeof this._knownCapabilities[ver][node.nodeName] === 'undefined')
this._knownCapabilities[ver][node.nodeName] = [];
this._knownCapabilities[ver][node.nodeName].push(this._attributesToJsObject(node.attributes));
}
}
this._jidVerIndex[from] = ver;
} else if (!this._jidVerIndex[from] || !this._jidVerIndex[from] !== ver) {
@@ -215,7 +228,7 @@
localStorage.setItem('strophe.caps._jidVerIndex', JSON.stringify(this._jidVerIndex));
localStorage.setItem('strophe.caps._knownCapabilities', JSON.stringify(this._knownCapabilities));
$(document).trigger('caps.strophe', [ from ]);
$(document).trigger('caps.strophe', [ from, this._knownCapabilities[ver], ver ]);
return false;
},
@@ -259,4 +272,4 @@
return 0;
}
});
}(jQuery));
}(jQuery));
@@ -1,330 +0,0 @@
/* jshint -W117 */
var setupRTC, getUserMediaWithConstraints, TraceablePeerConnection;
(function($){
TraceablePeerConnection = function(ice_config, constraints) {
var self = this;
var RTCPeerconnection = navigator.mozGetUserMedia ? mozRTCPeerConnection : webkitRTCPeerConnection;
this.peerconnection = new RTCPeerconnection(ice_config, constraints);
this.updateLog = [];
// override as desired
this.trace = function(what, info) {
//console.warn('WTRACE', what, info);
self.updateLog.push({
time: new Date(),
type: what,
value: info
});
};
this.onicecandidate = null;
this.peerconnection.onicecandidate = function (event) {
self.trace('onicecandidate', event.candidate);
if (self.onicecandidate !== null) {
self.onicecandidate(event);
}
};
this.onaddstream = null;
this.peerconnection.onaddstream = function (event) {
self.trace('onaddstream', event.stream);
if (self.onaddstream !== null) {
self.onaddstream(event);
}
};
this.onremovestream = null;
this.peerconnection.onremovestream = function (event) {
self.trace('onremovestream', event.stream);
if (self.onremovestream !== null) {
self.onremovestream(event);
}
};
this.onsignalingstatechange = null;
this.peerconnection.onsignalingstatechange = function (event) {
self.trace('onsignalingstatechange', event);
if (self.onsignalingstatechange !== null) {
self.onsignalingstatechange(event);
}
};
this.oniceconnectionstatechange = null;
this.peerconnection.oniceconnectionstatechange = function (event) {
self.trace('oniceconnectionstatechange', event);
if (self.oniceconnectionstatechange !== null) {
self.oniceconnectionstatechange(event);
}
};
this.onnegotiationneeded = null;
this.peerconnection.onnegotiationneeded = function (event) {
self.trace('onnegotiationneeded', event);
if (self.onnegotiationneeded !== null) {
self.onnegotiationneeded(event);
}
};
self.ondatachannel = null;
this.peerconnection.ondatachannel = function (event) {
self.trace('ondatachannel', event);
if (self.ondatachannel !== null) {
self.ondatachannel(event);
}
}
};
TraceablePeerConnection.prototype.__defineGetter__('signalingState', function() { return this.peerconnection.signalingState; });
TraceablePeerConnection.prototype.__defineGetter__('iceConnectionState', function() { return this.peerconnection.iceConnectionState; });
TraceablePeerConnection.prototype.__defineGetter__('localDescription', function() { return this.peerconnection.localDescription; });
TraceablePeerConnection.prototype.__defineGetter__('remoteDescription', function() { return this.peerconnection.remoteDescription; });
TraceablePeerConnection.prototype.addStream = function (stream) {
this.trace('addStream', stream);
this.peerconnection.addStream(stream);
};
TraceablePeerConnection.prototype.removeStream = function (stream) {
this.trace('removeStream', stream);
this.peerconnection.removeStream(stream);
};
TraceablePeerConnection.prototype.createDataChannel = function (label, opts) {
this.trace('createDataChannel', label, opts);
this.peerconnection.createDataChannel(label, opts);
}
TraceablePeerConnection.prototype.setLocalDescription = function (description, successCallback, failureCallback) {
var self = this;
this.trace('setLocalDescription', description);
this.peerconnection.setLocalDescription(description,
function () {
self.trace('setLocalDescriptionOnSuccess');
successCallback();
},
function (err) {
self.trace('setLocalDescriptionOnFailure', err);
failureCallback(err);
}
);
};
TraceablePeerConnection.prototype.setRemoteDescription = function (description, successCallback, failureCallback) {
var self = this;
this.trace('setRemoteDescription', description);
this.peerconnection.setRemoteDescription(description,
function () {
self.trace('setRemoteDescriptionOnSuccess');
successCallback();
},
function (err) {
self.trace('setRemoteDescriptionOnFailure', err);
failureCallback(err);
}
);
};
TraceablePeerConnection.prototype.close = function () {
this.trace('stop');
this.peerconnection.close();
};
TraceablePeerConnection.prototype.createOffer = function (successCallback, failureCallback, constraints) {
var self = this;
this.trace('createOffer', constraints);
this.peerconnection.createOffer(
function (sdp) {
self.trace('createOfferOnSuccess', sdp);
successCallback(sdp);
},
function(err) {
self.trace('createOfferOnFailure', err);
failureCallback(err);
},
constraints
);
};
TraceablePeerConnection.prototype.createAnswer = function (successCallback, failureCallback, constraints) {
var self = this;
this.trace('createAnswer', constraints);
this.peerconnection.createAnswer(
function (sdp) {
self.trace('createAnswerOnSuccess', sdp);
successCallback(sdp);
},
function(err) {
self.trace('createAnswerOnFailure', err);
failureCallback(err);
},
constraints
);
};
TraceablePeerConnection.prototype.addIceCandidate = function (candidate, successCallback, failureCallback) {
var self = this;
this.trace('addIceCandidate', candidate);
this.peerconnection.addIceCandidate(candidate);
/* maybe later
this.peerconnection.addIceCandidate(candidate,
function () {
self.trace('addIceCandidateOnSuccess');
successCallback();
},
function (err) {
self.trace('addIceCandidateOnFailure', err);
failureCallback(err);
}
);
*/
};
TraceablePeerConnection.prototype.getStats = function(callback) {
this.peerconnection.getStats(callback);
};
// mozilla chrome compat layer -- very similar to adapter.js
setupRTC = function (){
var RTC = null;
if (navigator.mozGetUserMedia) {
console.log('This appears to be Firefox');
var version = parseInt(navigator.userAgent.match(/Firefox\/([0-9]+)\./)[1], 10);
if (version >= 22) {
RTC = {
peerconnection: mozRTCPeerConnection,
browser: 'firefox',
getUserMedia: navigator.mozGetUserMedia.bind(navigator),
attachMediaStream: function (element, stream) {
element[0].mozSrcObject = stream;
element[0].play();
},
pc_constraints: {}
};
if (!MediaStream.prototype.getVideoTracks)
MediaStream.prototype.getVideoTracks = function () { return []; };
if (!MediaStream.prototype.getAudioTracks)
MediaStream.prototype.getAudioTracks = function () { return []; };
RTCSessionDescription = mozRTCSessionDescription;
RTCIceCandidate = mozRTCIceCandidate;
}
} else if (navigator.webkitGetUserMedia) {
console.log('This appears to be Chrome');
RTC = {
peerconnection: webkitRTCPeerConnection,
browser: 'chrome',
getUserMedia: navigator.webkitGetUserMedia.bind(navigator),
attachMediaStream: function (element, stream) {
element.attr('src', webkitURL.createObjectURL(stream));
},
// DTLS should now be enabled by default but..
pc_constraints: {'optional': [{'DtlsSrtpKeyAgreement': 'true'}]}
};
if (navigator.userAgent.indexOf('Android') != -1) {
RTC.pc_constraints = {}; // disable DTLS on Android
}
if (!webkitMediaStream.prototype.getVideoTracks) {
webkitMediaStream.prototype.getVideoTracks = function () {
return this.videoTracks;
};
}
if (!webkitMediaStream.prototype.getAudioTracks) {
webkitMediaStream.prototype.getAudioTracks = function () {
return this.audioTracks;
};
}
}
if (RTC === null) {
try { console.log('Browser does not appear to be WebRTC-capable'); } catch (e) { }
}
return RTC;
};
getUserMediaWithConstraints = function(um, resolution, bandwidth, fps) {
var constraints = {audio: false, video: false};
if (um.indexOf('video') >= 0) {
constraints.video = {mandatory: {}};// same behaviour as true
}
if (um.indexOf('audio') >= 0) {
constraints.audio = {};// same behaviour as true
}
if (um.indexOf('screen') >= 0) {
constraints.video = {
"mandatory": {
"chromeMediaSource": "screen"
}
};
}
if (resolution && !constraints.video) {
constraints.video = {mandatory: {}};// same behaviour as true
}
// see https://code.google.com/p/chromium/issues/detail?id=143631#c9 for list of supported resolutions
switch (resolution) {
// 16:9 first
case '1080':
case 'fullhd':
constraints.video.mandatory.minWidth = 1920;
constraints.video.mandatory.minHeight = 1080;
constraints.video.mandatory.minAspectRatio = 1.77;
break;
case '720':
case 'hd':
constraints.video.mandatory.minWidth = 1280;
constraints.video.mandatory.minHeight = 720;
constraints.video.mandatory.minAspectRatio = 1.77;
break;
case '360':
constraints.video.mandatory.minWidth = 640;
constraints.video.mandatory.minHeight = 360;
constraints.video.mandatory.minAspectRatio = 1.77;
break;
case '180':
constraints.video.mandatory.minWidth = 320;
constraints.video.mandatory.minHeight = 180;
constraints.video.mandatory.minAspectRatio = 1.77;
break;
// 4:3
case '960':
constraints.video.mandatory.minWidth = 960;
constraints.video.mandatory.minHeight = 720;
break;
case '640':
case 'vga':
constraints.video.mandatory.minWidth = 640;
constraints.video.mandatory.minHeight = 480;
break;
case '320':
constraints.video.mandatory.minWidth = 320;
constraints.video.mandatory.minHeight = 240;
break;
default:
if (navigator.userAgent.indexOf('Android') != -1) {
constraints.video.mandatory.minWidth = 320;
constraints.video.mandatory.minHeight = 240;
constraints.video.mandatory.maxFrameRate = 15;
}
break;
}
if (bandwidth) { // doesn't work currently, see webrtc issue 1846
if (!constraints.video) constraints.video = {mandatory: {}};//same behaviour as true
constraints.video.optional = [{bandwidth: bandwidth}];
}
if (fps) { // for some cameras it might be necessary to request 30fps
// so they choose 30fps mjpg over 10fps yuy2
if (!constraints.video) constraints.video = {mandatory: {}};// same behaviour as tru;
constraints.video.mandatory.minFrameRate = fps;
}
try {
RTC.getUserMedia(constraints,
function (stream) {
console.log('onUserMediaSuccess');
$(document).trigger('mediaready.jingle', [stream]);
},
function (error) {
console.warn('Failed to get access to local media. Error ', error);
$(document).trigger('mediafailure.jingle');
});
} catch (e) {
console.error('GUM failed: ', e);
$(document).trigger('mediafailure.jingle');
}
}
}(jQuery));
-261
Ver Arquivo
@@ -1,261 +0,0 @@
/* jshint -W117 */
(function($){
Strophe.addConnectionPlugin('jingle', {
connection: null,
sessions: {},
jid2session: {},
ice_config: {iceServers: []},
pc_constraints: {},
media_constraints: {
mandatory: {
'OfferToReceiveAudio': true,
'OfferToReceiveVideo': true
}
// MozDontOfferDataChannel: true when this is firefox
},
localStream: null,
init: function (conn) {
this.connection = conn;
if (this.connection.disco) {
// http://xmpp.org/extensions/xep-0167.html#support
// http://xmpp.org/extensions/xep-0176.html#support
this.connection.disco.addFeature('urn:xmpp:jingle:1');
this.connection.disco.addFeature('urn:xmpp:jingle:apps:rtp:1');
this.connection.disco.addFeature('urn:xmpp:jingle:transports:ice-udp:1');
this.connection.disco.addFeature('urn:xmpp:jingle:apps:rtp:audio');
this.connection.disco.addFeature('urn:xmpp:jingle:apps:rtp:video');
// this is dealt with by SDP O/A so we don't need to annouce this
//this.connection.disco.addFeature('urn:xmpp:jingle:apps:rtp:rtcp-fb:0'); // XEP-0293
//this.connection.disco.addFeature('urn:xmpp:jingle:apps:rtp:rtp-hdrext:0'); // XEP-0294
this.connection.disco.addFeature('urn:ietf:rfc:5761'); // rtcp-mux
//this.connection.disco.addFeature('urn:ietf:rfc:5888'); // a=group, e.g. bundle
//this.connection.disco.addFeature('urn:ietf:rfc:5576'); // a=ssrc
}
this.connection.addHandler(this.onJingle.bind(this), 'urn:xmpp:jingle:1', 'iq', 'set', null, null);
},
onJingle: function (iq) {
var sid = $(iq).find('jingle').attr('sid');
var action = $(iq).find('jingle').attr('action');
// send ack first
var ack = $iq({type: 'result',
to: iq.getAttribute('from'),
id: iq.getAttribute('id')
});
console.log('on jingle ' + action);
var sess = this.sessions[sid];
if ('session-initiate' != action) {
if (sess === null) {
ack.type = 'error';
ack.c('error', {type: 'cancel'})
.c('item-not-found', {xmlns: 'urn:ietf:params:xml:ns:xmpp-stanzas'}).up()
.c('unknown-session', {xmlns: 'urn:xmpp:jingle:errors:1'});
this.connection.send(ack);
return true;
}
// compare from to sess.peerjid (bare jid comparison for later compat with message-mode)
// local jid is not checked
if (Strophe.getBareJidFromJid(iq.getAttribute('from')) != Strophe.getBareJidFromJid(sess.peerjid)) {
console.warn('jid mismatch for session id', sid, iq.getAttribute('from'), sess.peerjid);
ack.type = 'error';
ack.c('error', {type: 'cancel'})
.c('item-not-found', {xmlns: 'urn:ietf:params:xml:ns:xmpp-stanzas'}).up()
.c('unknown-session', {xmlns: 'urn:xmpp:jingle:errors:1'});
this.connection.send(ack);
return true;
}
} else if (sess !== undefined) {
// existing session with same session id
// this might be out-of-order if the sess.peerjid is the same as from
ack.type = 'error';
ack.c('error', {type: 'cancel'})
.c('service-unavailable', {xmlns: 'urn:ietf:params:xml:ns:xmpp-stanzas'}).up();
console.warn('duplicate session id', sid);
this.connection.send(ack);
return true;
}
// FIXME: check for a defined action
this.connection.send(ack);
// see http://xmpp.org/extensions/xep-0166.html#concepts-session
switch (action) {
case 'session-initiate':
sess = new JingleSession($(iq).attr('to'), $(iq).find('jingle').attr('sid'), this.connection);
// configure session
if (this.localStream) {
sess.localStreams.push(this.localStream);
}
sess.media_constraints = this.media_constraints;
sess.pc_constraints = this.pc_constraints;
sess.ice_config = this.ice_config;
sess.initiate($(iq).attr('from'), false);
// FIXME: setRemoteDescription should only be done when this call is to be accepted
sess.setRemoteDescription($(iq).find('>jingle'), 'offer');
this.sessions[sess.sid] = sess;
this.jid2session[sess.peerjid] = sess;
// the callback should either
// .sendAnswer and .accept
// or .sendTerminate -- not necessarily synchronus
$(document).trigger('callincoming.jingle', [sess.sid]);
break;
case 'session-accept':
sess.setRemoteDescription($(iq).find('>jingle'), 'answer');
sess.accept();
$(document).trigger('callaccepted.jingle', [sess.sid]);
break;
case 'session-terminate':
console.log('terminating...');
sess.terminate();
this.terminate(sess.sid);
if ($(iq).find('>jingle>reason').length) {
$(document).trigger('callterminated.jingle', [
sess.sid,
$(iq).find('>jingle>reason>:first')[0].tagName,
$(iq).find('>jingle>reason>text').text()
]);
} else {
$(document).trigger('callterminated.jingle', [sess.sid]);
}
break;
case 'transport-info':
sess.addIceCandidate($(iq).find('>jingle>content'));
break;
case 'session-info':
var affected;
if ($(iq).find('>jingle>ringing[xmlns="urn:xmpp:jingle:apps:rtp:info:1"]').length) {
$(document).trigger('ringing.jingle', [sess.sid]);
} else if ($(iq).find('>jingle>mute[xmlns="urn:xmpp:jingle:apps:rtp:info:1"]').length) {
affected = $(iq).find('>jingle>mute[xmlns="urn:xmpp:jingle:apps:rtp:info:1"]').attr('name');
$(document).trigger('mute.jingle', [sess.sid, affected]);
} else if ($(iq).find('>jingle>unmute[xmlns="urn:xmpp:jingle:apps:rtp:info:1"]').length) {
affected = $(iq).find('>jingle>unmute[xmlns="urn:xmpp:jingle:apps:rtp:info:1"]').attr('name');
$(document).trigger('unmute.jingle', [sess.sid, affected]);
}
break;
case 'addsource': // FIXME: proprietary
sess.addSource($(iq).find('>jingle>content'));
break;
case 'removesource': // FIXME: proprietary
sess.removeSource($(iq).find('>jingle>content'));
break;
default:
console.warn('jingle action not implemented', action);
break;
}
return true;
},
initiate: function (peerjid, myjid) { // initiate a new jinglesession to peerjid
var sess = new JingleSession(myjid || this.connection.jid,
Math.random().toString(36).substr(2, 12), // random string
this.connection);
// configure session
if (this.localStream) {
sess.localStreams.push(this.localStream);
}
sess.media_constraints = this.media_constraints;
sess.pc_constraints = this.pc_constraints;
sess.ice_config = this.ice_config;
sess.initiate(peerjid, true);
this.sessions[sess.sid] = sess;
this.jid2session[sess.peerjid] = sess;
sess.sendOffer();
return sess;
},
terminate: function (sid, reason, text) { // terminate by sessionid (or all sessions)
if (sid === null || sid === undefined) {
for (sid in this.sessions) {
if (this.sessions[sid].state != 'ended') {
this.sessions[sid].sendTerminate(reason || (!this.sessions[sid].active()) ? 'cancel' : null, text);
this.sessions[sid].terminate();
}
delete this.jid2session[this.sessions[sid].peerjid];
delete this.sessions[sid];
}
} else if (this.sessions.hasOwnProperty(sid)) {
if (this.sessions[sid].state != 'ended') {
this.sessions[sid].sendTerminate(reason || (!this.sessions[sid].active()) ? 'cancel' : null, text);
this.sessions[sid].terminate();
}
delete this.jid2session[this.sessions[sid].peerjid];
delete this.sessions[sid];
}
},
terminateByJid: function (jid) {
if (this.jid2session.hasOwnProperty(jid)) {
var sess = this.jid2session[jid];
if (sess) {
sess.terminate();
console.log('peer went away silently', jid);
delete this.sessions[sess.sid];
delete this.jid2session[jid];
$(document).trigger('callterminated.jingle', [sess.sid, 'gone']);
}
}
},
getStunAndTurnCredentials: function () {
// get stun and turn configuration from server via xep-0215
// uses time-limited credentials as described in
// http://tools.ietf.org/html/draft-uberti-behave-turn-rest-00
//
// see https://code.google.com/p/prosody-modules/source/browse/mod_turncredentials/mod_turncredentials.lua
// for a prosody module which implements this
//
// currently, this doesn't work with updateIce and therefore credentials with a long
// validity have to be fetched before creating the peerconnection
// TODO: implement refresh via updateIce as described in
// https://code.google.com/p/webrtc/issues/detail?id=1650
this.connection.sendIQ(
$iq({type: 'get', to: this.connection.domain})
.c('services', {xmlns: 'urn:xmpp:extdisco:1'}).c('service', {host: 'turn.' + this.connection.domain}),
function (res) {
var iceservers = [];
$(res).find('>services>service').each(function (idx, el) {
el = $(el);
var dict = {};
switch (el.attr('type')) {
case 'stun':
dict.url = 'stun:' + el.attr('host');
if (el.attr('port')) {
dict.url += ':' + el.attr('port');
}
iceservers.push(dict);
break;
case 'turn':
dict.url = 'turn:';
if (el.attr('username')) { // https://code.google.com/p/webrtc/issues/detail?id=1508
if (navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./) && parseInt(navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2], 10) < 28) {
dict.url += el.attr('username') + '@';
} else {
dict.username = el.attr('username'); // only works in M28
}
}
dict.url += el.attr('host');
if (el.attr('port') && el.attr('port') != '3478') {
dict.url += ':' + el.attr('port');
}
if (el.attr('transport') && el.attr('transport') != 'udp') {
dict.url += '?transport=' + el.attr('transport');
}
if (el.attr('password')) {
dict.credential = el.attr('password');
}
iceservers.push(dict);
break;
}
});
this.ice_config.iceServers = iceservers;
},
function (err) {
console.warn('getting turn credentials failed', err);
console.warn('is mod_turncredentials or similar installed?');
}
);
// implement push?
}
});
}(jQuery));
@@ -1,813 +0,0 @@
/* jshint -W117 */
var SDP;
(function($){
// SDP STUFF
SDP = function(sdp) {
this.media = sdp.split('\r\nm=');
for (var i = 1; i < this.media.length; i++) {
this.media[i] = 'm=' + this.media[i];
if (i != this.media.length - 1) {
this.media[i] += '\r\n';
}
}
this.session = this.media.shift() + '\r\n';
this.raw = this.session + this.media.join('');
}
// remove iSAC and CN from SDP
SDP.prototype.mangle = function () {
var i, j, mline, lines, rtpmap, newdesc;
for (i = 0; i < this.media.length; i++) {
lines = this.media[i].split('\r\n');
lines.pop(); // remove empty last element
mline = SDPUtil.parse_mline(lines.shift());
if (mline.media != 'audio')
continue;
newdesc = '';
mline.fmt.length = 0;
for (j = 0; j < lines.length; j++) {
if (lines[j].substr(0, 9) == 'a=rtpmap:') {
rtpmap = SDPUtil.parse_rtpmap(lines[j]);
if (rtpmap.name == 'CN' || rtpmap.name == 'ISAC')
continue;
mline.fmt.push(rtpmap.id);
newdesc += lines[j] + '\r\n';
} else {
newdesc += lines[j] + '\r\n';
}
}
this.media[i] = SDPUtil.build_mline(mline) + '\r\n';
this.media[i] += newdesc;
}
this.raw = this.session + this.media.join('');
};
// remove lines matching prefix from session section
SDP.prototype.removeSessionLines = function(prefix) {
var self = this;
var lines = SDPUtil.find_lines(this.session, prefix);
lines.forEach(function(line) {
self.session = self.session.replace(line + '\r\n', '');
});
this.raw = this.session + this.media.join('');
return lines;
}
// remove lines matching prefix from a media section specified by mediaindex
// TODO: non-numeric mediaindex could match mid
SDP.prototype.removeMediaLines = function(mediaindex, prefix) {
var self = this;
var lines = SDPUtil.find_lines(this.media[mediaindex], prefix);
lines.forEach(function(line) {
self.media[mediaindex] = self.media[mediaindex].replace(line + '\r\n', '');
});
this.raw = this.session + this.media.join('');
return lines;
}
// add content's to a jingle element
SDP.prototype.toJingle = function (elem, thecreator) {
var i, j, k, mline, ssrc, rtpmap, tmp, line, lines;
var self = this;
// new bundle plan
if (SDPUtil.find_line(this.session, 'a=group:')) {
lines = SDPUtil.find_lines(this.session, 'a=group:');
for (i = 0; i < lines.length; i++) {
tmp = lines[i].split(' ');
var semantics = tmp.shift().substr(8);
// new plan
elem.c('group', {xmlns: 'urn:xmpp:jingle:apps:grouping:0', type: semantics, semantics:semantics});
for (j = 0; j < tmp.length; j++) {
elem.c('content', {name: tmp[j]}).up();
}
elem.up();
// temporary plan, to be removed
elem.c('group', {xmlns: 'urn:ietf:rfc:5888', type: semantics});
for (j = 0; j < tmp.length; j++) {
elem.c('content', {name: tmp[j]}).up();
}
elem.up();
}
}
// old bundle plan, to be removed
var bundle = [];
if (SDPUtil.find_line(this.session, 'a=group:BUNDLE')) {
bundle = SDPUtil.find_line(this.session, 'a=group:BUNDLE ').split(' ');
bundle.shift();
}
for (i = 0; i < this.media.length; i++) {
mline = SDPUtil.parse_mline(this.media[i].split('\r\n')[0]);
if (!(mline.media == 'audio' || mline.media == 'video')) {
continue;
}
if (SDPUtil.find_line(this.media[i], 'a=ssrc:')) {
ssrc = SDPUtil.find_line(this.media[i], 'a=ssrc:').substring(7).split(' ')[0]; // take the first
} else {
ssrc = false;
}
elem.c('content', {creator: thecreator, name: mline.media});
if (SDPUtil.find_line(this.media[i], 'a=mid:')) {
// prefer identifier from a=mid if present
var mid = SDPUtil.parse_mid(SDPUtil.find_line(this.media[i], 'a=mid:'));
elem.attrs({ name: mid });
// old BUNDLE plan, to be removed
if (bundle.indexOf(mid) != -1) {
elem.c('bundle', {xmlns: 'http://estos.de/ns/bundle'}).up();
bundle.splice(bundle.indexOf(mid), 1);
}
}
if (SDPUtil.find_line(this.media[i], 'a=rtpmap:').length) {
elem.c('description',
{xmlns: 'urn:xmpp:jingle:apps:rtp:1',
media: mline.media });
if (ssrc) {
elem.attrs({ssrc: ssrc});
}
for (j = 0; j < mline.fmt.length; j++) {
rtpmap = SDPUtil.find_line(this.media[i], 'a=rtpmap:' + mline.fmt[j]);
elem.c('payload-type', SDPUtil.parse_rtpmap(rtpmap));
// put any 'a=fmtp:' + mline.fmt[j] lines into <param name=foo value=bar/>
if (SDPUtil.find_line(this.media[i], 'a=fmtp:' + mline.fmt[j])) {
tmp = SDPUtil.parse_fmtp(SDPUtil.find_line(this.media[i], 'a=fmtp:' + mline.fmt[j]));
for (k = 0; k < tmp.length; k++) {
elem.c('parameter', tmp[k]).up();
}
}
this.RtcpFbToJingle(i, elem, mline.fmt[j]); // XEP-0293 -- map a=rtcp-fb
elem.up();
}
if (SDPUtil.find_line(this.media[i], 'a=crypto:', this.session)) {
elem.c('encryption', {required: 1});
var crypto = SDPUtil.find_lines(this.media[i], 'a=crypto:', this.session);
crypto.forEach(function(line) {
elem.c('crypto', SDPUtil.parse_crypto(line)).up();
});
elem.up(); // end of encryption
}
if (ssrc) {
// new style mapping
elem.c('source', { ssrc: ssrc, xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0' });
// FIXME: group by ssrc and support multiple different ssrcs
var ssrclines = SDPUtil.find_lines(this.media[i], 'a=ssrc:');
ssrclines.forEach(function(line) {
idx = line.indexOf(' ');
var linessrc = line.substr(0, idx).substr(7);
if (linessrc != ssrc) {
elem.up();
ssrc = linessrc;
elem.c('source', { ssrc: ssrc, xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0' });
}
var kv = line.substr(idx + 1);
elem.c('parameter');
if (kv.indexOf(':') == -1) {
elem.attrs({ name: kv });
} else {
elem.attrs({ name: kv.split(':', 2)[0] });
elem.attrs({ value: kv.split(':', 2)[1] });
}
elem.up();
});
elem.up();
// old proprietary mapping, to be removed at some point
tmp = SDPUtil.parse_ssrc(this.media[i]);
tmp.xmlns = 'http://estos.de/ns/ssrc';
tmp.ssrc = ssrc;
elem.c('ssrc', tmp).up(); // ssrc is part of description
}
if (SDPUtil.find_line(this.media[i], 'a=rtcp-mux')) {
elem.c('rtcp-mux').up();
}
// XEP-0293 -- map a=rtcp-fb:*
this.RtcpFbToJingle(i, elem, '*');
// XEP-0294
if (SDPUtil.find_line(this.media[i], 'a=extmap:')) {
lines = SDPUtil.find_lines(this.media[i], 'a=extmap:');
for (j = 0; j < lines.length; j++) {
tmp = SDPUtil.parse_extmap(lines[j]);
elem.c('rtp-hdrext', { xmlns: 'urn:xmpp:jingle:apps:rtp:rtp-hdrext:0',
uri: tmp.uri,
id: tmp.value });
if (tmp.hasOwnProperty('direction')) {
switch (tmp.direction) {
case 'sendonly':
elem.attrs({senders: 'responder'});
break;
case 'recvonly':
elem.attrs({senders: 'initiator'});
break;
case 'sendrecv':
elem.attrs({senders: 'both'});
break;
case 'inactive':
elem.attrs({senders: 'none'});
break;
}
}
// TODO: handle params
elem.up();
}
}
elem.up(); // end of description
}
// map ice-ufrag/pwd, dtls fingerprint, candidates
this.TransportToJingle(i, elem);
if (SDPUtil.find_line(this.media[i], 'a=sendrecv', this.session)) {
elem.attrs({senders: 'both'});
} else if (SDPUtil.find_line(this.media[i], 'a=sendonly', this.session)) {
elem.attrs({senders: 'initiator'});
} else if (SDPUtil.find_line(this.media[i], 'a=recvonly', this.session)) {
elem.attrs({senders: 'responder'});
} else if (SDPUtil.find_line(this.media[i], 'a=inactive', this.session)) {
elem.attrs({senders: 'none'});
}
if (mline.port == '0') {
// estos hack to reject an m-line
elem.attrs({senders: 'rejected'});
}
elem.up(); // end of content
}
elem.up();
return elem;
};
SDP.prototype.TransportToJingle = function (mediaindex, elem) {
var i = mediaindex;
var tmp;
var self = this;
elem.c('transport');
// XEP-0320
var fingerprints = SDPUtil.find_lines(this.media[mediaindex], 'a=fingerprint:', this.session);
fingerprints.forEach(function(line) {
tmp = SDPUtil.parse_fingerprint(line);
tmp.xmlns = 'urn:xmpp:tmp:jingle:apps:dtls:0';
// tmp.xmlns = 'urn:xmpp:jingle:apps:dtls:0'; -- FIXME: update receivers first
elem.c('fingerprint').t(tmp.fingerprint);
delete tmp.fingerprint;
line = SDPUtil.find_line(self.media[mediaindex], 'a=setup:', self.session);
if (line) {
tmp.setup = line.substr(8);
}
elem.attrs(tmp);
elem.up(); // end of fingerprint
});
tmp = SDPUtil.iceparams(this.media[mediaindex], this.session);
if (tmp) {
tmp.xmlns = 'urn:xmpp:jingle:transports:ice-udp:1';
elem.attrs(tmp);
// XEP-0176
if (SDPUtil.find_line(this.media[mediaindex], 'a=candidate:', this.session)) { // add any a=candidate lines
var lines = SDPUtil.find_lines(this.media[mediaindex], 'a=candidate:', this.session);
lines.forEach(function (line) {
elem.c('candidate', SDPUtil.candidateToJingle(line)).up();
});
}
}
elem.up(); // end of transport
}
SDP.prototype.RtcpFbToJingle = function (mediaindex, elem, payloadtype) { // XEP-0293
var lines = SDPUtil.find_lines(this.media[mediaindex], 'a=rtcp-fb:' + payloadtype);
lines.forEach(function (line) {
var tmp = SDPUtil.parse_rtcpfb(line);
if (tmp.type == 'trr-int') {
elem.c('rtcp-fb-trr-int', {xmlns: 'urn:xmpp:jingle:apps:rtp:rtcp-fb:0', value: tmp.params[0]});
elem.up();
} else {
elem.c('rtcp-fb', {xmlns: 'urn:xmpp:jingle:apps:rtp:rtcp-fb:0', type: tmp.type});
if (tmp.params.length > 0) {
elem.attrs({'subtype': tmp.params[0]});
}
elem.up();
}
});
};
SDP.prototype.RtcpFbFromJingle = function (elem, payloadtype) { // XEP-0293
var media = '';
var tmp = elem.find('>rtcp-fb-trr-int[xmlns="urn:xmpp:jingle:apps:rtp:rtcp-fb:0"]');
if (tmp.length) {
media += 'a=rtcp-fb:' + '*' + ' ' + 'trr-int' + ' ';
if (tmp.attr('value')) {
media += tmp.attr('value');
} else {
media += '0';
}
media += '\r\n';
}
tmp = elem.find('>rtcp-fb[xmlns="urn:xmpp:jingle:apps:rtp:rtcp-fb:0"]');
tmp.each(function () {
media += 'a=rtcp-fb:' + payloadtype + ' ' + $(this).attr('type');
if ($(this).attr('subtype')) {
media += ' ' + $(this).attr('subtype');
}
media += '\r\n';
});
return media;
};
// construct an SDP from a jingle stanza
SDP.prototype.fromJingle = function (jingle) {
var self = this;
this.raw = 'v=0\r\n' +
'o=- ' + '1923518516' + ' 2 IN IP4 0.0.0.0\r\n' +// FIXME
's=-\r\n' +
't=0 0\r\n';
// http://tools.ietf.org/html/draft-ietf-mmusic-sdp-bundle-negotiation-04#section-8
if ($(jingle).find('>group[xmlns="urn:xmpp:jingle:apps:grouping:0"]').length) {
$(jingle).find('>group[xmlns="urn:xmpp:jingle:apps:grouping:0"]').each(function (idx, group) {
var contents = $(group).find('>content').map(function (idx, content) {
return content.getAttribute('name');
}).get();
if (contents.length > 0) {
self.raw += 'a=group:' + (group.getAttribute('semantics') || group.getAttribute('type')) + ' ' + contents.join(' ') + '\r\n';
}
});
} else if ($(jingle).find('>group[xmlns="urn:ietf:rfc:5888"]').length) {
// temporary namespace, not to be used. to be removed soon.
$(jingle).find('>group[xmlns="urn:ietf:rfc:5888"]').each(function (idx, group) {
var contents = $(group).find('>content').map(function (idx, content) {
return content.getAttribute('name');
}).get();
if (group.getAttribute('type') !== null && contents.length > 0) {
self.raw += 'a=group:' + group.getAttribute('type') + ' ' + contents.join(' ') + '\r\n';
}
});
} else {
// for backward compability, to be removed soon
// assume all contents are in the same bundle group, can be improved upon later
var bundle = $(jingle).find('>content').filter(function (idx, content) {
//elem.c('bundle', {xmlns:'http://estos.de/ns/bundle'});
return $(content).find('>bundle').length > 0;
}).map(function (idx, content) {
return content.getAttribute('name');
}).get();
if (bundle.length) {
this.raw += 'a=group:BUNDLE ' + bundle.join(' ') + '\r\n';
}
}
this.session = this.raw;
jingle.find('>content').each(function () {
var m = self.jingle2media($(this));
self.media.push(m);
});
// reconstruct msid-semantic -- apparently not necessary
/*
var msid = SDPUtil.parse_ssrc(this.raw);
if (msid.hasOwnProperty('mslabel')) {
this.session += "a=msid-semantic: WMS " + msid.mslabel + "\r\n";
}
*/
this.raw = this.session + this.media.join('');
};
// translate a jingle content element into an an SDP media part
SDP.prototype.jingle2media = function (content) {
var media = '',
desc = content.find('description'),
ssrc = desc.attr('ssrc'),
self = this,
tmp;
tmp = { media: desc.attr('media') };
tmp.port = '1';
if (content.attr('senders') == 'rejected') {
// estos hack to reject an m-line.
tmp.port = '0';
}
if (content.find('>transport>fingerprint').length || desc.find('encryption').length) {
tmp.proto = 'RTP/SAVPF';
} else {
tmp.proto = 'RTP/AVPF';
}
tmp.fmt = desc.find('payload-type').map(function () { return this.getAttribute('id'); }).get();
media += SDPUtil.build_mline(tmp) + '\r\n';
media += 'c=IN IP4 0.0.0.0\r\n';
media += 'a=rtcp:1 IN IP4 0.0.0.0\r\n';
tmp = content.find('>transport[xmlns="urn:xmpp:jingle:transports:ice-udp:1"]');
if (tmp.length) {
if (tmp.attr('ufrag')) {
media += SDPUtil.build_iceufrag(tmp.attr('ufrag')) + '\r\n';
}
if (tmp.attr('pwd')) {
media += SDPUtil.build_icepwd(tmp.attr('pwd')) + '\r\n';
}
tmp.find('>fingerprint').each(function () {
// FIXME: check namespace at some point
media += 'a=fingerprint:' + this.getAttribute('hash');
media += ' ' + $(this).text();
media += '\r\n';
if (this.getAttribute('setup')) {
media += 'a=setup:' + this.getAttribute('setup') + '\r\n';
}
});
}
switch (content.attr('senders')) {
case 'initiator':
media += 'a=sendonly\r\n';
break;
case 'responder':
media += 'a=recvonly\r\n';
break;
case 'none':
media += 'a=inactive\r\n';
break;
case 'both':
media += 'a=sendrecv\r\n';
break;
}
media += 'a=mid:' + content.attr('name') + '\r\n';
// <description><rtcp-mux/></description>
// see http://code.google.com/p/libjingle/issues/detail?id=309 -- no spec though
// and http://mail.jabber.org/pipermail/jingle/2011-December/001761.html
if (desc.find('rtcp-mux').length) {
media += 'a=rtcp-mux\r\n';
}
if (desc.find('encryption').length) {
desc.find('encryption>crypto').each(function () {
media += 'a=crypto:' + this.getAttribute('tag');
media += ' ' + this.getAttribute('crypto-suite');
media += ' ' + this.getAttribute('key-params');
if (this.getAttribute('session-params')) {
media += ' ' + this.getAttribute('session-params');
}
media += '\r\n';
});
}
desc.find('payload-type').each(function () {
media += SDPUtil.build_rtpmap(this) + '\r\n';
if ($(this).find('>parameter').length) {
media += 'a=fmtp:' + this.getAttribute('id') + ' ';
media += $(this).find('parameter').map(function () { return (this.getAttribute('name') ? (this.getAttribute('name') + '=') : '') + this.getAttribute('value'); }).get().join(';');
media += '\r\n';
}
// xep-0293
media += self.RtcpFbFromJingle($(this), this.getAttribute('id'));
});
// xep-0293
media += self.RtcpFbFromJingle(desc, '*');
// xep-0294
tmp = desc.find('>rtp-hdrext[xmlns="urn:xmpp:jingle:apps:rtp:rtp-hdrext:0"]');
tmp.each(function () {
media += 'a=extmap:' + this.getAttribute('id') + ' ' + this.getAttribute('uri') + '\r\n';
});
content.find('>transport[xmlns="urn:xmpp:jingle:transports:ice-udp:1"]>candidate').each(function () {
media += SDPUtil.candidateFromJingle(this);
});
tmp = content.find('description>source[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]');
tmp.each(function () {
var ssrc = this.getAttribute('ssrc');
$(this).find('>parameter').each(function () {
media += 'a=ssrc:' + ssrc + ' ' + this.getAttribute('name');
if (this.getAttribute('value') && this.getAttribute('value').length)
media += ':' + this.getAttribute('value');
media += '\r\n';
});
});
if (tmp.length === 0) {
// fallback to proprietary mapping of a=ssrc lines
tmp = content.find('description>ssrc[xmlns="http://estos.de/ns/ssrc"]');
if (tmp.length) {
media += 'a=ssrc:' + ssrc + ' cname:' + tmp.attr('cname') + '\r\n';
media += 'a=ssrc:' + ssrc + ' msid:' + tmp.attr('msid') + '\r\n';
media += 'a=ssrc:' + ssrc + ' mslabel:' + tmp.attr('mslabel') + '\r\n';
media += 'a=ssrc:' + ssrc + ' label:' + tmp.attr('label') + '\r\n';
}
}
return media;
};
SDPUtil = {
iceparams: function (mediadesc, sessiondesc) {
var data = null;
if (SDPUtil.find_line(mediadesc, 'a=ice-ufrag:', sessiondesc) &&
SDPUtil.find_line(mediadesc, 'a=ice-pwd:', sessiondesc)) {
data = {
ufrag: SDPUtil.parse_iceufrag(SDPUtil.find_line(mediadesc, 'a=ice-ufrag:', sessiondesc)),
pwd: SDPUtil.parse_icepwd(SDPUtil.find_line(mediadesc, 'a=ice-pwd:', sessiondesc))
};
}
return data;
},
parse_iceufrag: function (line) {
return line.substring(12);
},
build_iceufrag: function (frag) {
return 'a=ice-ufrag:' + frag;
},
parse_icepwd: function (line) {
return line.substring(10);
},
build_icepwd: function (pwd) {
return 'a=ice-pwd:' + pwd;
},
parse_mid: function (line) {
return line.substring(6);
},
parse_mline: function (line) {
var parts = line.substring(2).split(' '),
data = {};
data.media = parts.shift();
data.port = parts.shift();
data.proto = parts.shift();
if (parts[parts.length - 1] === '') { // trailing whitespace
parts.pop();
}
data.fmt = parts;
return data;
},
build_mline: function (mline) {
return 'm=' + mline.media + ' ' + mline.port + ' ' + mline.proto + ' ' + mline.fmt.join(' ');
},
parse_rtpmap: function (line) {
var parts = line.substring(9).split(' '),
data = {};
data.id = parts.shift();
parts = parts[0].split('/');
data.name = parts.shift();
data.clockrate = parts.shift();
data.channels = parts.length ? parts.shift() : '1';
return data;
},
build_rtpmap: function (el) {
var line = 'a=rtpmap:' + el.getAttribute('id') + ' ' + el.getAttribute('name') + '/' + el.getAttribute('clockrate');
if (el.getAttribute('channels') && el.getAttribute('channels') != '1') {
line += '/' + el.getAttribute('channels');
}
return line;
},
parse_crypto: function (line) {
var parts = line.substring(9).split(' '),
data = {};
data.tag = parts.shift();
data['crypto-suite'] = parts.shift();
data['key-params'] = parts.shift();
if (parts.length) {
data['session-params'] = parts.join(' ');
}
return data;
},
parse_fingerprint: function (line) { // RFC 4572
var parts = line.substring(14).split(' '),
data = {};
data.hash = parts.shift();
data.fingerprint = parts.shift();
// TODO assert that fingerprint satisfies 2UHEX *(":" 2UHEX) ?
return data;
},
parse_fmtp: function (line) {
var parts = line.split(' '),
i, key, value,
data = [];
parts.shift();
parts = parts.join(' ').split(';');
for (i = 0; i < parts.length; i++) {
key = parts[i].split('=')[0];
while (key.length && key[0] == ' ') {
key = key.substring(1);
}
value = parts[i].split('=')[1];
if (key && value) {
data.push({name: key, value: value});
} else if (key) {
// rfc 4733 (DTMF) style stuff
data.push({name: '', value: key});
}
}
return data;
},
parse_icecandidate: function (line) {
var candidate = {},
elems = line.split(' ');
candidate.foundation = elems[0].substring(12);
candidate.component = elems[1];
candidate.protocol = elems[2].toLowerCase();
candidate.priority = elems[3];
candidate.ip = elems[4];
candidate.port = elems[5];
// elems[6] => "typ"
candidate.type = elems[7];
candidate.generation = 0; // default value, may be overwritten below
for (var i = 8; i < elems.length; i += 2) {
switch (elems[i]) {
case 'raddr':
candidate['rel-addr'] = elems[i + 1];
break;
case 'rport':
candidate['rel-port'] = elems[i + 1];
break;
case 'generation':
candidate.generation = elems[i + 1];
break;
default: // TODO
console.log('parse_icecandidate not translating "' + elems[i] + '" = "' + elems[i + 1] + '"');
}
}
candidate.network = '1';
candidate.id = Math.random().toString(36).substr(2, 10); // not applicable to SDP -- FIXME: should be unique, not just random
return candidate;
},
build_icecandidate: function (cand) {
var line = ['a=candidate:' + cand.foundation, cand.component, cand.protocol, cand.priority, cand.ip, cand.port, 'typ', cand.type].join(' ');
line += ' ';
switch (cand.type) {
case 'srflx':
case 'prflx':
case 'relay':
if (cand.hasOwnAttribute('rel-addr') && cand.hasOwnAttribute('rel-port')) {
line += 'raddr';
line += ' ';
line += cand['rel-addr'];
line += ' ';
line += 'rport';
line += ' ';
line += cand['rel-port'];
line += ' ';
}
break;
}
line += 'generation';
line += ' ';
line += cand.hasOwnAttribute('generation') ? cand.generation : '0';
return line;
},
parse_ssrc: function (desc) {
// proprietary mapping of a=ssrc lines
// TODO: see "Jingle RTP Source Description" by Juberti and P. Thatcher on google docs
// and parse according to that
var lines = desc.split('\r\n'),
data = {};
for (var i = 0; i < lines.length; i++) {
if (lines[i].substring(0, 7) == 'a=ssrc:') {
var idx = lines[i].indexOf(' ');
data[lines[i].substr(idx + 1).split(':', 2)[0]] = lines[i].substr(idx + 1).split(':', 2)[1];
}
}
return data;
},
parse_rtcpfb: function (line) {
var parts = line.substr(10).split(' ');
var data = {};
data.pt = parts.shift();
data.type = parts.shift();
data.params = parts;
return data;
},
parse_extmap: function (line) {
var parts = line.substr(9).split(' ');
var data = {};
data.value = parts.shift();
if (data.value.indexOf('/') != -1) {
data.direction = data.value.substr(data.value.indexOf('/') + 1);
data.value = data.value.substr(0, data.value.indexOf('/'));
} else {
data.direction = 'both';
}
data.uri = parts.shift();
data.params = parts;
return data;
},
find_line: function (haystack, needle, sessionpart) {
var lines = haystack.split('\r\n');
for (var i = 0; i < lines.length; i++) {
if (lines[i].substring(0, needle.length) == needle) {
return lines[i];
}
}
if (!sessionpart) {
return false;
}
// search session part
lines = sessionpart.split('\r\n');
for (var j = 0; j < lines.length; j++) {
if (lines[j].substring(0, needle.length) == needle) {
return lines[j];
}
}
return false;
},
find_lines: function (haystack, needle, sessionpart) {
var lines = haystack.split('\r\n'),
needles = [];
for (var i = 0; i < lines.length; i++) {
if (lines[i].substring(0, needle.length) == needle)
needles.push(lines[i]);
}
if (needles.length || !sessionpart) {
return needles;
}
// search session part
lines = sessionpart.split('\r\n');
for (var j = 0; j < lines.length; j++) {
if (lines[j].substring(0, needle.length) == needle) {
needles.push(lines[j]);
}
}
return needles;
},
candidateToJingle: function (line) {
// a=candidate:2979166662 1 udp 2113937151 192.168.2.100 57698 typ host generation 0
// <candidate component=... foundation=... generation=... id=... ip=... network=... port=... priority=... protocol=... type=.../>
if (line.substring(0, 12) != 'a=candidate:') {
console.log('parseCandidate called with a line that is not a candidate line');
console.log(line);
return null;
}
if (line.substring(line.length - 2) == '\r\n') // chomp it
line = line.substring(0, line.length - 2);
var candidate = {},
elems = line.split(' '),
i;
if (elems[6] != 'typ') {
console.log('did not find typ in the right place');
console.log(line);
return null;
}
candidate.foundation = elems[0].substring(12);
candidate.component = elems[1];
candidate.protocol = elems[2].toLowerCase();
candidate.priority = elems[3];
candidate.ip = elems[4];
candidate.port = elems[5];
// elems[6] => "typ"
candidate.type = elems[7];
for (i = 8; i < elems.length; i += 2) {
switch (elems[i]) {
case 'raddr':
candidate['rel-addr'] = elems[i + 1];
break;
case 'rport':
candidate['rel-port'] = elems[i + 1];
break;
case 'generation':
candidate.generation = elems[i + 1];
break;
default: // TODO
console.log('not translating "' + elems[i] + '" = "' + elems[i + 1] + '"');
}
}
candidate.network = '1';
candidate.id = Math.random().toString(36).substr(2, 10); // not applicable to SDP -- FIXME: should be unique, not just random
return candidate;
},
candidateFromJingle: function (cand) {
var line = 'a=candidate:';
line += cand.getAttribute('foundation');
line += ' ';
line += cand.getAttribute('component');
line += ' ';
line += cand.getAttribute('protocol'); //.toUpperCase(); // chrome M23 doesn't like this
line += ' ';
line += cand.getAttribute('priority');
line += ' ';
line += cand.getAttribute('ip');
line += ' ';
line += cand.getAttribute('port');
line += ' ';
line += 'typ';
line += ' ' + cand.getAttribute('type');
line += ' ';
switch (cand.getAttribute('type')) {
case 'srflx':
case 'prflx':
case 'relay':
if (cand.getAttribute('rel-addr') && cand.getAttribute('rel-port')) {
line += 'raddr';
line += ' ';
line += cand.getAttribute('rel-addr');
line += ' ';
line += 'rport';
line += ' ';
line += cand.getAttribute('rel-port');
line += ' ';
}
break;
}
line += 'generation';
line += ' ';
line += cand.getAttribute('generation') || '0';
return line + '\r\n';
}
};
}(jQuery));
@@ -1,859 +0,0 @@
/* jshint -W117 */
// Jingle stuff
var JingleSession;
(function($){
JingleSession = function(me, sid, connection) {
this.me = me;
this.sid = sid;
this.connection = connection;
this.initiator = null;
this.responder = null;
this.isInitiator = null;
this.peerjid = null;
this.state = null;
this.peerconnection = null;
this.remoteStream = null;
this.localSDP = null;
this.remoteSDP = null;
this.localStreams = [];
this.relayedStreams = [];
this.remoteStreams = [];
this.startTime = null;
this.stopTime = null;
this.media_constraints = null;
this.pc_constraints = null;
this.ice_config = {},
this.drip_container = [];
this.usetrickle = true;
this.usepranswer = false; // early transport warmup -- mind you, this might fail. depends on webrtc issue 1718
this.usedrip = false; // dripping is sending trickle candidates not one-by-one
this.hadstuncandidate = false;
this.hadturncandidate = false;
this.lasticecandidate = false;
this.statsinterval = null;
this.reason = null;
this.addssrc = [];
this.removessrc = [];
this.wait = true;
}
JingleSession.prototype.initiate = function (peerjid, isInitiator) {
var self = this;
if (this.state !== null) {
console.error('attempt to initiate on session ' + this.sid +
'in state ' + this.state);
return;
}
this.isInitiator = isInitiator;
this.state = 'pending';
this.initiator = isInitiator ? this.me : peerjid;
this.responder = !isInitiator ? this.me : peerjid;
this.peerjid = peerjid;
//console.log('create PeerConnection ' + JSON.stringify(this.ice_config));
try {
this.peerconnection = new RTCPeerconnection(this.ice_config,
this.pc_constraints);
} catch (e) {
console.error('Failed to create PeerConnection, exception: ',
e.message);
console.error(e);
return;
}
this.hadstuncandidate = false;
this.hadturncandidate = false;
this.lasticecandidate = false;
this.peerconnection.onicecandidate = function (event) {
self.sendIceCandidate(event.candidate);
};
this.peerconnection.onaddstream = function (event) {
self.remoteStream = event.stream;
self.remoteStreams.push(event.stream);
$(document).trigger('remotestreamadded.jingle', [event, self.sid]);
};
this.peerconnection.onremovestream = function (event) {
self.remoteStream = null;
// FIXME: remove from this.remoteStreams
$(document).trigger('remotestreamremoved.jingle', [event, self.sid]);
};
this.peerconnection.onsignalingstatechange = function (event) {
if (!(self && self.peerconnection)) return;
};
this.peerconnection.oniceconnectionstatechange = function (event) {
if (!(self && self.peerconnection)) return;
switch (self.peerconnection.iceConnectionState) {
case 'connected':
this.startTime = new Date();
break;
case 'disconnected':
this.stopTime = new Date();
break;
}
$(document).trigger('iceconnectionstatechange.jingle', [self.sid, self]);
};
// add any local and relayed stream
this.localStreams.forEach(function(stream) {
self.peerconnection.addStream(stream);
});
this.relayedStreams.forEach(function(stream) {
self.peerconnection.addStream(stream);
});
};
JingleSession.prototype.accept = function () {
var self = this;
this.state = 'active';
var pranswer = this.peerconnection.localDescription;
if (!pranswer || pranswer.type != 'pranswer') {
return;
}
console.log('going from pranswer to answer');
if (this.usetrickle) {
// remove candidates already sent from session-accept
var lines = SDPUtil.find_lines(pranswer.sdp, 'a=candidate:');
for (var i = 0; i < lines.length; i++) {
pranswer.sdp = pranswer.sdp.replace(lines[i] + '\r\n', '');
}
}
while (SDPUtil.find_line(pranswer.sdp, 'a=inactive')) {
// FIXME: change any inactive to sendrecv or whatever they were originally
pranswer.sdp = pranswer.sdp.replace('a=inactive', 'a=sendrecv');
}
var prsdp = new SDP(pranswer.sdp);
var accept = $iq({to: this.peerjid,
type: 'set'})
.c('jingle', {xmlns: 'urn:xmpp:jingle:1',
action: 'session-accept',
initiator: this.initiator,
responder: this.responder,
sid: this.sid });
prsdp.toJingle(accept, this.initiator == this.me ? 'initiator' : 'responder');
this.connection.sendIQ(accept,
function () {
var ack = {};
ack.source = 'answer';
$(document).trigger('ack.jingle', [self.sid, ack]);
},
function (stanza) {
var error = ($(stanza).find('error').length) ? {
code: $(stanza).find('error').attr('code'),
reason: $(stanza).find('error :first')[0].tagName,
}:{};
error.source = 'answer';
$(document).trigger('error.jingle', [self.sid, error]);
},
10000);
var sdp = this.peerconnection.localDescription.sdp;
while (SDPUtil.find_line(sdp, 'a=inactive')) {
// FIXME: change any inactive to sendrecv or whatever they were originally
sdp = sdp.replace('a=inactive', 'a=sendrecv');
}
this.peerconnection.setLocalDescription(new RTCSessionDescription({type: 'answer', sdp: sdp}),
function () {
//console.log('setLocalDescription success');
},
function (e) {
console.error('setLocalDescription failed', e);
}
);
};
JingleSession.prototype.terminate = function (reason) {
this.state = 'ended';
this.reason = reason;
this.peerconnection.close();
if (this.statsinterval !== null) {
window.clearInterval(this.statsinterval);
this.statsinterval = null;
}
};
JingleSession.prototype.active = function () {
return this.state == 'active';
};
JingleSession.prototype.sendIceCandidate = function (candidate) {
var self = this;
if (candidate && !this.lasticecandidate) {
var ice = SDPUtil.iceparams(this.localSDP.media[candidate.sdpMLineIndex], this.localSDP.session);
var jcand = SDPUtil.candidateToJingle(candidate.candidate);
if (!(ice && jcand)) {
console.error('failed to get ice && jcand');
return;
}
ice.xmlns = 'urn:xmpp:jingle:transports:ice-udp:1';
if (jcand.type === 'srflx') {
this.hadstuncandidate = true;
} else if (jcand.type === 'relay') {
this.hadturncandidate = true;
}
if (this.usetrickle) {
if (this.usedrip) {
if (this.drip_container.length === 0) {
// start 10ms callout
window.setTimeout(function () {
if (self.drip_container.length === 0) return;
var allcands = self.drip_container;
self.drip_container = [];
var cand = $iq({to: self.peerjid, type: 'set'})
.c('jingle', {xmlns: 'urn:xmpp:jingle:1',
action: 'transport-info',
initiator: self.initiator,
sid: self.sid});
for (var mid = 0; mid < self.localSDP.media.length; mid++) {
var cands = allcands.filter(function (el) { return el.sdpMLineIndex == mid; });
if (cands.length > 0) {
var ice = SDPUtil.iceparams(self.localSDP.media[mid], self.localSDP.session);
ice.xmlns = 'urn:xmpp:jingle:transports:ice-udp:1';
cand.c('content', {creator: self.initiator == self.me ? 'initiator' : 'responder',
name: cands[0].sdpMid
}).c('transport', ice);
for (var i = 0; i < cands.length; i++) {
cand.c('candidate', SDPUtil.candidateToJingle(cands[i].candidate)).up();
}
// add fingerprint
if (SDPUtil.find_line(self.localSDP.media[mid], 'a=fingerprint:', self.localSDP.session)) {
var tmp = SDPUtil.parse_fingerprint(SDPUtil.find_line(self.localSDP.media[mid], 'a=fingerprint:', self.localSDP.session));
tmp.required = true;
cand.c('fingerprint').t(tmp.fingerprint);
delete tmp.fingerprint;
cand.attrs(tmp);
cand.up();
}
cand.up(); // transport
cand.up(); // content
}
}
// might merge last-candidate notification into this, but it is called alot later. See webrtc issue #2340
//console.log('was this the last candidate', self.lasticecandidate);
self.connection.sendIQ(cand,
function () {
var ack = {};
ack.source = 'transportinfo';
$(document).trigger('ack.jingle', [self.sid, ack]);
},
function (stanza) {
var error = ($(stanza).find('error').length) ? {
code: $(stanza).find('error').attr('code'),
reason: $(stanza).find('error :first')[0].tagName,
}:{};
error.source = 'transportinfo';
$(document).trigger('error.jingle', [self.sid, error]);
},
10000);
}, 10);
}
this.drip_container.push(event.candidate);
return;
}
// map to transport-info
var cand = $iq({to: this.peerjid, type: 'set'})
.c('jingle', {xmlns: 'urn:xmpp:jingle:1',
action: 'transport-info',
initiator: this.initiator,
sid: this.sid})
.c('content', {creator: this.initiator == this.me ? 'initiator' : 'responder',
name: candidate.sdpMid
})
.c('transport', ice)
.c('candidate', jcand);
cand.up();
// add fingerprint
if (SDPUtil.find_line(this.localSDP.media[candidate.sdpMLineIndex], 'a=fingerprint:', this.localSDP.session)) {
var tmp = SDPUtil.parse_fingerprint(SDPUtil.find_line(this.localSDP.media[candidate.sdpMLineIndex], 'a=fingerprint:', this.localSDP.session));
tmp.required = true;
cand.c('fingerprint').t(tmp.fingerprint);
delete tmp.fingerprint;
cand.attrs(tmp);
cand.up();
}
this.connection.sendIQ(cand,
function () {
var ack = {};
ack.source = 'transportinfo';
$(document).trigger('ack.jingle', [self.sid, ack]);
},
function (stanza) {
console.error('transport info error');
var error = ($(stanza).find('error').length) ? {
code: $(stanza).find('error').attr('code'),
reason: $(stanza).find('error :first')[0].tagName,
}:{};
error.source = 'transportinfo';
$(document).trigger('error.jingle', [self.sid, error]);
},
10000);
}
} else {
//console.log('sendIceCandidate: last candidate.');
if (!this.usetrickle) {
//console.log('should send full offer now...');
var init = $iq({to: this.peerjid,
type: 'set'})
.c('jingle', {xmlns: 'urn:xmpp:jingle:1',
action: this.peerconnection.localDescription.type == 'offer' ? 'session-initiate' : 'session-accept',
initiator: this.initiator,
sid: this.sid});
this.localSDP = new SDP(this.peerconnection.localDescription.sdp);
this.localSDP.toJingle(init, this.initiator == this.me ? 'initiator' : 'responder');
this.connection.sendIQ(init,
function () {
//console.log('session initiate ack');
var ack = {};
ack.source = 'offer';
$(document).trigger('ack.jingle', [self.sid, ack]);
},
function (stanza) {
self.state = 'error';
self.peerconnection.close();
var error = ($(stanza).find('error').length) ? {
code: $(stanza).find('error').attr('code'),
reason: $(stanza).find('error :first')[0].tagName,
}:{};
error.source = 'offer';
$(document).trigger('error.jingle', [self.sid, error]);
},
10000);
}
this.lasticecandidate = true;
console.log('Have we encountered any srflx candidates? ' + this.hadstuncandidate);
console.log('Have we encountered any relay candidates? ' + this.hadturncandidate);
if (!(this.hadstuncandidate || this.hadturncandidate) && this.peerconnection.signalingState != 'closed') {
$(document).trigger('nostuncandidates.jingle', [this.sid]);
}
}
};
JingleSession.prototype.sendOffer = function () {
//console.log('sendOffer...');
var self = this;
this.peerconnection.createOffer(function (sdp) {
self.createdOffer(sdp);
},
function (e) {
console.error('createOffer failed', e);
},
this.media_constraints
);
};
JingleSession.prototype.createdOffer = function (sdp) {
//console.log('createdOffer', sdp);
var self = this;
this.localSDP = new SDP(sdp.sdp);
//this.localSDP.mangle();
if (this.usetrickle) {
var init = $iq({to: this.peerjid,
type: 'set'})
.c('jingle', {xmlns: 'urn:xmpp:jingle:1',
action: 'session-initiate',
initiator: this.initiator,
sid: this.sid});
this.localSDP.toJingle(init, this.initiator == this.me ? 'initiator' : 'responder');
this.connection.sendIQ(init,
function () {
var ack = {};
ack.source = 'offer';
$(document).trigger('ack.jingle', [self.sid, ack]);
},
function (stanza) {
self.state = 'error';
self.peerconnection.close();
var error = ($(stanza).find('error').length) ? {
code: $(stanza).find('error').attr('code'),
reason: $(stanza).find('error :first')[0].tagName,
}:{};
error.source = 'offer';
$(document).trigger('error.jingle', [self.sid, error]);
},
10000);
}
sdp.sdp = this.localSDP.raw;
this.peerconnection.setLocalDescription(sdp,
function () {
//console.log('setLocalDescription success');
},
function (e) {
console.error('setLocalDescription failed', e);
}
);
var cands = SDPUtil.find_lines(this.localSDP.raw, 'a=candidate:');
for (var i = 0; i < cands.length; i++) {
var cand = SDPUtil.parse_icecandidate(cands[i]);
if (cand.type == 'srflx') {
this.hadstuncandidate = true;
} else if (cand.type == 'relay') {
this.hadturncandidate = true;
}
}
};
JingleSession.prototype.setRemoteDescription = function (elem, desctype) {
//console.log('setting remote description... ', desctype);
this.remoteSDP = new SDP('');
this.remoteSDP.fromJingle(elem);
if (this.peerconnection.remoteDescription !== null) {
console.log('setRemoteDescription when remote description is not null, should be pranswer', this.peerconnection.remoteDescription);
if (this.peerconnection.remoteDescription.type == 'pranswer') {
var pranswer = new SDP(this.peerconnection.remoteDescription.sdp);
for (var i = 0; i < pranswer.media.length; i++) {
// make sure we have ice ufrag and pwd
if (!SDPUtil.find_line(this.remoteSDP.media[i], 'a=ice-ufrag:', this.remoteSDP.session)) {
if (SDPUtil.find_line(pranswer.media[i], 'a=ice-ufrag:', pranswer.session)) {
this.remoteSDP.media[i] += SDPUtil.find_line(pranswer.media[i], 'a=ice-ufrag:', pranswer.session) + '\r\n';
} else {
console.warn('no ice ufrag?');
}
if (SDPUtil.find_line(pranswer.media[i], 'a=ice-pwd:', pranswer.session)) {
this.remoteSDP.media[i] += SDPUtil.find_line(pranswer.media[i], 'a=ice-pwd:', pranswer.session) + '\r\n';
} else {
console.warn('no ice pwd?');
}
}
// copy over candidates
var lines = SDPUtil.find_lines(pranswer.media[i], 'a=candidate:');
for (var j = 0; j < lines.length; j++) {
this.remoteSDP.media[i] += lines[j] + '\r\n';
}
}
this.remoteSDP.raw = this.remoteSDP.session + this.remoteSDP.media.join('');
}
}
var remotedesc = new RTCSessionDescription({type: desctype, sdp: this.remoteSDP.raw});
this.peerconnection.setRemoteDescription(remotedesc,
function () {
//console.log('setRemoteDescription success');
},
function (e) {
console.error('setRemoteDescription error', e);
}
);
};
JingleSession.prototype.addIceCandidate = function (elem) {
var self = this;
if (this.peerconnection.signalingState == 'closed') {
return;
}
if (!this.peerconnection.remoteDescription && this.peerconnection.signalingState == 'have-local-offer') {
console.log('trickle ice candidate arriving before session accept...');
// create a PRANSWER for setRemoteDescription
if (!this.remoteSDP) {
var cobbled = 'v=0\r\n' +
'o=- ' + '1923518516' + ' 2 IN IP4 0.0.0.0\r\n' +// FIXME
's=-\r\n' +
't=0 0\r\n';
// first, take some things from the local description
for (var i = 0; i < this.localSDP.media.length; i++) {
cobbled += SDPUtil.find_line(this.localSDP.media[i], 'm=') + '\r\n';
cobbled += SDPUtil.find_lines(this.localSDP.media[i], 'a=rtpmap:').join('\r\n') + '\r\n';
if (SDPUtil.find_line(this.localSDP.media[i], 'a=mid:')) {
cobbled += SDPUtil.find_line(this.localSDP.media[i], 'a=mid:') + '\r\n';
}
cobbled += 'a=inactive\r\n';
}
this.remoteSDP = new SDP(cobbled);
}
// then add things like ice and dtls from remote candidate
elem.each(function () {
for (var i = 0; i < self.remoteSDP.media.length; i++) {
if (SDPUtil.find_line(self.remoteSDP.media[i], 'a=mid:' + $(this).attr('name')) ||
self.remoteSDP.media[i].indexOf('m=' + $(this).attr('name')) === 0) {
if (!SDPUtil.find_line(self.remoteSDP.media[i], 'a=ice-ufrag:')) {
var tmp = $(this).find('transport');
self.remoteSDP.media[i] += 'a=ice-ufrag:' + tmp.attr('ufrag') + '\r\n';
self.remoteSDP.media[i] += 'a=ice-pwd:' + tmp.attr('pwd') + '\r\n';
tmp = $(this).find('transport>fingerprint');
if (tmp.length) {
self.remoteSDP.media[i] += 'a=fingerprint:' + tmp.attr('hash') + ' ' + tmp.text() + '\r\n';
} else {
console.log('no dtls fingerprint (webrtc issue #1718?)');
self.remoteSDP.media[i] += 'a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:BAADBAADBAADBAADBAADBAADBAADBAADBAADBAAD\r\n';
}
break;
}
}
}
});
this.remoteSDP.raw = this.remoteSDP.session + this.remoteSDP.media.join('');
// we need a complete SDP with ice-ufrag/ice-pwd in all parts
// this makes the assumption that the PRANSWER is constructed such that the ice-ufrag is in all mediaparts
// but it could be in the session part as well. since the code above constructs this sdp this can't happen however
var iscomplete = this.remoteSDP.media.filter(function (mediapart) {
return SDPUtil.find_line(mediapart, 'a=ice-ufrag:');
}).length == this.remoteSDP.media.length;
if (iscomplete) {
console.log('setting pranswer');
try {
this.peerconnection.setRemoteDescription(new RTCSessionDescription({type: 'pranswer', sdp: this.remoteSDP.raw }),
function() {
},
function(e) {
console.log('setRemoteDescription pranswer failed', e.toString());
});
} catch (e) {
console.error('setting pranswer failed', e);
}
} else {
//console.log('not yet setting pranswer');
}
}
// operate on each content element
elem.each(function () {
// would love to deactivate this, but firefox still requires it
var idx = -1;
var i;
for (i = 0; i < self.remoteSDP.media.length; i++) {
if (SDPUtil.find_line(self.remoteSDP.media[i], 'a=mid:' + $(this).attr('name')) ||
self.remoteSDP.media[i].indexOf('m=' + $(this).attr('name')) === 0) {
idx = i;
break;
}
}
if (idx == -1) { // fall back to localdescription
for (i = 0; i < self.localSDP.media.length; i++) {
if (SDPUtil.find_line(self.localSDP.media[i], 'a=mid:' + $(this).attr('name')) ||
self.localSDP.media[i].indexOf('m=' + $(this).attr('name')) === 0) {
idx = i;
break;
}
}
}
var name = $(this).attr('name');
// TODO: check ice-pwd and ice-ufrag?
$(this).find('transport>candidate').each(function () {
var line, candidate;
line = SDPUtil.candidateFromJingle(this);
candidate = new RTCIceCandidate({sdpMLineIndex: idx,
sdpMid: name,
candidate: line});
try {
self.peerconnection.addIceCandidate(candidate);
} catch (e) {
console.error('addIceCandidate failed', e.toString(), line);
}
});
});
};
JingleSession.prototype.sendAnswer = function (provisional) {
//console.log('createAnswer', provisional);
var self = this;
this.peerconnection.createAnswer(
function (sdp) {
self.createdAnswer(sdp, provisional);
},
function (e) {
console.error('createAnswer failed', e);
},
this.media_constraints
);
};
JingleSession.prototype.createdAnswer = function (sdp, provisional) {
//console.log('createAnswer callback');
console.log(sdp);
var self = this;
this.localSDP = new SDP(sdp.sdp);
//this.localSDP.mangle();
this.usepranswer = provisional === true;
if (this.usetrickle) {
if (!this.usepranswer) {
var accept = $iq({to: this.peerjid,
type: 'set'})
.c('jingle', {xmlns: 'urn:xmpp:jingle:1',
action: 'session-accept',
initiator: this.initiator,
responder: this.responder,
sid: this.sid });
this.localSDP.toJingle(accept, this.initiator == this.me ? 'initiator' : 'responder');
this.connection.sendIQ(accept,
function () {
var ack = {};
ack.source = 'answer';
$(document).trigger('ack.jingle', [self.sid, ack]);
},
function (stanza) {
var error = ($(stanza).find('error').length) ? {
code: $(stanza).find('error').attr('code'),
reason: $(stanza).find('error :first')[0].tagName,
}:{};
error.source = 'answer';
$(document).trigger('error.jingle', [self.sid, error]);
},
10000);
} else {
sdp.type = 'pranswer';
for (var i = 0; i < this.localSDP.media.length; i++) {
this.localSDP.media[i] = this.localSDP.media[i].replace('a=sendrecv\r\n', 'a=inactive\r\n');
}
this.localSDP.raw = this.localSDP.session + '\r\n' + this.localSDP.media.join('');
}
}
sdp.sdp = this.localSDP.raw;
this.peerconnection.setLocalDescription(sdp,
function () {
//console.log('setLocalDescription success');
},
function (e) {
console.error('setLocalDescription failed', e);
}
);
var cands = SDPUtil.find_lines(this.localSDP.raw, 'a=candidate:');
for (var j = 0; j < cands.length; j++) {
var cand = SDPUtil.parse_icecandidate(cands[j]);
if (cand.type == 'srflx') {
this.hadstuncandidate = true;
} else if (cand.type == 'relay') {
this.hadturncandidate = true;
}
}
};
JingleSession.prototype.sendTerminate = function (reason, text) {
var self = this,
term = $iq({to: this.peerjid,
type: 'set'})
.c('jingle', {xmlns: 'urn:xmpp:jingle:1',
action: 'session-terminate',
initiator: this.initiator,
sid: this.sid})
.c('reason')
.c(reason || 'success');
if (text) {
term.up().c('text').t(text);
}
this.connection.sendIQ(term,
function () {
self.peerconnection.close();
self.peerconnection = null;
self.terminate();
var ack = {};
ack.source = 'terminate';
$(document).trigger('ack.jingle', [self.sid, ack]);
},
function (stanza) {
var error = ($(stanza).find('error').length) ? {
code: $(stanza).find('error').attr('code'),
reason: $(stanza).find('error :first')[0].tagName,
}:{};
$(document).trigger('ack.jingle', [self.sid, error]);
},
10000);
if (this.statsinterval !== null) {
window.clearInterval(this.statsinterval);
this.statsinterval = null;
}
};
JingleSession.prototype.addSource = function (elem) {
console.log('addssrc', new Date().getTime());
console.log('ice', this.peerconnection.iceConnectionState);
var sdp = new SDP(this.peerconnection.remoteDescription.sdp);
var self = this;
$(elem).each(function (idx, content) {
var name = $(content).attr('name');
var lines = '';
tmp = $(content).find('>source[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]');
tmp.each(function () {
var ssrc = $(this).attr('ssrc');
$(this).find('>parameter').each(function () {
lines += 'a=ssrc:' + ssrc + ' ' + $(this).attr('name');
if ($(this).attr('value') && $(this).attr('value').length)
lines += ':' + $(this).attr('value');
lines += '\r\n';
});
});
sdp.media.forEach(function(media, idx) {
if (!SDPUtil.find_line(media, 'a=mid:' + name))
return;
sdp.media[idx] += lines;
if (!self.addssrc[idx]) self.addssrc[idx] = '';
self.addssrc[idx] += lines;
});
sdp.raw = sdp.session + sdp.media.join('');
});
this.modifySources();
};
JingleSession.prototype.removeSource = function (elem) {
console.log('removessrc', new Date().getTime());
console.log('ice', this.peerconnection.iceConnectionState);
var sdp = new SDP(this.peerconnection.remoteDescription.sdp);
var self = this;
$(elem).each(function (idx, content) {
var name = $(content).attr('name');
var lines = '';
tmp = $(content).find('>source[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]');
tmp.each(function () {
var ssrc = $(this).attr('ssrc');
$(this).find('>parameter').each(function () {
lines += 'a=ssrc:' + ssrc + ' ' + $(this).attr('name');
if ($(this).attr('value') && $(this).attr('value').length)
lines += ':' + $(this).attr('value');
lines += '\r\n';
});
});
sdp.media.forEach(function(media, idx) {
if (!SDPUtil.find_line(media, 'a=mid:' + name))
return;
sdp.media[idx] += lines;
if (!self.addssrc[idx]) self.removessrc[idx] = '';
self.removessrc[idx] += lines;
});
sdp.raw = sdp.session + sdp.media.join('');
});
this.modifySources();
};
JingleSession.prototype.modifySources = function() {
var self = this;
if (!(this.addssrc.length || this.removessrc.length)) return;
if (this.peerconnection.signalingState == 'closed') return;
if (!(this.peerconnection.signalingState == 'stable' && this.peerconnection.iceConnectionState == 'connected')) {
console.warn('modifySources not yet', this.peerconnection.signalingState, this.peerconnection.iceConnectionState);
this.wait = true;
window.setTimeout(function() { self.modifySources(); }, 250);
return;
}
if (this.wait) {
window.setTimeout(function() { self.modifySources(); }, 2500);
this.wait = false;
return;
}
var sdp = new SDP(this.peerconnection.remoteDescription.sdp);
// add sources
this.addssrc.forEach(function(lines, idx) {
sdp.media[idx] += lines;
});
this.addssrc = [];
// remove sources
this.removessrc.forEach(function(lines, idx) {
lines = lines.split('\r\n');
lines.pop(); // remove empty last element;
lines.forEach(function(line) {
sdp.media[idx] = sdp.media[idx].replace(line + '\r\n', '');
});
});
this.removessrc = [];
sdp.raw = sdp.session + sdp.media.join('');
this.peerconnection.setRemoteDescription(new RTCSessionDescription({type: 'offer', sdp: sdp.raw}),
function() {
self.peerconnection.createAnswer(
function(modifiedAnswer) {
self.peerconnection.setLocalDescription(modifiedAnswer,
function() {
//console.log('modified setLocalDescription ok');
},
function(error) {
console.log('modified setLocalDescription failed');
}
);
},
function(error) {
console.log('modified answer failed');
}
);
},
function(error) {
console.log('modify failed');
}
);
};
JingleSession.prototype.sendMute = function (muted, content) {
var info = $iq({to: this.peerjid,
type: 'set'})
.c('jingle', {xmlns: 'urn:xmpp:jingle:1',
action: 'session-info',
initiator: this.initiator,
sid: this.sid });
info.c(muted ? 'mute' : 'unmute', {xmlns: 'urn:xmpp:jingle:apps:rtp:info:1'});
info.attrs({'creator': this.me == this.initiator ? 'creator' : 'responder'});
if (content) {
info.attrs({'name': content});
}
this.connection.send(info);
};
JingleSession.prototype.sendRinging = function () {
var info = $iq({to: this.peerjid,
type: 'set'})
.c('jingle', {xmlns: 'urn:xmpp:jingle:1',
action: 'session-info',
initiator: this.initiator,
sid: this.sid });
info.c('ringing', {xmlns: 'urn:xmpp:jingle:apps:rtp:info:1'});
this.connection.send(info);
};
JingleSession.prototype.getStats = function (interval) {
var self = this;
var recv = {audio: 0, video: 0};
var lost = {audio: 0, video: 0};
var lastrecv = {audio: 0, video: 0};
var lastlost = {audio: 0, video: 0};
var loss = {audio: 0, video: 0};
var delta = {audio: 0, video: 0};
this.statsinterval = window.setInterval(function () {
if (self && self.peerconnection && self.peerconnection.getStats) {
self.peerconnection.getStats(function (stats) {
var results = stats.result();
// TODO: there are so much statistics you can get from this..
for (var i = 0; i < results.length; ++i) {
if (results[i].type == 'ssrc') {
var packetsrecv = results[i].stat('packetsReceived');
var packetslost = results[i].stat('packetsLost');
if (packetsrecv && packetslost) {
packetsrecv = parseInt(packetsrecv, 10);
packetslost = parseInt(packetslost, 10);
if (results[i].stat('googFrameRateReceived')) {
lastlost.video = lost.video;
lastrecv.video = recv.video;
recv.video = packetsrecv;
lost.video = packetslost;
} else {
lastlost.audio = lost.audio;
lastrecv.audio = recv.audio;
recv.audio = packetsrecv;
lost.audio = packetslost;
}
}
}
}
delta.audio = recv.audio - lastrecv.audio;
delta.video = recv.video - lastrecv.video;
loss.audio = (delta.audio > 0) ? Math.ceil(100 * (lost.audio - lastlost.audio) / delta.audio) : 0;
loss.video = (delta.video > 0) ? Math.ceil(100 * (lost.video - lastlost.video) / delta.video) : 0;
$(document).trigger('packetloss.jingle', [self.sid, loss]);
});
}
}, interval || 3000);
return this.statsinterval;
};
}(jQuery));
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+7 -6
Ver Arquivo
@@ -3,9 +3,10 @@
* Klaus Herberth, 2014
*/
// This code was written by Tyler Akins and has been placed in the
// public domain. It would be nice if you left this header intact.
// Base64 code from Tyler Akins -- http://rumkin.com
/*! This code was written by Tyler Akins and has been placed in the
public domain. It would be nice if you left this header intact.
Base64 code from Tyler Akins -- http://rumkin.com
*/
var Base64 = (function () {
var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
@@ -84,7 +85,7 @@ var Base64 = (function () {
return obj;
})();
/*
/*!
* A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
* in FIPS PUB 180-1
* Version 2.1a Copyright Paul Johnston 2000 - 2002.
@@ -261,7 +262,7 @@ function binb2b64(binarray)
return str;
}
/*
/*!
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
* Digest Algorithm, as defined in RFC 1321.
* Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
@@ -469,7 +470,7 @@ var MD5 = (function () {
return obj;
})();
/*
/*!
This program is distributed under the terms of the MIT license.
Please see the LICENSE file for details.
+2 -2
Ver Arquivo
@@ -353,7 +353,7 @@ Strophe.addConnectionPlugin('muc', {
}).c("query", {
xmlns: Strophe.NS.MUC_OWNER
});
if (config instanceof Form) {
if (Strophe.x && config instanceof Strophe.x.Form) {
config.type = "submit";
iq.cnode(config.toXML());
} else {
@@ -1017,4 +1017,4 @@ Occupant = (function() {
return Occupant;
})();
})();
+845
Ver Arquivo
@@ -0,0 +1,845 @@
// Generated by CoffeeScript 1.8.0
(function() {
var $field, $form, $item, $opt, Field, Form, Item, Option, helper,
__slice = [].slice,
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
helper = {
fill: function(src, target, klass) {
var f, _i, _len, _results;
_results = [];
for (_i = 0, _len = src.length; _i < _len; _i++) {
f = src[_i];
_results.push(target.push(f instanceof klass ? f : new klass(f)));
}
return _results;
},
createHtmlFieldCouple: function(f) {
var div, id;
div = $("<div>");
id = "Strophe.x.Field-" + f.type + "-" + f["var"];
div.append("<label for='" + id + "'>" + (f.label || '') + "</label>").append($(f.toHTML()).attr("id", id)).append("<br />");
return div.children();
},
getHtmlFields: function(html) {
html = $(html);
return __slice.call(html.find("input")).concat(__slice.call(html.find("select")), __slice.call(html.find("textarea")));
}
};
Form = (function() {
Form._types = ["form", "submit", "cancel", "result"];
function Form(opt) {
this.toHTML = __bind(this.toHTML, this);
this.toJSON = __bind(this.toJSON, this);
this.toXML = __bind(this.toXML, this);
var f, i, _i, _j, _len, _len1, _ref, _ref1, _ref2, _ref3;
this.fields = [];
this.items = [];
this.reported = [];
if (opt) {
if (_ref = opt.type, __indexOf.call(Form._types, _ref) >= 0) {
this.type = opt.type;
}
this.title = opt.title;
this.instructions = opt.instructions;
helper.fill = function(src, target, klass) {
var f, _i, _len, _results;
_results = [];
for (_i = 0, _len = src.length; _i < _len; _i++) {
f = src[_i];
_results.push(target.push(f instanceof klass ? f : new klass(f)));
}
return _results;
};
if (opt.fields) {
if (opt.fields) {
helper.fill(opt.fields, this.fields, Field);
}
} else if (opt.items) {
if (opt.items) {
helper.fill(opt.items, this.items, Item);
}
_ref1 = this.items;
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
i = _ref1[_i];
_ref2 = i.fields;
for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
f = _ref2[_j];
if (!(_ref3 = f["var"], __indexOf.call(this.reported, _ref3) >= 0)) {
this.reported.push(f["var"]);
}
}
}
}
}
}
Form.prototype.type = "form";
Form.prototype.title = null;
Form.prototype.instructions = null;
Form.prototype.toXML = function() {
var f, i, r, xml, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2;
xml = $build("x", {
xmlns: "jabber:x:data",
type: this.type
});
if (this.title) {
xml.c("title").t(this.title.toString()).up();
}
if (this.instructions) {
xml.c("instructions").t(this.instructions.toString()).up();
}
if (this.fields.length > 0) {
_ref = this.fields;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
f = _ref[_i];
xml.cnode(f.toXML()).up();
}
} else if (this.items.length > 0) {
xml.c("reported");
_ref1 = this.reported;
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
r = _ref1[_j];
xml.c("field", {
"var": r
}).up();
}
xml.up();
_ref2 = this.items;
for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
i = _ref2[_k];
xml.cnode(i.toXML()).up();
}
}
return xml.tree();
};
Form.prototype.toJSON = function() {
var f, i, json, _i, _j, _len, _len1, _ref, _ref1;
json = {
type: this.type
};
if (this.title) {
json.title = this.title;
}
if (this.instructions) {
json.instructions = this.instructions;
}
if (this.fields.length > 0) {
json.fields = [];
_ref = this.fields;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
f = _ref[_i];
json.fields.push(f.toJSON());
}
} else if (this.items.length > 0) {
json.items = [];
json.reported = this.reported;
_ref1 = this.items;
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
i = _ref1[_j];
json.items.push(i.toJSON());
}
}
return json;
};
Form.prototype.toHTML = function() {
var f, form, i, _i, _j, _len, _len1, _ref, _ref1;
form = $("<form data-type='" + this.type + "'>");
if (this.title) {
form.append("<h1>" + this.title + "</h1>");
}
if (this.instructions) {
form.append("<p>" + this.instructions + "</p>");
}
if (this.fields.length > 0) {
_ref = this.fields;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
f = _ref[_i];
(helper.createHtmlFieldCouple(f)).appendTo(form);
}
} else if (this.items.length > 0) {
_ref1 = this.items;
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
i = _ref1[_j];
($(i.toHTML())).appendTo(form);
}
}
return form[0];
};
Form.fromXML = function(xml) {
var f, fields, i, instr, items, j, r, reported, title;
xml = $(xml);
f = new Form({
type: xml.attr("type")
});
title = xml.find("title");
if (title.length === 1) {
f.title = title.text();
}
instr = xml.find("instructions");
if (instr.length === 1) {
f.instructions = instr.text();
}
fields = xml.find("field");
items = xml.find("item");
if (items.length > 0) {
f.items = (function() {
var _i, _len, _results;
_results = [];
for (_i = 0, _len = items.length; _i < _len; _i++) {
i = items[_i];
_results.push(Item.fromXML(i));
}
return _results;
})();
} else if (fields.length > 0) {
f.fields = (function() {
var _i, _len, _results;
_results = [];
for (_i = 0, _len = fields.length; _i < _len; _i++) {
j = fields[_i];
_results.push(Field.fromXML(j));
}
return _results;
})();
}
reported = xml.find("reported");
if (reported.length === 1) {
fields = reported.find("field");
f.reported = (function() {
var _i, _len, _results;
_results = [];
for (_i = 0, _len = fields.length; _i < _len; _i++) {
r = fields[_i];
_results.push(($(r)).attr("var"));
}
return _results;
})();
}
return f;
};
Form.fromHTML = function(html) {
var f, field, fields, i, instructions, item, items, j, title, _i, _j, _len, _len1, _ref, _ref1, _ref2;
html = $(html);
f = new Form({
type: html.attr("data-type")
});
title = html.find("h1").text();
if (title) {
f.title = title;
}
instructions = html.find("p").text();
if (instructions) {
f.instructions = instructions;
}
items = html.find("fieldset");
fields = helper.getHtmlFields(html);
if (items.length > 0) {
f.items = (function() {
var _i, _len, _results;
_results = [];
for (_i = 0, _len = items.length; _i < _len; _i++) {
i = items[_i];
_results.push(Item.fromHTML(i));
}
return _results;
})();
_ref = f.items;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
item = _ref[_i];
_ref1 = item.fields;
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
field = _ref1[_j];
if (!(_ref2 = field["var"], __indexOf.call(f.reported, _ref2) >= 0)) {
f.reported.push(field["var"]);
}
}
}
} else if (fields.length > 0) {
f.fields = (function() {
var _k, _len2, _results;
_results = [];
for (_k = 0, _len2 = fields.length; _k < _len2; _k++) {
j = fields[_k];
_results.push(Field.fromHTML(j));
}
return _results;
})();
}
return f;
};
return Form;
})();
Field = (function() {
Field._types = ["boolean", "fixed", "hidden", "jid-multi", "jid-single", "list-multi", "list-single", "text-multi", "text-private", "text-single"];
Field._multiTypes = ["list-multi", "jid-multi", "text-multi", "hidden"];
function Field(opt) {
this.toHTML = __bind(this.toHTML, this);
this.toXML = __bind(this.toXML, this);
this.toJSON = __bind(this.toJSON, this);
this.addOptions = __bind(this.addOptions, this);
this.addOption = __bind(this.addOption, this);
this.addValues = __bind(this.addValues, this);
this.addValue = __bind(this.addValue, this);
var _ref, _ref1;
this.options = [];
this.values = [];
if (opt) {
if (_ref = opt.type, __indexOf.call(Field._types, _ref) >= 0) {
this.type = opt.type.toString();
}
if (opt.desc) {
this.desc = opt.desc.toString();
}
if (opt.label) {
this.label = opt.label.toString();
}
this["var"] = ((_ref1 = opt["var"]) != null ? _ref1.toString() : void 0) || "_no_var_was_defined_";
this.required = opt.required === true || opt.required === "true";
if (opt.options) {
this.addOptions(opt.options);
}
if (opt.value) {
opt.values = [opt.value];
}
if (opt.values) {
this.addValues(opt.values);
}
}
}
Field.prototype.type = "text-single";
Field.prototype.desc = null;
Field.prototype.label = null;
Field.prototype["var"] = "_no_var_was_defined_";
Field.prototype.required = false;
Field.prototype.addValue = function(val) {
return this.addValues([val]);
};
Field.prototype.addValues = function(vals) {
var multi, v, _ref;
multi = (_ref = this.type, __indexOf.call(Field._multiTypes, _ref) >= 0);
if (multi || (!multi && vals.length === 1)) {
this.values = __slice.call(this.values).concat(__slice.call((function() {
var _i, _len, _results;
_results = [];
for (_i = 0, _len = vals.length; _i < _len; _i++) {
v = vals[_i];
_results.push(v.toString());
}
return _results;
})()));
}
return this;
};
Field.prototype.addOption = function(opt) {
return this.addOptions([opt]);
};
Field.prototype.addOptions = function(opts) {
var o;
if (this.type === "list-single" || this.type === "list-multi") {
if (typeof opts[0] !== "object") {
opts = (function() {
var _i, _len, _results;
_results = [];
for (_i = 0, _len = opts.length; _i < _len; _i++) {
o = opts[_i];
_results.push(new Option({
value: o.toString()
}));
}
return _results;
})();
}
helper.fill(opts, this.options, Option);
}
return this;
};
Field.prototype.toJSON = function() {
var json, o, _i, _len, _ref;
json = {
type: this.type,
"var": this["var"],
required: this.required
};
if (this.desc) {
json.desc = this.desc;
}
if (this.label) {
json.label = this.label;
}
if (this.values) {
json.values = this.values;
}
if (this.options) {
json.options = [];
_ref = this.options;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
o = _ref[_i];
json.options.push(o.toJSON());
}
}
return json;
};
Field.prototype.toXML = function() {
var attrs, o, v, xml, _i, _j, _len, _len1, _ref, _ref1;
attrs = {
type: this.type,
"var": this["var"]
};
if (this.label) {
attrs.label = this.label;
}
xml = $build("field", attrs);
if (this.desc) {
xml.c("desc").t(this.desc).up();
}
if (this.required) {
xml.c("required").up();
}
if (this.values) {
_ref = this.values;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
v = _ref[_i];
xml.c("value").t(v.toString()).up();
}
}
if (this.options) {
_ref1 = this.options;
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
o = _ref1[_j];
xml.cnode(o.toXML()).up();
}
}
return xml.tree();
};
Field.prototype.toHTML = function() {
var el, k, line, o, opt, txt, val, _i, _j, _len, _len1, _ref, _ref1, _ref2;
switch (this.type.toLowerCase()) {
case 'list-single':
case 'list-multi':
el = $("<select>");
if (this.type === 'list-multi') {
el.attr('multiple', 'multiple');
}
if (this.options.length > 0) {
_ref = this.options;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
opt = _ref[_i];
if (!(opt)) {
continue;
}
o = $(opt.toHTML());
_ref1 = this.values;
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
k = _ref1[_j];
if (k.toString() === opt.value.toString()) {
o.attr('selected', 'selected');
}
}
o.appendTo(el);
}
}
break;
case 'text-multi':
case 'jid-multi':
el = $("<textarea>");
txt = ((function() {
var _k, _len2, _ref2, _results;
_ref2 = this.values;
_results = [];
for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
line = _ref2[_k];
_results.push(line);
}
return _results;
}).call(this)).join('\n');
if (txt) {
el.text(txt);
}
break;
case 'text-single':
case 'boolean':
case 'text-private':
case 'hidden':
case 'fixed':
case 'jid-single':
el = $("<input>");
if (this.values) {
el.val(this.values[0]);
}
switch (this.type.toLowerCase()) {
case 'text-single':
el.attr('type', 'text');
el.attr('placeholder', this.desc);
break;
case 'boolean':
el.attr('type', 'checkbox');
val = (_ref2 = this.values[0]) != null ? typeof _ref2.toString === "function" ? _ref2.toString() : void 0 : void 0;
if (val && (val === "true" || val === "1")) {
el.attr('checked', 'checked');
}
break;
case 'text-private':
el.attr('type', 'password');
break;
case 'hidden':
el.attr('type', 'hidden');
break;
case 'fixed':
el.attr('type', 'text').attr('readonly', 'readonly');
break;
case 'jid-single':
el.attr('type', 'email');
}
break;
default:
el = $("<input type='text'>");
}
el.attr('name', this["var"]);
if (this.required) {
el.attr('required', this.required);
}
return el[0];
};
Field.fromXML = function(xml) {
var o, v;
xml = $(xml);
return new Field({
type: xml.attr("type"),
"var": xml.attr("var"),
label: xml.attr("label"),
desc: xml.find("desc").text(),
required: xml.find("required").length === 1,
values: (function() {
var _i, _len, _ref, _results;
_ref = xml.find(">value");
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
v = _ref[_i];
_results.push(($(v)).text());
}
return _results;
})(),
options: (function() {
var _i, _len, _ref, _results;
_ref = xml.find("option");
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
o = _ref[_i];
_results.push(Option.fromXML(o));
}
return _results;
})()
});
};
Field._htmlElementToFieldType = function(el) {
var r, type;
el = $(el);
switch (el[0].nodeName.toLowerCase()) {
case "textarea":
type = "text-multi";
break;
case "select":
if (el.attr("multiple") === "multiple") {
type = "list-multi";
} else {
type = "list-single";
}
break;
case "input":
switch (el.attr("type")) {
case "checkbox":
type = "boolean";
break;
case "email":
type = "jid-single";
break;
case "hidden":
type = "hidden";
break;
case "password":
type = "text-private";
break;
case "text":
r = el.attr("readonly") === "readonly";
if (r) {
type = "fixed";
} else {
type = "text-single";
}
}
}
return type;
};
Field.fromHTML = function(html) {
var el, f, txt, type;
html = $(html);
type = Field._htmlElementToFieldType(html);
f = new Field({
type: type,
"var": html.attr("name"),
required: html.attr("required") === "required"
});
switch (type) {
case "list-multi":
case "list-single":
f.values = (function() {
var _i, _len, _ref, _results;
_ref = html.find("option:selected");
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
el = _ref[_i];
_results.push(($(el)).val());
}
return _results;
})();
f.options = (function() {
var _i, _len, _ref, _results;
_ref = html.find("option");
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
el = _ref[_i];
_results.push(Option.fromHTML(el));
}
return _results;
})();
break;
case "text-multi":
case "jid-multi":
txt = html.text();
if (txt.trim() !== "") {
f.values = txt.split('\n');
}
break;
case 'text-single':
case 'boolean':
case 'text-private':
case 'hidden':
case 'fixed':
case 'jid-single':
if (html.val().trim() !== "") {
f.values = [html.val()];
}
}
return f;
};
return Field;
})();
Option = (function() {
function Option(opt) {
this.toHTML = __bind(this.toHTML, this);
this.toJSON = __bind(this.toJSON, this);
this.toXML = __bind(this.toXML, this);
if (opt) {
if (opt.label) {
this.label = opt.label.toString();
}
if (opt.value) {
this.value = opt.value.toString();
}
}
}
Option.prototype.label = "";
Option.prototype.value = "";
Option.prototype.toXML = function() {
return $build("option", {
label: this.label
}).c("value").t(this.value.toString()).tree();
};
Option.prototype.toJSON = function() {
return {
label: this.label,
value: this.value
};
};
Option.prototype.toHTML = function() {
return ($("<option>")).attr('value', this.value).text(this.label || this.value)[0];
};
Option.fromXML = function(xml) {
return new Option({
label: ($(xml)).attr("label"),
value: ($(xml)).text()
});
};
Option.fromHTML = function(html) {
return new Option({
value: ($(html)).attr("value"),
label: ($(html)).text()
});
};
return Option;
})();
Item = (function() {
function Item(opts) {
this.toHTML = __bind(this.toHTML, this);
this.toJSON = __bind(this.toJSON, this);
this.toXML = __bind(this.toXML, this);
this.fields = [];
if (opts != null ? opts.fields : void 0) {
helper.fill(opts.fields, this.fields, Field);
}
}
Item.prototype.toXML = function() {
var f, xml, _i, _len, _ref;
xml = $build("item");
_ref = this.fields;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
f = _ref[_i];
xml.cnode(f.toXML()).up();
}
return xml.tree();
};
Item.prototype.toJSON = function() {
var f, json, _i, _len, _ref;
json = {};
if (this.fields) {
json.fields = [];
_ref = this.fields;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
f = _ref[_i];
json.fields.push(f.toJSON());
}
}
return json;
};
Item.prototype.toHTML = function() {
var f, fieldset, _i, _len, _ref;
fieldset = $("<fieldset>");
_ref = this.fields;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
f = _ref[_i];
(helper.createHtmlFieldCouple(f)).appendTo(fieldset);
}
return fieldset[0];
};
Item.fromXML = function(xml) {
var f, fields;
xml = $(xml);
fields = xml.find("field");
return new Item({
fields: (function() {
var _i, _len, _results;
_results = [];
for (_i = 0, _len = fields.length; _i < _len; _i++) {
f = fields[_i];
_results.push(Field.fromXML(f));
}
return _results;
})()
});
};
Item.fromHTML = function(html) {
var f;
return new Item({
fields: (function() {
var _i, _len, _ref, _results;
_ref = helper.getHtmlFields(html);
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
f = _ref[_i];
_results.push(Field.fromHTML(f));
}
return _results;
})()
});
};
return Item;
})();
Strophe.x = {
Form: Form,
Field: Field,
Option: Option,
Item: Item
};
$form = function(opt) {
return new Strophe.x.Form(opt);
};
$field = function(opt) {
return new Strophe.x.Field(opt);
};
$opt = function(opt) {
return new Strophe.x.Option(opt);
};
$item = function(opts) {
return new Strophe.x.Item(opts);
};
Strophe.addConnectionPlugin('x', {
init: function(conn) {
var _ref, _ref1;
Strophe.addNamespace('DATA', 'jabber:x:data');
if (((_ref = conn.disco) != null ? _ref.addFeature : void 0) != null) {
conn.disco.addFeature(Strophe.NS.DATA);
}
if (((_ref1 = conn.disco) != null ? _ref1.addNode : void 0) != null) {
return conn.disco.addNode(Strophe.NS.DATA, {
items: []
});
}
},
parseFromResult: function(result) {
var _ref;
if (result.nodeName.toLowerCase() === "x") {
return Form.fromXML(result);
} else {
return Form.fromXML((_ref = ($(result)).find("x")) != null ? _ref[0] : void 0);
}
}
});
}).call(this);
Diff do arquivo suprimido porque uma ou mais linhas são muito longas
Arquivo binário não exibido.
Arquivo binário não exibido.
+11
Ver Arquivo
@@ -0,0 +1,11 @@
Rotary-Phone6.mp3
===
Creator: David English
Source: http://www.beepzoid.com/old-phones/
License: unknown
Ping1.mp3
===
Creator: CameronMusic
Source: https://soundcloud.com/freefilmandgamemusic/ping-1?in=freefilmandgamemusic/sets/free-notification-sounds-and
License: cc 3.0, http://creativecommons.org/licenses/by/3.0/
Arquivo binário não exibido.
+104
Ver Arquivo
@@ -0,0 +1,104 @@
[
{
"name": "strophe.js",
"file": "lib/strophe.js",
"license": "multiple",
"url": "http://strophe.im/strophejs/"
},
{
"name": "strophe.js/muc",
"file": "lib/strophe.muc.js",
"license": "MIT",
"url": "https://github.com/strophe/strophejs-plugins"
},
{
"name": "strophe.js/disco",
"file": "lib/strophe.disco.js",
"license": "MIT",
"url": "https://github.com/strophe/strophejs-plugins"
},
{
"name": "strophe.js/caps",
"file": "lib/strophe.caps.js",
"license": "MIT",
"url": "https://github.com/strophe/strophejs-plugins"
},
{
"name": "strophe.js/vcard",
"file": "lib/strophe.vcard.js",
"license": "MIT",
"url": "https://github.com/strophe/strophejs-plugins"
},
{
"name": "strophe.js/bookmarks",
"file": "lib/strophe.bookmarks/index.js",
"license": "MIT",
"url": "https://github.com/strophe/strophejs-plugins/tree/master/bookmarks"
},
{
"name": "strophe.js/x",
"file": "lib/strophe.x/index.js",
"license": "MIT",
"url": "https://github.com/strophe/strophejs-plugins/tree/master/dataforms"
},
{
"name": "strophe.jinglejs",
"file": "lib/strophe.jinglejs/strophe.jinglejs-bundle.js",
"license": "MIT",
"url": "https://github.com/sualko/strophe.jinglejs"
},
{
"name": "Salsa20",
"file": "lib/otr/build/dep/salsa20.js",
"license": "AGPL3",
"url": "https://github.com/neoatlantis/node-salsa20"
},
{
"name": "bigint",
"file": "lib/otr/build/dep/bigint.js",
"license": "public domain",
"url": "www.leemon.com"
},
{
"name": "cryptojs",
"file": "lib/otr/build/dep/crypto.js",
"license": "code.google.com/p/crypto-js/wiki/license",
"url": "code.google.com/p/crypto-js"
},
{
"name": "eventemitter",
"file": "lib/otr/build/dep/eventemitter.js",
"license": "MIT",
"url": "http://git.io/ee"
},
{
"name": "otr.js",
"file": "lib/otr/build/otr.js",
"license": "MPL v2.0",
"url": "https://arlolra.github.io/otr/"
},
{
"name": "i18next",
"file": "lib/i18next/release/i18next-latest.min.js",
"license": "MIT",
"url": "http://i18next.com/"
},
{
"name": "Magnific Popup",
"file": "lib/magnific-popup/dist/jquery.magnific-popup.min.js",
"license": "MIT",
"url": "http://dimsemenov.com/plugins/magnific-popup/"
},
{
"name": null,
"file": "lib/translation.js",
"license": "MIT",
"url": "https://webtranslateit.com/en/projects/10365-JSXC"
},
{
"name": "favico.js",
"file": "lib/favico.js/favico.js",
"license": "MIT",
"url": "https://github.com/ejci/favico.js"
}
]
+353
Ver Arquivo
@@ -0,0 +1,353 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Global</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Global</h1>
<section>
<header>
<h2>
</h2>
</header>
<article>
<div class="container-overview">
<dl class="details">
</dl>
</div>
<h3 class="subsection-title">Type Definitions</h3>
<dl>
<dt>
<h4 class="name" id="getUsers-cb"><span class="type-signature"></span>getUsers-cb<span class="signature">(list)</span><span class="type-signature"></span></h4>
</dt>
<dd>
<div class="description">
Processes user list.
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>list</code></td>
<td class="type">
<span class="param-type">object</span>
</td>
<td class="description last">List of users, key: username, value: alias</td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="jsxc.lib.options.js.html">jsxc.lib.options.js</a>, <a href="jsxc.lib.options.js.html#line187">line 187</a>
</li></ul></dd>
</dl>
</dd>
<dt>
<h4 class="name" id="loadSettingsCallback"><span class="type-signature"></span>loadSettingsCallback<span class="signature">(settings)</span><span class="type-signature"></span></h4>
</dt>
<dd>
<div class="description">
This callback processes all settings.
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>settings</code></td>
<td class="type">
<span class="param-type">object</span>
</td>
<td class="description last">could be every jsxc option</td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="jsxc.lib.options.js.html">jsxc.lib.options.js</a>, <a href="jsxc.lib.options.js.html#line154">line 154</a>
</li></ul></dd>
</dl>
</dd>
</dl>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Index</a></h2><h3>Namespaces</h3><ul><li><a href="jsxc.html">jsxc</a></li><li><a href="jsxc.gui.html">gui</a></li><li><a href="jsxc.gui.dialog.html">dialog</a></li><li><a href="jsxc.gui.queryActions.html">queryActions</a></li><li><a href="jsxc.gui.roster.html">roster</a></li><li><a href="jsxc.gui.window.html">window</a></li><li><a href="jsxc.muc.html">muc</a></li><li><a href="jsxc.notification.html">notification</a></li><li><a href="jsxc.options.html">options</a></li><li><a href="jsxc.otr.html">otr</a></li><li><a href="jsxc.storage.html">storage</a></li><li><a href="jsxc.webrtc.html">webrtc</a></li><li><a href="jsxc.xmpp.html">xmpp</a></li><li><a href="jsxc.xmpp.bookmarks.html">bookmarks</a></li><li><a href="jsxc.xmpp.carbons.html">carbons</a></li></ul><h3><a href="global.html">Global</a></h3>
</nav>
<br clear="both">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.2</a> on Tue Sep 08 2015 14:08:28 GMT+0200 (CEST)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>
+63
Ver Arquivo
@@ -0,0 +1,63 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Index</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Index</h1>
<h3> </h3>
</div>
<nav>
<h2><a href="index.html">Index</a></h2><h3>Namespaces</h3><ul><li><a href="jsxc.html">jsxc</a></li><li><a href="jsxc.gui.html">gui</a></li><li><a href="jsxc.gui.dialog.html">dialog</a></li><li><a href="jsxc.gui.queryActions.html">queryActions</a></li><li><a href="jsxc.gui.roster.html">roster</a></li><li><a href="jsxc.gui.window.html">window</a></li><li><a href="jsxc.muc.html">muc</a></li><li><a href="jsxc.notification.html">notification</a></li><li><a href="jsxc.options.html">options</a></li><li><a href="jsxc.otr.html">otr</a></li><li><a href="jsxc.storage.html">storage</a></li><li><a href="jsxc.webrtc.html">webrtc</a></li><li><a href="jsxc.xmpp.html">xmpp</a></li><li><a href="jsxc.xmpp.bookmarks.html">bookmarks</a></li><li><a href="jsxc.xmpp.carbons.html">carbons</a></li></ul><h3><a href="global.html">Global</a></h3>
</nav>
<br clear="both">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.2</a> on Tue Sep 08 2015 14:08:28 GMT+0200 (CEST)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>
+556
Ver Arquivo
@@ -0,0 +1,556 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Namespace: dialog</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Namespace: dialog</h1>
<section>
<header>
<h2>
<span class="ancestors"><a href="jsxc.html">jsxc</a><a href="jsxc.gui.html">.gui</a>.</span>
dialog
</h2>
</header>
<article>
<div class="container-overview">
<div class="description">Wrapper for dialog</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="jsxc.lib.gui.js.html">jsxc.lib.gui.js</a>, <a href="jsxc.lib.gui.js.html#line1765">line 1765</a>
</li></ul></dd>
</dl>
</div>
<h3 class="subsection-title">Methods</h3>
<dl>
<dt>
<h4 class="name" id="close"><span class="type-signature">&lt;static> </span>close<span class="signature">()</span><span class="type-signature"></span></h4>
</dt>
<dd>
<div class="description">
Close current dialog.
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="jsxc.lib.gui.js.html">jsxc.lib.gui.js</a>, <a href="jsxc.lib.gui.js.html#line1843">line 1843</a>
</li></ul></dd>
</dl>
</dd>
<dt>
<h4 class="name" id="open"><span class="type-signature">&lt;static> </span>open<span class="signature">(data, <span class="optional">o</span>)</span><span class="type-signature"> &rarr; {jQuery}</span></h4>
</dt>
<dd>
<div class="description">
Open a Dialog.
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Argument</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>data</code></td>
<td class="type">
<span class="param-type">String</span>
</td>
<td class="attributes">
</td>
<td class="description last">Data of the dialog</td>
</tr>
<tr>
<td class="name"><code>o</code></td>
<td class="type">
<span class="param-type">Object</span>
</td>
<td class="attributes">
&lt;optional><br>
</td>
<td class="description last">Options for the dialog
<h6>Properties</h6>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Argument</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>noClose</code></td>
<td class="type">
<span class="param-type">Boolean</span>
</td>
<td class="attributes">
&lt;optional><br>
</td>
<td class="description last">If true, hide all default close options</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="jsxc.lib.gui.js.html">jsxc.lib.gui.js</a>, <a href="jsxc.lib.gui.js.html#line1780">line 1780</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
Dialog object
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">jQuery</span>
</dd>
</dl>
</dd>
<dt>
<h4 class="name" id="resize"><span class="type-signature">&lt;static> </span>resize<span class="signature">(options)</span><span class="type-signature"></span></h4>
</dt>
<dd>
<div class="description">
Resizes current dialog.
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>options</code></td>
<td class="type">
<span class="param-type">Object</span>
</td>
<td class="description last">e.g. width and height</td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="jsxc.lib.gui.js.html">jsxc.lib.gui.js</a>, <a href="jsxc.lib.gui.js.html#line1854">line 1854</a>
</li></ul></dd>
</dl>
</dd>
</dl>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Index</a></h2><h3>Namespaces</h3><ul><li><a href="jsxc.html">jsxc</a></li><li><a href="jsxc.gui.html">gui</a></li><li><a href="jsxc.gui.dialog.html">dialog</a></li><li><a href="jsxc.gui.queryActions.html">queryActions</a></li><li><a href="jsxc.gui.roster.html">roster</a></li><li><a href="jsxc.gui.window.html">window</a></li><li><a href="jsxc.muc.html">muc</a></li><li><a href="jsxc.notification.html">notification</a></li><li><a href="jsxc.options.html">options</a></li><li><a href="jsxc.otr.html">otr</a></li><li><a href="jsxc.storage.html">storage</a></li><li><a href="jsxc.webrtc.html">webrtc</a></li><li><a href="jsxc.xmpp.html">xmpp</a></li><li><a href="jsxc.xmpp.bookmarks.html">bookmarks</a></li><li><a href="jsxc.xmpp.carbons.html">carbons</a></li></ul><h3><a href="global.html">Global</a></h3>
</nav>
<br clear="both">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.2</a> on Tue Sep 08 2015 14:08:28 GMT+0200 (CEST)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>
+3413
Ver Arquivo
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+473
Ver Arquivo
@@ -0,0 +1,473 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Namespace: queryActions</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Namespace: queryActions</h1>
<section>
<header>
<h2>
<span class="ancestors"><a href="jsxc.html">jsxc</a><a href="jsxc.gui.html">.gui</a>.</span>
queryActions
</h2>
</header>
<article>
<div class="container-overview">
<div class="description">Different uri query actions as defined in XEP-0147.</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="jsxc.lib.gui.js.html">jsxc.lib.gui.js</a>, <a href="jsxc.lib.gui.js.html#line36">line 36</a>
</li></ul></dd>
</dl>
</div>
<h3 class="subsection-title">Methods</h3>
<dl>
<dt>
<h4 class="name" id="join"><span class="type-signature">&lt;static> </span>join<span class="signature">()</span><span class="type-signature"></span></h4>
</dt>
<dd>
<div class="description">
xmpp:JID?join[;password=TEXT]
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="jsxc.lib.gui.js.html">jsxc.lib.gui.js</a>, <a href="jsxc.lib.gui.js.html#line71">line 71</a>
</li></ul></dd>
</dl>
</dd>
<dt>
<h4 class="name" id="message"><span class="type-signature">&lt;static> </span>message<span class="signature">()</span><span class="type-signature"></span></h4>
</dt>
<dd>
<div class="description">
xmpp:JID?message[;body=TEXT]
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="jsxc.lib.gui.js.html">jsxc.lib.gui.js</a>, <a href="jsxc.lib.gui.js.html#line43">line 43</a>
</li></ul></dd>
</dl>
</dd>
<dt>
<h4 class="name" id="remove"><span class="type-signature">&lt;static> </span>remove<span class="signature">()</span><span class="type-signature"></span></h4>
</dt>
<dd>
<div class="description">
xmpp:JID?remove
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="jsxc.lib.gui.js.html">jsxc.lib.gui.js</a>, <a href="jsxc.lib.gui.js.html#line52">line 52</a>
</li></ul></dd>
</dl>
</dd>
<dt>
<h4 class="name" id="subscribe"><span class="type-signature">&lt;static> </span>subscribe<span class="signature">()</span><span class="type-signature"></span></h4>
</dt>
<dd>
<div class="description">
xmpp:JID?subscribe[;name=NAME]
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="jsxc.lib.gui.js.html">jsxc.lib.gui.js</a>, <a href="jsxc.lib.gui.js.html#line57">line 57</a>
</li></ul></dd>
</dl>
</dd>
<dt>
<h4 class="name" id="vcard"><span class="type-signature">&lt;static> </span>vcard<span class="signature">()</span><span class="type-signature"></span></h4>
</dt>
<dd>
<div class="description">
xmpp:JID?vcard
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="jsxc.lib.gui.js.html">jsxc.lib.gui.js</a>, <a href="jsxc.lib.gui.js.html#line66">line 66</a>
</li></ul></dd>
</dl>
</dd>
</dl>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Index</a></h2><h3>Namespaces</h3><ul><li><a href="jsxc.html">jsxc</a></li><li><a href="jsxc.gui.html">gui</a></li><li><a href="jsxc.gui.dialog.html">dialog</a></li><li><a href="jsxc.gui.queryActions.html">queryActions</a></li><li><a href="jsxc.gui.roster.html">roster</a></li><li><a href="jsxc.gui.window.html">window</a></li><li><a href="jsxc.muc.html">muc</a></li><li><a href="jsxc.notification.html">notification</a></li><li><a href="jsxc.options.html">options</a></li><li><a href="jsxc.otr.html">otr</a></li><li><a href="jsxc.storage.html">storage</a></li><li><a href="jsxc.webrtc.html">webrtc</a></li><li><a href="jsxc.xmpp.html">xmpp</a></li><li><a href="jsxc.xmpp.bookmarks.html">bookmarks</a></li><li><a href="jsxc.xmpp.carbons.html">carbons</a></li></ul><h3><a href="global.html">Global</a></h3>
</nav>
<br clear="both">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.2</a> on Tue Sep 08 2015 14:08:28 GMT+0200 (CEST)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+124
Ver Arquivo
@@ -0,0 +1,124 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Namespace: template</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Namespace: template</h1>
<section>
<header>
<h2>
<span class="ancestors"><a href="jsxc.html">jsxc</a><a href="jsxc.gui.html">.gui</a>.</span>
template
</h2>
</header>
<article>
<div class="container-overview">
<div class="description">Hold all HTML templates.</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="jsxc.lib.gui.js.html">jsxc.lib.gui.js</a>, <a href="jsxc.lib.gui.js.html#line2288">line 2288</a>
</li></ul></dd>
</dl>
</div>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Index</a></h2><h3>Namespaces</h3><ul><li><a href="jsxc.html">jsxc</a></li><li><a href="jsxc.gui.html">gui</a></li><li><a href="jsxc.gui.dialog.html">dialog</a></li><li><a href="jsxc.gui.queryActions.html">queryActions</a></li><li><a href="jsxc.gui.roster.html">roster</a></li><li><a href="jsxc.gui.template.html">template</a></li><li><a href="jsxc.gui.window.html">window</a></li><li><a href="jsxc.muc.html">muc</a></li><li><a href="jsxc.notification.html">notification</a></li><li><a href="jsxc.options.html">options</a></li><li><a href="jsxc.otr.html">otr</a></li><li><a href="jsxc.storage.html">storage</a></li><li><a href="jsxc.webrtc.html">webrtc</a></li><li><a href="jsxc.xmpp.html">xmpp</a></li><li><a href="jsxc.xmpp.carbons.html">carbons</a></li></ul><h3><a href="global.html">Global</a></h3>
</nav>
<br clear="both">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.2</a> on Sat May 23 2015 16:03:19 GMT+0200 (CEST)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+4452
Ver Arquivo
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+124
Ver Arquivo
@@ -0,0 +1,124 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Namespace: l10n</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Namespace: l10n</h1>
<section>
<header>
<h2>
<span class="ancestors"><a href="jsxc.html">jsxc</a>.</span>
l10n
</h2>
</header>
<article>
<div class="container-overview">
<div class="description">Contains all available translations</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="jsxc.lib.js.html">jsxc.lib.js</a>, <a href="jsxc.lib.js.html#line5777">line 5777</a>
</li></ul></dd>
</dl>
</div>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Index</a></h2><h3>Namespaces</h3><ul><li><a href="jsxc.html">jsxc</a></li><li><a href="jsxc.gui.html">gui</a></li><li><a href="jsxc.gui.dialog.html">dialog</a></li><li><a href="jsxc.gui.queryActions.html">queryActions</a></li><li><a href="jsxc.gui.roster.html">roster</a></li><li><a href="jsxc.gui.template.html">template</a></li><li><a href="jsxc.gui.window.html">window</a></li><li><a href="jsxc.l10n.html">l10n</a></li><li><a href="jsxc.notification.html">notification</a></li><li><a href="jsxc.options.html">options</a></li><li><a href="jsxc.otr.html">otr</a></li><li><a href="jsxc.storage.html">storage</a></li><li><a href="jsxc.webrtc.html">webrtc</a></li><li><a href="jsxc.xmpp.html">xmpp</a></li><li><a href="jsxc.xmpp.carbons.html">carbons</a></li></ul>
</nav>
<br clear="both">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.2</a> on Wed Feb 25 2015 19:15:14 GMT+0100 (CET)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+889
Ver Arquivo
@@ -0,0 +1,889 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Source: jsxc.lib.js</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Source: jsxc.lib.js</h1>
<section>
<article>
<pre class="prettyprint source"><code>/**
* JavaScript Xmpp Chat namespace
*
* @namespace jsxc
*/
jsxc = {
/** Version of jsxc */
version: '&lt; $ app.version $ >',
/** True if i'm the master */
master: false,
/** True if the role allocation is finished */
role_allocation: false,
/** Timeout for keepalive */
to: null,
/** Timeout after normal keepalive starts */
toBusy: null,
/** Timeout for notification */
toNotification: null,
/** Timeout delay for notification */
toNotificationDelay: 500,
/** Interval for keep-alive */
keepalive: null,
/** True if last activity was up to 10 min ago */
restore: false,
/** True if restore is complete */
restoreCompleted: false,
/** True if login through box */
triggeredFromBox: false,
/** True if logout through element click */
triggeredFromElement: false,
/** True if logout through logout click */
triggeredFromLogout: false,
/** last values which we wrote into localstorage (IE workaround) */
ls: [],
/**
* storage event is even fired if I write something into storage (IE
* workaround) 0: conform, 1: not conform, 2: not shure
*/
storageNotConform: null,
/** Timeout for storageNotConform test */
toSNC: null,
/** My bar id */
bid: null,
/** Some constants */
CONST: {
NOTIFICATION_DEFAULT: 'default',
NOTIFICATION_GRANTED: 'granted',
NOTIFICATION_DENIED: 'denied',
STATUS: ['offline', 'dnd', 'xa', 'away', 'chat', 'online'],
SOUNDS: {
MSG: 'incomingMessage.wav',
CALL: 'Rotary-Phone6.mp3',
NOTICE: 'Ping1.mp3'
},
REGEX: {
JID: new RegExp('\\b[^"&\'\\/:&lt;>@\\s]+@[\\w-_.]+\\b', 'ig'),
URL: new RegExp(/((?:https?:\/\/|www\.|([\w\-]+\.[a-zA-Z]{2,3})(?=\b))(?:(?:[\-A-Za-z0-9+&@#\/%?=~_|!:,.;]*\([\-A-Za-z0-9+&@#\/%?=~_|!:,.;]*\)([\-A-Za-z0-9+&@#\/%?=~_|!:,.;]*[\-A-Za-z0-9+&@#\/%=~_|])?)|(?:[\-A-Za-z0-9+&@#\/%?=~_|!:,.;]*[\-A-Za-z0-9+&@#\/%=~_|]))?)/gi)
},
NS: {
CARBONS: 'urn:xmpp:carbons:2',
FORWARD: 'urn:xmpp:forward:0'
}
},
/**
* Parse a unix timestamp and return a formatted time string
*
* @memberOf jsxc
* @param {Object} unixtime
* @returns time of day and/or date
*/
getFormattedTime: function(unixtime) {
var msgDate = new Date(parseInt(unixtime));
var date = ('0' + msgDate.getDate()).slice(-2);
var month = ('0' + (msgDate.getMonth() + 1)).slice(-2);
var year = msgDate.getFullYear();
var hours = ('0' + msgDate.getHours()).slice(-2);
var minutes = ('0' + msgDate.getMinutes()).slice(-2);
var dateNow = new Date(),
time = hours + ':' + minutes;
// compare dates only
dateNow.setHours(0, 0, 0, 0);
msgDate.setHours(0, 0, 0, 0);
if (dateNow.getTime() !== msgDate.getTime()) {
return date + '.' + month + '.' + year + ' ' + time;
}
return time;
},
/**
* Write debug message to console and to log.
*
* @memberOf jsxc
* @param {String} msg Debug message
* @param {Object} data
* @param {String} Could be warn|error|null
*/
debug: function(msg, data, level) {
if (level) {
msg = '[' + level + '] ' + msg;
}
if (data) {
if (jsxc.storage.getItem('debug') === true) {
console.log(msg, data);
}
// try to convert data to string
var d;
try {
// clone html snippet
d = $("&lt;span>").prepend($(data).clone()).html();
} catch (err) {
try {
d = JSON.stringify(data);
} catch (err2) {
d = 'see js console';
}
}
jsxc.log = jsxc.log + msg + ': ' + d + '\n';
} else {
console.log(msg);
jsxc.log = jsxc.log + msg + '\n';
}
},
/**
* Write warn message.
*
* @memberOf jsxc
* @param {String} msg Warn message
* @param {Object} data
*/
warn: function(msg, data) {
jsxc.debug(msg, data, 'WARN');
},
/**
* Write error message.
*
* @memberOf jsxc
* @param {String} msg Error message
* @param {Object} data
*/
error: function(msg, data) {
jsxc.debug(msg, data, 'ERROR');
},
/** debug log */
log: '',
/**
* Starts the action
*
* @memberOf jsxc
* @param {object} options
*/
init: function(options) {
if (options) {
// override default options
$.extend(true, jsxc.options, options);
}
// Check localStorage
if (typeof(localStorage) === 'undefined') {
jsxc.warn("Browser doesn't support localStorage.");
return;
}
/**
* Getter method for options. Saved options will override default one.
*
* @param {string} key option key
* @returns default or saved option value
*/
jsxc.options.get = function(key) {
var local = jsxc.storage.getUserItem('options') || {};
return local[key] || jsxc.options[key];
};
/**
* Setter method for options. Will write into localstorage.
*
* @param {string} key option key
* @param {object} value option value
*/
jsxc.options.set = function(key, value) {
jsxc.storage.updateItem('options', key, value, true);
};
jsxc.storageNotConform = jsxc.storage.getItem('storageNotConform');
if (jsxc.storageNotConform === null) {
jsxc.storageNotConform = 2;
}
// detect language
var lang;
if (jsxc.storage.getItem('lang') !== null) {
lang = jsxc.storage.getItem('lang');
} else if (jsxc.options.autoLang && navigator.language) {
lang = navigator.language.substr(0, 2);
} else {
lang = jsxc.options.defaultLang;
}
// initialize i18n translator
$.i18n.init({
lng: lang,
fallbackLng: 'en',
resStore: I18next,
// use localStorage and set expiration to a day
useLocalStorage: true,
localStorageExpirationTime: 60 * 60 * 24 * 1000,
});
if (jsxc.storage.getItem('debug') === true) {
jsxc.options.otr.debug = true;
}
// Register event listener for the storage event
window.addEventListener('storage', jsxc.storage.onStorage, false);
var lastActivity = jsxc.storage.getItem('lastActivity') || 0;
if ((new Date()).getTime() - lastActivity &lt; jsxc.options.loginTimeout) {
jsxc.restore = true;
}
$(document).on('connectionReady.jsxc', function() {
// Looking for logout element
if (jsxc.options.logoutElement !== null && jsxc.options.logoutElement.length > 0) {
var logout = function() {
jsxc.options.logoutElement = $(this);
jsxc.triggeredFromLogout = true;
return jsxc.xmpp.logout();
};
jsxc.options.logoutElement.off('click', null, logout).one('click', logout);
}
});
// Check if we have to establish a new connection
if (!jsxc.storage.getItem('rid') || !jsxc.storage.getItem('sid') || !jsxc.restore) {
// clean up rid and sid
jsxc.storage.removeItem('rid');
jsxc.storage.removeItem('sid');
// Looking for a login form
if (!jsxc.isLoginForm()) {
if (jsxc.options.displayRosterMinimized()) {
// Show minimized roster
jsxc.storage.setUserItem('roster', 'hidden');
jsxc.gui.roster.init();
jsxc.gui.roster.noConnection();
}
return;
}
if (typeof jsxc.options.formFound === 'function') {
jsxc.options.formFound.call();
}
// create jquery object
var form = jsxc.options.loginForm.form = $(jsxc.options.loginForm.form);
var events = form.data('events') || {
submit: []
};
var submits = [];
// save attached submit events and remove them. Will be reattached
// in jsxc.submitLoginForm
$.each(events.submit, function(index, val) {
submits.push(val.handler);
});
form.data('submits', submits);
form.off('submit');
// Add jsxc login action to form
form.submit(function() {
jsxc.prepareLogin(function(settings) {
if (settings !== false) {
// settings.xmpp.onlogin is deprecated since v2.1.0
var enabled = (settings.loginForm && settings.loginForm.enable) || (settings.xmpp && settings.xmpp.onlogin);
enabled = enabled === "true" || enabled === true;
if (enabled) {
jsxc.options.loginForm.triggered = true;
jsxc.xmpp.login();
}
} else {
jsxc.submitLoginForm();
}
});
// Trigger submit in jsxc.xmpp.connected()
return false;
});
} else if (!jsxc.isLoginForm() || (jsxc.options.loginForm && jsxc.options.loginForm.attachIfFound)) {
// Restore old connection
jsxc.bid = jsxc.jidToBid(jsxc.storage.getItem('jid'));
jsxc.gui.init();
if (typeof(jsxc.storage.getItem('alive')) === 'undefined' || !jsxc.restore) {
jsxc.onMaster();
} else {
jsxc.checkMaster();
}
}
},
/**
* Returns true if login form is found.
*
* @memberOf jsxc
* @returns {boolean} True if login form was found.
*/
isLoginForm: function() {
return jsxc.options.loginForm.form && jsxc.el_exists(jsxc.options.loginForm.form) && jsxc.el_exists(jsxc.options.loginForm.jid) && jsxc.el_exists(jsxc.options.loginForm.pass);
},
/**
* Load settings and prepare jid.
*
* @memberOf jsxc
* @param {string} username
* @param {string} password
* @param {function} cb Called after login is prepared with result as param
*/
prepareLogin: function(username, password, cb) {
if (typeof username === 'function') {
cb = username;
username = null;
}
username = username || $(jsxc.options.loginForm.jid).val();
password = password || $(jsxc.options.loginForm.pass).val();
if (!jsxc.triggeredFromBox && (jsxc.options.loginForm.onConnecting === 'dialog' || typeof jsxc.options.loginForm.onConnecting === 'undefined')) {
jsxc.gui.showWaitAlert($.t('Logging_in'));
}
var settings;
if (typeof jsxc.options.loadSettings === 'function') {
settings = jsxc.options.loadSettings.call(this, username, password, function(s) {
jsxc._prepareLogin(username, password, cb, s);
});
if (typeof settings !== 'undefined') {
jsxc._prepareLogin(username, password, cb, settings);
}
} else {
jsxc._prepareLogin(username, password, cb);
}
},
/**
* Process xmpp settings and save loaded settings.
*
* @private
* @memberOf jsxc
* @param {string} username
* @param {string} password
* @param {function} cb Called after login is prepared with result as param
* @param {object} [loadedSettings] additonal options
*/
_prepareLogin: function(username, password, cb, loadedSettings) {
if (loadedSettings === false) {
jsxc.warn('No settings provided');
cb(false);
return;
}
// prevent to modify the original object
var settings = $.extend(true, {}, jsxc.options);
if (loadedSettings) {
// overwrite current options with loaded settings;
settings = $.extend(true, settings, loadedSettings);
} else {
loadedSettings = {};
}
if (typeof settings.xmpp.username === 'string') {
username = settings.xmpp.username;
}
var resource = (settings.xmpp.resource) ? '/' + settings.xmpp.resource : '';
var domain = settings.xmpp.domain;
var jid;
if (username.match(/@(.*)$/)) {
jid = (username.match(/\/(.*)$/)) ? username : username + resource;
} else {
jid = username + '@' + domain + resource;
}
if (typeof jsxc.options.loginForm.preJid === 'function') {
jid = jsxc.options.loginForm.preJid(jid);
}
jsxc.bid = jsxc.jidToBid(jid);
settings.xmpp.username = jid.split('@')[0];
settings.xmpp.domain = jid.split('@')[1].split('/')[0];
settings.xmpp.resource = jid.split('@')[1].split('/')[1] || "";
if (!loadedSettings.xmpp) {
// force xmpp settings to be saved to storage
loadedSettings.xmpp = {};
}
// save loaded settings to storage
$.each(loadedSettings, function(key) {
var old = jsxc.options.get(key);
var val = settings[key];
val = $.extend(true, old, val);
jsxc.options.set(key, val);
});
jsxc.options.xmpp.jid = jid;
jsxc.options.xmpp.password = password;
cb(settings);
},
/**
* Called if the script is a slave
*/
onSlave: function() {
jsxc.debug('I am the slave.');
jsxc.role_allocation = true;
jsxc.restoreRoster();
jsxc.restoreWindows();
jsxc.restoreCompleted = true;
$(document).trigger('restoreCompleted.jsxc');
},
/**
* Called if the script is the master
*/
onMaster: function() {
jsxc.debug('I am master.');
jsxc.master = true;
// Init local storage
jsxc.storage.setItem('alive', 0);
jsxc.storage.setItem('alive_busy', 0);
if (!jsxc.storage.getUserItem('windowlist')) {
jsxc.storage.setUserItem('windowlist', []);
}
// Sending keepalive signal
jsxc.startKeepAlive();
if (jsxc.options.get('otr').enable) {
// create or load DSA key and call _onMaster
jsxc.otr.createDSA();
} else {
jsxc._onMaster();
}
},
/**
* Second half of the onMaster routine
*/
_onMaster: function() {
// create otr objects, if we lost the master
if (jsxc.role_allocation) {
$.each(jsxc.storage.getUserItem('windowlist'), function(index, val) {
jsxc.otr.create(val);
});
}
jsxc.role_allocation = true;
if (jsxc.restore && !jsxc.restoreCompleted) {
jsxc.restoreRoster();
jsxc.restoreWindows();
jsxc.restoreCompleted = true;
$(document).trigger('restoreCompleted.jsxc');
}
// Prepare notifications
if (jsxc.restore) {
var noti = jsxc.storage.getUserItem('notification');
noti = (typeof noti === 'number') ? noti : 2;
if (jsxc.options.notification && noti > 0 && jsxc.notification.hasSupport()) {
if (jsxc.notification.hasPermission()) {
jsxc.notification.init();
} else {
jsxc.notification.prepareRequest();
}
} else {
// No support => disable
jsxc.options.notification = false;
}
}
$(document).on('connectionReady.jsxc', function() {
jsxc.gui.updateAvatar($('#jsxc_avatar'), jsxc.jidToBid(jsxc.storage.getItem('jid')), 'own');
});
jsxc.xmpp.login();
},
/**
* Checks if there is a master
*/
checkMaster: function() {
jsxc.debug('check master');
jsxc.to = window.setTimeout(jsxc.onMaster, 1000);
jsxc.storage.ink('alive');
},
/**
* Start sending keep-alive signal
*/
startKeepAlive: function() {
jsxc.keepalive = window.setInterval(jsxc.keepAlive, jsxc.options.timeout - 1000);
},
/**
* Sends the keep-alive signal to signal that the master is still there.
*/
keepAlive: function() {
jsxc.storage.ink('alive');
if (jsxc.role_allocation) {
jsxc.storage.setItem('lastActivity', (new Date()).getTime());
}
},
/**
* Send one keep-alive signal with higher timeout, and than resume with
* normal signal
*/
keepBusyAlive: function() {
if (jsxc.toBusy) {
window.clearTimeout(jsxc.toBusy);
}
if (jsxc.keepalive) {
window.clearInterval(jsxc.keepalive);
}
jsxc.storage.ink('alive_busy');
jsxc.toBusy = window.setTimeout(jsxc.startKeepAlive, jsxc.options.busyTimeout - 1000);
},
/**
* Generates a random integer number between 0 and max
*
* @param {Integer} max
* @return {Integer} random integer between 0 and max
*/
random: function(max) {
return Math.floor(Math.random() * max);
},
/**
* Checks if there is a element with the given selector
*
* @param {String} selector jQuery selector
* @return {Boolean}
*/
el_exists: function(selector) {
return $(selector).length > 0;
},
/**
* Creates a CSS compatible string from a JID
*
* @param {type} jid Valid Jabber ID
* @returns {String} css Compatible string
*/
jidToCid: function(jid) {
jsxc.warn('jsxc.jidToCid is deprecated!');
var cid = Strophe.getBareJidFromJid(jid).replace('@', '-').replace(/\./g, '-').toLowerCase();
return cid;
},
/**
* Create comparable bar jid.
*
* @memberOf jsxc
* @param jid
* @returns comparable bar jid
*/
jidToBid: function(jid) {
return Strophe.unescapeNode(Strophe.getBareJidFromJid(jid).toLowerCase());
},
/**
* Restore roster
*/
restoreRoster: function() {
var buddies = jsxc.storage.getUserItem('buddylist');
if (!buddies || buddies.length === 0) {
jsxc.debug('No saved buddylist.');
jsxc.gui.roster.empty();
return;
}
$.each(buddies, function(index, value) {
jsxc.gui.roster.add(value);
});
jsxc.gui.roster.loaded = true;
$(document).trigger('cloaded.roster.jsxc');
},
/**
* Restore all windows
*/
restoreWindows: function() {
var windows = jsxc.storage.getUserItem('windowlist');
if (windows === null) {
return;
}
$.each(windows, function(index, bid) {
var window = jsxc.storage.getUserItem('window', bid);
if (!window) {
jsxc.debug('Associated window-element is missing: ' + bid);
return true;
}
jsxc.gui.window.init(bid);
if (!window.minimize) {
jsxc.gui.window.show(bid);
} else {
jsxc.gui.window.hide(bid);
}
jsxc.gui.window.setText(bid, window.text);
});
},
/**
* This method submits the specified login form.
*/
submitLoginForm: function() {
var form = jsxc.options.loginForm.form.off('submit');
// Attach original events
var submits = form.data('submits') || [];
$.each(submits, function(index, val) {
form.submit(val);
});
if (form.find('#submit').length > 0) {
form.find('#submit').click();
} else {
form.submit();
}
},
/**
* Escapes some characters to HTML character
*/
escapeHTML: function(text) {
text = text.replace(/&amp;/g, '&').replace(/&lt;/g, '&lt;').replace(/&gt;/g, '>');
return text.replace(/&/g, '&amp;').replace(/&lt;/g, '&lt;').replace(/>/g, '&gt;');
},
/**
* Removes all html tags.
*
* @memberOf jsxc
* @param text
* @returns stripped text
*/
removeHTML: function(text) {
return $('&lt;span>').html(text).text();
},
/**
* Executes only one of the given events
*
* @param {string} obj.key event name
* @param {function} obj.value function to execute
* @returns {string} namespace of all events
*/
switchEvents: function(obj) {
var ns = Math.random().toString(36).substr(2, 12);
var self = this;
$.each(obj, function(key, val) {
$(document).one(key + '.' + ns, function() {
$(document).off('.' + ns);
val.apply(self, arguments);
});
});
return ns;
},
/**
* Checks if tab is hidden.
*
* @returns {boolean} True if tab is hidden
*/
isHidden: function() {
var hidden = false;
if (typeof document.hidden !== 'undefined') {
hidden = document.hidden;
} else if (typeof document.webkitHidden !== 'undefined') {
hidden = document.webkitHidden;
} else if (typeof document.mozHidden !== 'undefined') {
hidden = document.mozHidden;
} else if (typeof document.msHidden !== 'undefined') {
hidden = document.msHidden;
}
// handle multiple tabs
if (hidden && jsxc.master) {
jsxc.storage.ink('hidden', 0);
} else if (!hidden && !jsxc.master) {
jsxc.storage.ink('hidden');
}
return hidden;
},
/**
* Checks if tab has focus.
*
* @returns {boolean} True if tabs has focus
*/
hasFocus: function() {
var focus = true;
if (typeof document.hasFocus === 'function') {
focus = document.hasFocus();
}
if (!focus && jsxc.master) {
jsxc.storage.ink('focus', 0);
} else if (focus && !jsxc.master) {
jsxc.storage.ink('focus');
}
return focus;
},
/**
* Executes the given function in jsxc namespace.
*
* @memberOf jsxc
* @param {string} fnName Function name
* @param {array} fnParams Function parameters
* @returns Function return value
*/
exec: function(fnName, fnParams) {
var fnList = fnName.split('.');
var fn = jsxc[fnList[0]];
var i;
for (i = 1; i &lt; fnList.length; i++) {
fn = fn[fnList[i]];
}
if (typeof fn === 'function') {
return fn.apply(null, fnParams);
}
},
/**
* Hash string into 32-bit signed integer.
*
* @memberOf jsxc
* @param {string} str input string
* @returns {integer} 32-bit signed integer
*/
hashStr: function(str) {
var hash = 0,
i;
if (str.length === 0) {
return hash;
}
for (i = 0; i &lt; str.length; i++) {
hash = ((hash &lt;&lt; 5) - hash) + str.charCodeAt(i);
hash |= 0; // Convert to 32bit integer
}
return hash;
}
};
</code></pre>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Index</a></h2><h3>Namespaces</h3><ul><li><a href="jsxc.html">jsxc</a></li><li><a href="jsxc.gui.html">gui</a></li><li><a href="jsxc.gui.dialog.html">dialog</a></li><li><a href="jsxc.gui.queryActions.html">queryActions</a></li><li><a href="jsxc.gui.roster.html">roster</a></li><li><a href="jsxc.gui.window.html">window</a></li><li><a href="jsxc.muc.html">muc</a></li><li><a href="jsxc.notification.html">notification</a></li><li><a href="jsxc.options.html">options</a></li><li><a href="jsxc.otr.html">otr</a></li><li><a href="jsxc.storage.html">storage</a></li><li><a href="jsxc.webrtc.html">webrtc</a></li><li><a href="jsxc.xmpp.html">xmpp</a></li><li><a href="jsxc.xmpp.bookmarks.html">bookmarks</a></li><li><a href="jsxc.xmpp.carbons.html">carbons</a></li></ul><h3><a href="global.html">Global</a></h3>
</nav>
<br clear="both">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.2</a> on Tue Sep 08 2015 14:08:28 GMT+0200 (CEST)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+166
Ver Arquivo
@@ -0,0 +1,166 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Source: jsxc.lib.notice.js</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Source: jsxc.lib.notice.js</h1>
<section>
<article>
<pre class="prettyprint source"><code>/**
* This namespace handle the notice system.
*
* @namspace jsxc.notice
* @memberOf jsxc
*/
jsxc.notice = {
/** Number of notices. */
_num: 0,
/**
* Loads the saved notices.
*
* @memberOf jsxc.notice
*/
load: function() {
// reset list
$('#jsxc_notice ul li').remove();
$('#jsxc_notice > span').text('');
jsxc.notice._num = 0;
var saved = jsxc.storage.getUserItem('notices') || [];
var key = null;
for (key in saved) {
if (saved.hasOwnProperty(key)) {
var val = saved[key];
jsxc.notice.add(val.msg, val.description, val.fnName, val.fnParams, key);
}
}
},
/**
* Add a new notice to the stack;
*
* @memberOf jsxc.notice
* @param msg Header message
* @param description Notice description
* @param fnName Function name to be called if you open the notice
* @param fnParams Array of params for function
* @param id Notice id
*/
add: function(msg, description, fnName, fnParams, id) {
var nid = id || Date.now();
var list = $('#jsxc_notice ul');
var notice = $('&lt;li/>');
notice.click(function() {
jsxc.notice.remove(nid);
jsxc.exec(fnName, fnParams);
return false;
});
notice.text(msg);
notice.attr('title', description || '');
notice.attr('data-nid', nid);
list.append(notice);
$('#jsxc_notice > span').text(++jsxc.notice._num);
if (!id) {
var saved = jsxc.storage.getUserItem('notices') || {};
saved[nid] = {
msg: msg,
description: description,
fnName: fnName,
fnParams: fnParams
};
jsxc.storage.setUserItem('notices', saved);
jsxc.notification.notify(msg, description || '', null, true, jsxc.CONST.SOUNDS.NOTICE);
}
},
/**
* Removes notice from stack
*
* @memberOf jsxc.notice
* @param nid The notice id
*/
remove: function(nid) {
var el = $('#jsxc_notice li[data-nid=' + nid + ']');
el.remove();
$('#jsxc_notice > span').text(--jsxc.notice._num || '');
var s = jsxc.storage.getUserItem('notices');
delete s[nid];
jsxc.storage.setUserItem('notices', s);
},
/**
* Check if there is already a notice for the given function name.
*
* @memberOf jsxc.notice
* @param {string} fnName Function name
* @returns {boolean} True if there is >0 functions with the given name
*/
has: function(fnName) {
var saved = jsxc.storage.getUserItem('notices') || [];
var has = false;
$.each(saved, function(index, val) {
if (val.fnName === fnName) {
has = true;
return false;
}
});
return has;
}
};
</code></pre>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Index</a></h2><h3>Namespaces</h3><ul><li><a href="jsxc.html">jsxc</a></li><li><a href="jsxc.gui.html">gui</a></li><li><a href="jsxc.gui.dialog.html">dialog</a></li><li><a href="jsxc.gui.queryActions.html">queryActions</a></li><li><a href="jsxc.gui.roster.html">roster</a></li><li><a href="jsxc.gui.window.html">window</a></li><li><a href="jsxc.muc.html">muc</a></li><li><a href="jsxc.notification.html">notification</a></li><li><a href="jsxc.options.html">options</a></li><li><a href="jsxc.otr.html">otr</a></li><li><a href="jsxc.storage.html">storage</a></li><li><a href="jsxc.webrtc.html">webrtc</a></li><li><a href="jsxc.xmpp.html">xmpp</a></li><li><a href="jsxc.xmpp.bookmarks.html">bookmarks</a></li><li><a href="jsxc.xmpp.carbons.html">carbons</a></li></ul><h3><a href="global.html">Global</a></h3>
</nav>
<br clear="both">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.2</a> on Tue Sep 08 2015 14:08:28 GMT+0200 (CEST)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>
+324
Ver Arquivo
@@ -0,0 +1,324 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Source: jsxc.lib.notification.js</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Source: jsxc.lib.notification.js</h1>
<section>
<article>
<pre class="prettyprint source"><code>/**
* This namespace handles the Notification API.
*
* @namespace jsxc.notification
*/
jsxc.notification = {
/** Current audio file. */
audio: null,
/**
* Register notification on incoming messages.
*
* @memberOf jsxc.notification
*/
init: function() {
$(document).on('postmessagein.jsxc', function(event, bid, msg) {
msg = (msg.match(/^\?OTR/)) ? $.t('Encrypted_message') : msg;
var data = jsxc.storage.getUserItem('buddy', bid);
jsxc.notification.notify({
title: $.t('New_message_from', {
name: data.name
}),
msg: msg,
soundFile: jsxc.CONST.SOUNDS.MSG,
source: bid
});
});
$(document).on('callincoming.jingle', function() {
jsxc.notification.playSound(jsxc.CONST.SOUNDS.CALL, true, true);
});
$(document).on('accept.call.jsxc reject.call.jsxc', function() {
jsxc.notification.stopSound();
});
},
/**
* Shows a pop up notification and optional play sound.
*
* @param title Title
* @param msg Message
* @param d Duration
* @param force Should message also shown, if tab is visible?
* @param soundFile Playing given sound file
* @param loop Loop sound file?
* @param source Bid which triggered this notification
*/
notify: function(title, msg, d, force, soundFile, loop, source) {
if (!jsxc.options.notification || !jsxc.notification.hasPermission()) {
return; // notifications disabled
}
var o;
if (title !== null && typeof title === 'object') {
o = title;
} else {
o = {
title: title,
msg: msg,
duration: d,
force: force,
soundFile: soundFile,
loop: loop,
source: source
};
}
if (jsxc.hasFocus() && !o.force) {
return; // Tab is visible
}
var icon = o.icon || jsxc.options.root + '/img/XMPP_logo.png';
if (typeof o.source === 'string') {
var data = jsxc.storage.getUserItem('buddy', o.source);
var src = jsxc.storage.getUserItem('avatar', data.avatar);
if (typeof src === 'string' && src !== '0') {
icon = src;
}
}
jsxc.toNotification = setTimeout(function() {
if (typeof o.soundFile === 'string') {
jsxc.notification.playSound(o.soundFile, o.loop, o.force);
}
var popup = new Notification($.t(o.title), {
body: $.t(o.msg),
icon: icon
});
var duration = o.duration || jsxc.options.popupDuration;
if (duration > 0) {
setTimeout(function() {
popup.close();
}, duration);
}
}, jsxc.toNotificationDelay);
},
/**
* Checks if browser has support for notifications and add on chrome to the
* default api.
*
* @returns {Boolean} True if the browser has support.
*/
hasSupport: function() {
if (window.webkitNotifications) {
// prepare chrome
window.Notification = function(title, opt) {
var popup = window.webkitNotifications.createNotification(null, title, opt.body);
popup.show();
popup.close = function() {
popup.cancel();
};
return popup;
};
var permission;
switch (window.webkitNotifications.checkPermission()) {
case 0:
permission = jsxc.CONST.NOTIFICATION_GRANTED;
break;
case 2:
permission = jsxc.CONST.NOTIFICATION_DENIED;
break;
default: // 1
permission = jsxc.CONST.NOTIFICATION_DEFAULT;
}
window.Notification.permission = permission;
window.Notification.requestPermission = function(func) {
window.webkitNotifications.requestPermission(func);
};
return true;
} else if (window.Notification) {
return true;
} else {
return false;
}
},
/**
* Ask user on first incoming message if we should inform him about new
* messages.
*/
prepareRequest: function() {
if (jsxc.notice.has('gui.showRequestNotification')) {
return;
}
$(document).one('postmessagein.jsxc', function() {
setTimeout(function() {
jsxc.notice.add($.t('Notifications') + '?', $.t('Should_we_notify_you_'), 'gui.showRequestNotification');
}, 1000);
});
},
/**
* Request notification permission.
*/
requestPermission: function() {
window.Notification.requestPermission(function(status) {
if (window.Notification.permission !== status) {
window.Notification.permission = status;
}
if (jsxc.notification.hasPermission()) {
$(document).trigger('notificationready.jsxc');
} else {
$(document).trigger('notificationfailure.jsxc');
}
});
},
/**
* Check permission.
*
* @returns {Boolean} True if we have the permission
*/
hasPermission: function() {
return window.Notification.permission === jsxc.CONST.NOTIFICATION_GRANTED;
},
/**
* Plays the given file.
*
* @memberOf jsxc.notification
* @param {string} soundFile File relative to the sound directory
* @param {boolean} loop True for loop
* @param {boolean} force Play even if a tab is visible. Default: false.
*/
playSound: function(soundFile, loop, force) {
if (!jsxc.master) {
// only master plays sound
return;
}
if (jsxc.options.get('muteNotification') || jsxc.storage.getUserItem('presence') === 'dnd') {
// sound mute or own presence is dnd
return;
}
if (jsxc.hasFocus() && !force) {
// tab is visible
return;
}
// stop current audio file
jsxc.notification.stopSound();
var audio = new Audio(jsxc.options.root + '/sound/' + soundFile);
audio.loop = loop || false;
audio.play();
jsxc.notification.audio = audio;
},
/**
* Stop/remove current sound.
*
* @memberOf jsxc.notification
*/
stopSound: function() {
var audio = jsxc.notification.audio;
if (typeof audio !== 'undefined' && audio !== null) {
audio.pause();
jsxc.notification.audio = null;
}
},
/**
* Mute sound.
*
* @memberOf jsxc.notification
* @param {boolean} external True if triggered from external tab. Default:
* false.
*/
muteSound: function(external) {
$('#jsxc_menu .jsxc_muteNotification').text($.t('Unmute'));
if (external !== true) {
jsxc.options.set('muteNotification', true);
}
},
/**
* Unmute sound.
*
* @memberOf jsxc.notification
* @param {boolean} external True if triggered from external tab. Default:
* false.
*/
unmuteSound: function(external) {
$('#jsxc_menu .jsxc_muteNotification').text($.t('Mute'));
if (external !== true) {
jsxc.options.set('muteNotification', false);
}
}
};
</code></pre>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Index</a></h2><h3>Namespaces</h3><ul><li><a href="jsxc.html">jsxc</a></li><li><a href="jsxc.gui.html">gui</a></li><li><a href="jsxc.gui.dialog.html">dialog</a></li><li><a href="jsxc.gui.queryActions.html">queryActions</a></li><li><a href="jsxc.gui.roster.html">roster</a></li><li><a href="jsxc.gui.window.html">window</a></li><li><a href="jsxc.muc.html">muc</a></li><li><a href="jsxc.notification.html">notification</a></li><li><a href="jsxc.options.html">options</a></li><li><a href="jsxc.otr.html">otr</a></li><li><a href="jsxc.storage.html">storage</a></li><li><a href="jsxc.webrtc.html">webrtc</a></li><li><a href="jsxc.xmpp.html">xmpp</a></li><li><a href="jsxc.xmpp.bookmarks.html">bookmarks</a></li><li><a href="jsxc.xmpp.carbons.html">carbons</a></li></ul><h3><a href="global.html">Global</a></h3>
</nav>
<br clear="both">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.2</a> on Tue Sep 08 2015 14:08:28 GMT+0200 (CEST)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>
+284
Ver Arquivo
@@ -0,0 +1,284 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Source: jsxc.lib.options.js</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Source: jsxc.lib.options.js</h1>
<section>
<article>
<pre class="prettyprint source"><code>/**
* Set some options for the chat.
*
* @namespace jsxc.options
*/
jsxc.options = {
/** name of container application (e.g. owncloud or SOGo) */
app_name: 'web applications',
/** Timeout for the keepalive signal */
timeout: 3000,
/** Timeout for the keepalive signal if the master is busy */
busyTimeout: 15000,
/** OTR options */
otr: {
enable: true,
ERROR_START_AKE: false,
debug: false,
SEND_WHITESPACE_TAG: true,
WHITESPACE_START_AKE: true
},
/** xmpp options */
xmpp: {
/** BOSH url */
url: null,
/** XMPP JID*/
jid: null,
/** XMPP domain */
domain: null,
/** XMPP password */
password: null,
/** True: Allow user to overwrite xmpp settings */
overwrite: false,
/** @deprecated since v2.1.0. Use now loginForm.enable. */
onlogin: null
},
/** default xmpp priorities */
priority: {
online: 0,
chat: 0,
away: 0,
xa: 0,
dnd: 0
},
/** If all 3 properties are set and enable is true, the login form is used */
loginForm: {
/** False, disables login through login form */
enable: true,
/** jquery object from form */
form: null,
/** jquery object from input element which contains the jid */
jid: null,
/** jquery object from input element which contains the password */
pass: null,
/** manipulate JID from input element */
preJid: function(jid) {
return jid;
},
/**
* Action after login was called: dialog [String] Show wait dialog, false [boolean] |
* quiet [String] Do nothing
*/
onConnecting: 'dialog',
/**
* Action after connected: submit [String] Submit form, false [boolean] Do
* nothing, continue [String] Start chat
*/
onConnected: 'submit',
/**
* Action after auth fail: submit [String] Submit form, false [boolean] | quiet [String] Do
* nothing, ask [String] Show auth fail dialog
*/
onAuthFail: 'submit',
/** True: Attach connection even is login form was found */
attachIfFound: true,
/**
* True: Display roster minimized after first login. Afterwards the last
* roster state will be used.
*/
startMinimized: false
},
/** jquery object from logout element */
logoutElement: null,
/** How many messages should be logged? */
numberOfMsg: 10,
/** Default language */
defaultLang: 'en',
/** auto language detection */
autoLang: true,
/** Place for roster */
rosterAppend: 'body',
/** Should we use the HTML5 notification API? */
notification: true,
/** duration for notification */
popupDuration: 6000,
/** Absolute path root of JSXC installation */
root: '',
/** Timeout for restore in ms */
loginTimeout: 1000 * 60 * 10,
/**
* This function decides wether the roster will be displayed or not if no
* connection is found.
*/
displayRosterMinimized: function() {
return false;
},
/** Set to true if you want to hide offline buddies. */
hideOffline: false,
/** Mute notification sound? */
muteNotification: false,
/**
* If no avatar is found, this function is called.
*
* @param jid Jid of that user.
* @this {jQuery} Elements to update with probable .jsxc_avatar elements
*/
defaultAvatar: function(jid) {
jsxc.gui.avatarPlaceholder($(this).find('.jsxc_avatar'), jid);
},
/**
* This callback processes all settings.
* @callback loadSettingsCallback
* @param settings {object} could be every jsxc option
*/
/**
* Returns permanent saved settings and overwrite default jsxc.options.
*
* @memberOf jsxc.options
* @function
* @param username {string} username
* @param password {string} password
* @param cb {loadSettingsCallback} Callback that handles the result
*/
loadSettings: null,
/**
* Call this function to save user settings permanent.
*
* @memberOf jsxc.options
* @param data Holds all data as key/value
* @returns {boolean} false if function failes
*/
saveSettinsPermanent: function() {
},
carbons: {
/** Enable carbon copies? */
enable: false
},
/**
* Processes user list.
*
* @callback getUsers-cb
* @param {object} list List of users, key: username, value: alias
*/
/**
* Returns a list of usernames and aliases
*
* @function getUsers
* @memberOf jsxc.options
* @param {string} search Search token (start with)
* @param {getUsers-cb} cb Called with list of users
*/
getUsers: null,
/** Options for info in favicon */
favicon: {
enable: true,
/** Favicon info background color */
bgColor: '#E59400',
/** Favicon info text color */
textColor: '#fff'
},
/** @deprecated since v2.1.0. Use now RTCPeerConfig.url. */
turnCredentialsPath: null,
/** RTCPeerConfiguration used for audio/video calls. */
RTCPeerConfig: {
/** Time-to-live for config from url */
ttl: 3600,
/** [optional] If set, jsxc requests and uses RTCPeerConfig from this url */
url: null,
/** ICE servers like defined in http://www.w3.org/TR/webrtc/#idl-def-RTCIceServer */
iceServers: [{
urls: 'stun:stun.stunprotocol.org'
}]
},
/** Link to an online user manual */
onlineHelp: 'http://www.jsxc.org/manual.html'
};
</code></pre>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Index</a></h2><h3>Namespaces</h3><ul><li><a href="jsxc.html">jsxc</a></li><li><a href="jsxc.gui.html">gui</a></li><li><a href="jsxc.gui.dialog.html">dialog</a></li><li><a href="jsxc.gui.queryActions.html">queryActions</a></li><li><a href="jsxc.gui.roster.html">roster</a></li><li><a href="jsxc.gui.window.html">window</a></li><li><a href="jsxc.muc.html">muc</a></li><li><a href="jsxc.notification.html">notification</a></li><li><a href="jsxc.options.html">options</a></li><li><a href="jsxc.otr.html">otr</a></li><li><a href="jsxc.storage.html">storage</a></li><li><a href="jsxc.webrtc.html">webrtc</a></li><li><a href="jsxc.xmpp.html">xmpp</a></li><li><a href="jsxc.xmpp.bookmarks.html">bookmarks</a></li><li><a href="jsxc.xmpp.carbons.html">carbons</a></li></ul><h3><a href="global.html">Global</a></h3>
</nav>
<br clear="both">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.2</a> on Tue Sep 08 2015 14:08:28 GMT+0200 (CEST)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>
+536
Ver Arquivo
@@ -0,0 +1,536 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Source: jsxc.lib.otr.js</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Source: jsxc.lib.otr.js</h1>
<section>
<article>
<pre class="prettyprint source"><code>/**
* @namespace jsxc.otr
*/
jsxc.otr = {
/** list of otr objects */
objects: {},
dsaFallback: null,
/**
* Handler for otr receive event
*
* @memberOf jsxc.otr
* @param {Object} d
* @param {string} d.bid
* @param {string} d.msg received message
* @param {boolean} d.encrypted True, if msg was encrypted.
* @param {boolean} d.forwarded
* @param {string} d.stamp timestamp
*/
receiveMessage: function(d) {
var bid = d.bid;
if (jsxc.otr.objects[bid].msgstate !== OTR.CONST.MSGSTATE_PLAINTEXT) {
jsxc.otr.backup(bid);
}
if (jsxc.otr.objects[bid].msgstate !== OTR.CONST.MSGSTATE_PLAINTEXT && !d.encrypted) {
jsxc.gui.window.postMessage(bid, 'sys', $.t('Received_an_unencrypted_message') + '. [' + d.msg + ']', d.encrypted, d.forwarded, d.stamp);
} else {
jsxc.gui.window.postMessage(bid, 'in', d.msg, d.encrypted, d.forwarded, d.stamp);
}
},
/**
* Handler for otr send event
*
* @param {string} jid
* @param {string} msg message to be send
*/
sendMessage: function(jid, msg, uid) {
if (jsxc.otr.objects[jsxc.jidToBid(jid)].msgstate !== 0) {
jsxc.otr.backup(jsxc.jidToBid(jid));
}
jsxc.xmpp._sendMessage(jid, msg, uid);
},
/**
* Create new otr instance
*
* @param {type} bid
* @returns {undefined}
*/
create: function(bid) {
if (jsxc.otr.objects.hasOwnProperty(bid)) {
return;
}
if (!jsxc.options.otr.priv) {
return;
}
// save list of otr objects
var ol = jsxc.storage.getUserItem('otrlist') || [];
if (ol.indexOf(bid) &lt; 0) {
ol.push(bid);
jsxc.storage.setUserItem('otrlist', ol);
}
jsxc.otr.objects[bid] = new OTR(jsxc.options.otr);
if (jsxc.options.otr.SEND_WHITESPACE_TAG) {
jsxc.otr.objects[bid].SEND_WHITESPACE_TAG = true;
}
if (jsxc.options.otr.WHITESPACE_START_AKE) {
jsxc.otr.objects[bid].WHITESPACE_START_AKE = true;
}
jsxc.otr.objects[bid].on('status', function(status) {
var data = jsxc.storage.getUserItem('buddy', bid);
if (data === null) {
return;
}
switch (status) {
case OTR.CONST.STATUS_SEND_QUERY:
jsxc.gui.window.postMessage(bid, 'sys', $.t('trying_to_start_private_conversation'));
break;
case OTR.CONST.STATUS_AKE_SUCCESS:
data.fingerprint = jsxc.otr.objects[bid].their_priv_pk.fingerprint();
data.msgstate = OTR.CONST.MSGSTATE_ENCRYPTED;
var msg_state = jsxc.otr.objects[bid].trust ? 'Verified' : 'Unverified';
var msg = $.t(msg_state + '_private_conversation_started');
jsxc.gui.window.postMessage(bid, 'sys', msg);
break;
case OTR.CONST.STATUS_END_OTR:
data.fingerprint = null;
if (jsxc.otr.objects[bid].msgstate === OTR.CONST.MSGSTATE_PLAINTEXT) {
// we abort the private conversation
data.msgstate = OTR.CONST.MSGSTATE_PLAINTEXT;
jsxc.gui.window.postMessage(bid, 'sys', $.t('private_conversation_aborted'));
} else {
// the buddy abort the private conversation
data.msgstate = OTR.CONST.MSGSTATE_FINISHED;
jsxc.gui.window.postMessage(bid, 'sys', $.t('your_buddy_closed_the_private_conversation_you_should_do_the_same'));
}
break;
case OTR.CONST.STATUS_SMP_HANDLE:
jsxc.keepBusyAlive();
break;
}
jsxc.storage.setUserItem('buddy', bid, data);
// for encryption and verification state
jsxc.gui.update(bid);
});
jsxc.otr.objects[bid].on('smp', function(type, data) {
switch (type) {
case 'question': // verification request received
jsxc.gui.window.postMessage(bid, 'sys', $.t('Authentication_request_received'));
if ($('#jsxc_dialog').length > 0) {
jsxc.otr.objects[bid].sm.abort();
break;
}
jsxc.otr.onSmpQuestion(bid, data);
jsxc.storage.setUserItem('smp_' + bid, {
data: data || null
});
break;
case 'trust': // verification completed
jsxc.otr.objects[bid].trust = data;
jsxc.storage.updateUserItem('buddy', bid, 'trust', data);
jsxc.otr.backup(bid);
jsxc.gui.update(bid);
if (data) {
jsxc.gui.window.postMessage(bid, 'sys', $.t('conversation_is_now_verified'));
} else {
jsxc.gui.window.postMessage(bid, 'sys', $.t('authentication_failed'));
}
jsxc.storage.removeUserItem('smp_' + bid);
jsxc.gui.dialog.close();
break;
case 'abort':
jsxc.gui.window.postMessage(bid, 'sys', $.t('Authentication_aborted'));
break;
default:
jsxc.debug('[OTR] sm callback: Unknown type: ' + type);
}
});
// Receive message
jsxc.otr.objects[bid].on('ui', function(msg, encrypted, meta) {
jsxc.otr.receiveMessage({
bid: bid,
msg: msg,
encrypted: encrypted === true,
stamp: meta.stamp,
forwarded: meta.forwarded
});
});
// Send message
jsxc.otr.objects[bid].on('io', function(msg, uid) {
var jid = jsxc.gui.window.get(bid).data('jid') || jsxc.otr.objects[bid].jid;
jsxc.otr.objects[bid].jid = jid;
jsxc.otr.sendMessage(jid, msg, uid);
});
jsxc.otr.objects[bid].on('error', function(err) {
// Handle this case in jsxc.otr.receiveMessage
if (err !== 'Received an unencrypted message.') {
jsxc.gui.window.postMessage(bid, 'sys', '[OTR] ' + $.t(err));
}
jsxc.error('[OTR] ' + err);
});
jsxc.otr.restore(bid);
},
/**
* show verification dialog with related part (secret or question)
*
* @param {type} bid
* @param {string} [data]
* @returns {undefined}
*/
onSmpQuestion: function(bid, data) {
jsxc.gui.showVerification(bid);
$('#jsxc_dialog select').prop('selectedIndex', (data ? 2 : 3)).change();
$('#jsxc_dialog > div:eq(0)').hide();
if (data) {
$('#jsxc_dialog > div:eq(2)').find('#jsxc_quest').val(data).prop('disabled', true);
$('#jsxc_dialog > div:eq(2)').find('.jsxc_submit').text($('Answer'));
$('#jsxc_dialog > div:eq(2)').find('.jsxc_explanation').text($.t('onsmp_explanation_question'));
} else {
$('#jsxc_dialog > div:eq(3)').find('.jsxc_explanation').text($.t('onsmp_explanation_secret'));
}
$('#jsxc_dialog .jsxc_close').click(function() {
jsxc.storage.removeUserItem('smp_' + bid);
if (jsxc.master) {
jsxc.otr.objects[bid].sm.abort();
}
});
},
/**
* Send verification request to buddy
*
* @param {string} bid
* @param {string} sec secret
* @param {string} [quest] question
* @returns {undefined}
*/
sendSmpReq: function(bid, sec, quest) {
jsxc.keepBusyAlive();
jsxc.otr.objects[bid].smpSecret(sec, quest || '');
},
/**
* Toggle encryption state
*
* @param {type} bid
* @returns {undefined}
*/
toggleTransfer: function(bid) {
if (typeof OTR !== 'function') {
return;
}
if (jsxc.storage.getUserItem('buddy', bid).msgstate === 0) {
jsxc.otr.goEncrypt(bid);
} else {
jsxc.otr.goPlain(bid);
}
},
/**
* Send request to encrypt the session
*
* @param {type} bid
* @returns {undefined}
*/
goEncrypt: function(bid) {
if (jsxc.master) {
if (jsxc.otr.objects.hasOwnProperty(bid)) {
jsxc.otr.objects[bid].sendQueryMsg();
}
} else {
jsxc.storage.updateUserItem('buddy', bid, 'transferReq', 1);
}
},
/**
* Abort encryptet session
*
* @param {type} bid
* @param cb callback
* @returns {undefined}
*/
goPlain: function(bid, cb) {
if (jsxc.master) {
if (jsxc.otr.objects.hasOwnProperty(bid)) {
jsxc.otr.objects[bid].endOtr.call(jsxc.otr.objects[bid], cb);
jsxc.otr.objects[bid].init.call(jsxc.otr.objects[bid]);
jsxc.otr.backup(bid);
}
} else {
jsxc.storage.updateUserItem('buddy', bid, 'transferReq', 0);
}
},
/**
* Backups otr session
*
* @param {string} bid
*/
backup: function(bid) {
var o = jsxc.otr.objects[bid]; // otr object
var r = {}; // return value
if (o === null) {
return;
}
// all variables which should be saved
var savekey = ['jid', 'our_instance_tag', 'msgstate', 'authstate', 'fragment', 'their_y', 'their_old_y', 'their_keyid', 'their_instance_tag', 'our_dh', 'our_old_dh', 'our_keyid', 'sessKeys', 'storedMgs', 'oldMacKeys', 'trust', 'transmittedRS', 'ssid', 'receivedPlaintext', 'authstate', 'send_interval'];
var i;
for (i = 0; i &lt; savekey.length; i++) {
r[savekey[i]] = JSON.stringify(o[savekey[i]]);
}
if (o.their_priv_pk !== null) {
r.their_priv_pk = JSON.stringify(o.their_priv_pk.packPublic());
}
if (o.ake.otr_version && o.ake.otr_version !== '') {
r.otr_version = JSON.stringify(o.ake.otr_version);
}
jsxc.storage.setUserItem('otr', bid, r);
},
/**
* Restore old otr session
*
* @param {string} bid
*/
restore: function(bid) {
var o = jsxc.otr.objects[bid];
var d = jsxc.storage.getUserItem('otr', bid);
if (o !== null || d !== null) {
var key;
for (key in d) {
if (d.hasOwnProperty(key)) {
var val = JSON.parse(d[key]);
if (key === 'their_priv_pk' && val !== null) {
val = DSA.parsePublic(val);
}
if (key === 'otr_version' && val !== null) {
o.ake.otr_version = val;
} else {
o[key] = val;
}
}
}
jsxc.otr.objects[bid] = o;
if (o.msgstate === 1 && o.their_priv_pk !== null) {
o._smInit.call(jsxc.otr.objects[bid]);
}
}
jsxc.otr.enable(bid);
},
/**
* Create or load DSA key
*
* @returns {unresolved}
*/
createDSA: function() {
if (jsxc.options.otr.priv) {
return;
}
if (typeof OTR !== 'function') {
jsxc.warn('OTR support disabled');
OTR = {};
OTR.CONST = {
MSGSTATE_PLAINTEXT: 0,
MSGSTATE_ENCRYPTED: 1,
MSGSTATE_FINISHED: 2
};
jsxc._onMaster();
return;
}
if (jsxc.storage.getUserItem('key') === null) {
var msg = $.t('Creating_your_private_key_');
var worker = null;
if (Worker) {
// try to create web-worker
try {
worker = new Worker(jsxc.options.root + '/lib/otr/lib/dsa-webworker.js');
} catch (err) {
jsxc.warn('Couldn\'t create web-worker.', err);
}
}
jsxc.otr.dsaFallback = (worker === null);
if (!jsxc.otr.dsaFallback) {
// create DSA key in background
jsxc._onMaster();
worker.onmessage = function(e) {
var type = e.data.type;
var val = e.data.val;
if (type === 'debug') {
jsxc.debug(val);
} else if (type === 'data') {
jsxc.otr.DSAready(DSA.parsePrivate(val));
}
};
// start worker
worker.postMessage({
imports: [jsxc.options.root + '/lib/otr/vendor/salsa20.js', jsxc.options.root + '/lib/otr/vendor/bigint.js', jsxc.options.root + '/lib/otr/vendor/crypto.js', jsxc.options.root + '/lib/otr/vendor/eventemitter.js', jsxc.options.root + '/lib/otr/lib/const.js', jsxc.options.root + '/lib/otr/lib/helpers.js', jsxc.options.root + '/lib/otr/lib/dsa.js'],
seed: BigInt.getSeed(),
debug: true
});
} else {
// fallback
jsxc.gui.dialog.open(jsxc.gui.template.get('waitAlert', null, msg), {
noClose: true
});
jsxc.debug('DSA key creation started.');
// wait until the wait alert is opened
setTimeout(function() {
var dsa = new DSA();
jsxc.otr.DSAready(dsa);
}, 500);
}
} else {
jsxc.debug('DSA key loaded');
jsxc.options.otr.priv = DSA.parsePrivate(jsxc.storage.getUserItem('key'));
jsxc.otr._createDSA();
}
},
/**
* Ending of createDSA().
*/
_createDSA: function() {
jsxc.storage.setUserItem('priv_fingerprint', jsxc.options.otr.priv.fingerprint());
if (jsxc.otr.dsaFallback !== false) {
jsxc._onMaster();
}
},
/**
* Ending of DSA key generation.
*
* @param {DSA} dsa DSA object
*/
DSAready: function(dsa) {
jsxc.storage.setUserItem('key', dsa.packPrivate());
jsxc.options.otr.priv = dsa;
// close wait alert
if (jsxc.otr.dsaFallback) {
jsxc.gui.dialog.close();
} else {
$.each(jsxc.storage.getUserItem('windowlist'), function(index, val) {
jsxc.otr.create(val);
});
}
jsxc.otr._createDSA();
},
enable: function(bid) {
jsxc.gui.window.get(bid).find('.jsxc_otr').removeClass('jsxc_disabled');
}
};
</code></pre>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Index</a></h2><h3>Namespaces</h3><ul><li><a href="jsxc.html">jsxc</a></li><li><a href="jsxc.gui.html">gui</a></li><li><a href="jsxc.gui.dialog.html">dialog</a></li><li><a href="jsxc.gui.queryActions.html">queryActions</a></li><li><a href="jsxc.gui.roster.html">roster</a></li><li><a href="jsxc.gui.window.html">window</a></li><li><a href="jsxc.muc.html">muc</a></li><li><a href="jsxc.notification.html">notification</a></li><li><a href="jsxc.options.html">options</a></li><li><a href="jsxc.otr.html">otr</a></li><li><a href="jsxc.storage.html">storage</a></li><li><a href="jsxc.webrtc.html">webrtc</a></li><li><a href="jsxc.xmpp.html">xmpp</a></li><li><a href="jsxc.xmpp.bookmarks.html">bookmarks</a></li><li><a href="jsxc.xmpp.carbons.html">carbons</a></li></ul><h3><a href="global.html">Global</a></h3>
</nav>
<br clear="both">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.2</a> on Tue Sep 08 2015 14:08:28 GMT+0200 (CEST)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>
+679
Ver Arquivo
@@ -0,0 +1,679 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Source: jsxc.lib.storage.js</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Source: jsxc.lib.storage.js</h1>
<section>
<article>
<pre class="prettyprint source"><code>/**
* Handle long-live data
*
* @namespace jsxc.storage
*/
jsxc.storage = {
/**
* Prefix for localstorage
*
* @privat
*/
PREFIX: 'jsxc',
SEP: ':',
/**
* @param {type} uk Should we generate a user prefix?
* @returns {String} prefix
* @memberOf jsxc.storage
*/
getPrefix: function(uk) {
var self = jsxc.storage;
return self.PREFIX + self.SEP + ((uk && jsxc.bid) ? jsxc.bid + self.SEP : '');
},
/**
* Save item to storage
*
* @function
* @param {String} key variablename
* @param {Object} value value
* @param {String} uk Userkey? Should we add the bid as prefix?
*/
setItem: function(key, value, uk) {
// Workaround for non-conform browser
if (jsxc.storageNotConform > 0 && key !== 'rid' && key !== 'lastActivity') {
if (jsxc.storageNotConform > 1 && jsxc.toSNC === null) {
jsxc.toSNC = window.setTimeout(function() {
jsxc.storageNotConform = 0;
jsxc.storage.setItem('storageNotConform', 0);
}, 1000);
}
jsxc.ls.push(JSON.stringify({
key: key,
value: value
}));
}
if (typeof(value) === 'object') {
// exclude jquery objects, because otherwise safari will fail
value = JSON.stringify(value, function(key, val) {
if (!(val instanceof jQuery)) {
return val;
}
});
}
localStorage.setItem(jsxc.storage.getPrefix(uk) + key, value);
},
setUserItem: function(type, key, value) {
var self = jsxc.storage;
if (arguments.length === 2) {
value = key;
key = type;
type = '';
} else if (arguments.length === 3) {
key = type + self.SEP + key;
}
return jsxc.storage.setItem(key, value, true);
},
/**
* Load item from storage
*
* @function
* @param {String} key variablename
* @param {String} uk Userkey? Should we add the bid as prefix?
*/
getItem: function(key, uk) {
key = jsxc.storage.getPrefix(uk) + key;
var value = localStorage.getItem(key);
try {
return JSON.parse(value);
} catch (e) {
return value;
}
},
/**
* Get a user item from storage.
*
* @param key
* @returns user item
*/
getUserItem: function(type, key) {
var self = jsxc.storage;
if (arguments.length === 1) {
key = type;
} else if (arguments.length === 2) {
key = type + self.SEP + key;
}
return jsxc.storage.getItem(key, true);
},
/**
* Remove item from storage
*
* @function
* @param {String} key variablename
* @param {String} uk Userkey? Should we add the bid as prefix?
*/
removeItem: function(key, uk) {
// Workaround for non-conform browser
if (jsxc.storageNotConform && key !== 'rid' && key !== 'lastActivity') {
jsxc.ls.push(JSON.stringify({
key: jsxc.storage.prefix + key,
value: ''
}));
}
localStorage.removeItem(jsxc.storage.getPrefix(uk) + key);
},
/**
* Remove user item from storage.
*
* @param key
*/
removeUserItem: function(type, key) {
var self = jsxc.storage;
if (arguments.length === 1) {
key = type;
} else if (arguments.length === 2) {
key = type + self.SEP + key;
}
jsxc.storage.removeItem(key, true);
},
/**
* Updates value of a variable in a saved object.
*
* @function
* @param {String} key variablename
* @param {String|object} variable variablename in object or object with
* variable/key pairs
* @param {Object} [value] value
* @param {String} uk Userkey? Should we add the bid as prefix?
*/
updateItem: function(key, variable, value, uk) {
var data = jsxc.storage.getItem(key, uk) || {};
if (typeof(variable) === 'object') {
$.each(variable, function(key, val) {
if (typeof(data[key]) === 'undefined') {
jsxc.debug('Variable ' + key + ' doesn\'t exist in ' + variable + '. It was created.');
}
data[key] = val;
});
} else {
if (typeof(data[variable]) === 'undefined') {
jsxc.debug('Variable ' + variable + ' doesn\'t exist. It was created.');
}
data[variable] = value;
}
jsxc.storage.setItem(key, data, uk);
},
/**
* Updates value of a variable in a saved user object.
*
* @param {String} key variablename
* @param {String|object} variable variablename in object or object with
* variable/key pairs
* @param {Object} [value] value
*/
updateUserItem: function(type, key, variable, value) {
var self = jsxc.storage;
if (arguments.length === 4 || (arguments.length === 3 && typeof variable === 'object')) {
key = type + self.SEP + key;
} else {
value = variable;
variable = key;
key = type;
}
return jsxc.storage.updateItem(key, variable, value, true);
},
/**
* Inkrements value
*
* @function
* @param {String} key variablename
* @param {String} uk Userkey? Should we add the bid as prefix?
*/
ink: function(key, uk) {
jsxc.storage.setItem(key, Number(jsxc.storage.getItem(key, uk)) + 1, uk);
},
/**
* Remove element from array or object
*
* @param {string} key name of array or object
* @param {string} name name of element in array or object
* @param {String} uk Userkey? Should we add the bid as prefix?
* @returns {undefined}
*/
removeElement: function(key, name, uk) {
var item = jsxc.storage.getItem(key, uk);
if ($.isArray(item)) {
item = $.grep(item, function(e) {
return e !== name;
});
} else if (typeof(item) === 'object' && item !== null) {
delete item[name];
}
jsxc.storage.setItem(key, item, uk);
},
removeUserElement: function(type, key, name) {
var self = jsxc.storage;
if (arguments.length === 2) {
name = key;
key = type;
} else if (arguments.length === 3) {
key = type + self.SEP + key;
}
return jsxc.storage.removeElement(key, name, true);
},
/**
* Triggered if changes are recognized
*
* @function
* @param {event} e Storageevent
* @param {String} e.key Keyname which triggered event
* @param {Object} e.oldValue Old Value for key
* @param {Object} e.newValue New Value for key
* @param {String} e.url
*/
onStorage: function(e) {
// skip
if (e.key === jsxc.storage.PREFIX + jsxc.storage.SEP + 'rid' || e.key === jsxc.storage.PREFIX + jsxc.storage.SEP + 'lastActivity') {
return;
}
var re = new RegExp('^' + jsxc.storage.PREFIX + jsxc.storage.SEP + '(?:[^' + jsxc.storage.SEP + ']+@[^' + jsxc.storage.SEP + ']+' + jsxc.storage.SEP + ')?(.*)', 'i');
var key = e.key.replace(re, '$1');
// Workaround for non-conform browser: Triggered event on every page
// (own)
if (jsxc.storageNotConform > 0 && jsxc.ls.length > 0) {
var val = e.newValue;
try {
val = JSON.parse(val);
} catch (err) {}
var index = $.inArray(JSON.stringify({
key: key,
value: val
}), jsxc.ls);
if (index >= 0) {
// confirm that the storage event is not fired regularly
if (jsxc.storageNotConform > 1) {
window.clearTimeout(jsxc.toSNC);
jsxc.storageNotConform = 1;
jsxc.storage.setItem('storageNotConform', 1);
}
jsxc.ls.splice(index, 1);
return;
}
}
// Workaround for non-conform browser
if (e.oldValue === e.newValue) {
return;
}
var n, o;
var bid = key.replace(new RegExp('[^' + jsxc.storage.SEP + ']+' + jsxc.storage.SEP + '(.*)', 'i'), '$1');
// react if someone ask, if there is a master
if (jsxc.master && key === 'alive') {
jsxc.debug('Master request.');
jsxc.storage.ink('alive');
return;
}
// master alive
if (!jsxc.master && (key === 'alive' || key === 'alive_busy') && !jsxc.triggeredFromElement) {
// reset timeout
window.clearTimeout(jsxc.to);
jsxc.to = window.setTimeout(jsxc.checkMaster, ((key === 'alive') ? jsxc.options.timeout : jsxc.options.busyTimeout) + jsxc.random(60));
// only call the first time
if (!jsxc.role_allocation) {
jsxc.onSlave();
}
return;
}
if (key.match(/^notices/)) {
jsxc.notice.load();
}
if (key.match(/^presence/)) {
jsxc.gui.changePresence(e.newValue, true);
}
if (key.match(/^options/) && e.newValue) {
n = JSON.parse(e.newValue);
if (typeof n.muteNotification !== 'undefined' && n.muteNotification) {
jsxc.notification.muteSound(true);
} else {
jsxc.notification.unmuteSound(true);
}
}
if (key.match(/^hidden/)) {
if (jsxc.master) {
clearTimeout(jsxc.toNotification);
} else {
jsxc.isHidden();
}
}
if (key.match(/^focus/)) {
if (jsxc.master) {
clearTimeout(jsxc.toNotification);
} else {
jsxc.hasFocus();
}
}
if (key.match(new RegExp('^chat' + jsxc.storage.SEP))) {
var posts = JSON.parse(e.newValue);
var data, el;
while (posts.length > 0) {
data = posts.pop();
el = $('#' + data.uid);
if (el.length === 0) {
if (jsxc.master && data.direction === 'out') {
jsxc.xmpp.sendMessage(bid, data.msg, data.uid);
}
jsxc.gui.window._postMessage(bid, data);
} else if (data.received) {
el.addClass('jsxc_received');
}
}
return;
}
if (key.match(new RegExp('^window' + jsxc.storage.SEP))) {
if (!e.newValue) {
jsxc.gui.window._close(bid);
return;
}
if (!e.oldValue) {
jsxc.gui.window.open(bid);
return;
}
n = JSON.parse(e.newValue);
o = JSON.parse(e.oldValue);
if (n.minimize !== o.minimize) {
if (n.minimize) {
jsxc.gui.window._hide(bid);
} else {
jsxc.gui.window._show(bid);
}
}
jsxc.gui.window.setText(bid, n.text);
if (n.unread !== o.unread) {
if (n.unread === 0) {
jsxc.gui.readMsg(bid);
} else {
jsxc.gui._unreadMsg(bid, n.unread);
}
}
return;
}
if (key.match(/^unreadMsg/) && jsxc.gui.favicon) {
jsxc.gui.favicon.badge(parseInt(e.newValue) || 0);
}
if (key.match(new RegExp('^smp' + jsxc.storage.SEP))) {
if (!e.newValue) {
jsxc.gui.dialog.close();
if (jsxc.master) {
jsxc.otr.objects[bid].sm.abort();
}
return;
}
n = JSON.parse(e.newValue);
if (typeof(n.data) !== 'undefined') {
jsxc.otr.onSmpQuestion(bid, n.data);
} else if (jsxc.master && n.sec) {
jsxc.gui.dialog.close();
jsxc.otr.sendSmpReq(bid, n.sec, n.quest);
}
}
if (!jsxc.master && key.match(new RegExp('^buddy' + jsxc.storage.SEP))) {
if (!e.newValue) {
jsxc.gui.roster.purge(bid);
return;
}
if (!e.oldValue) {
jsxc.gui.roster.add(bid);
return;
}
n = JSON.parse(e.newValue);
o = JSON.parse(e.oldValue);
jsxc.gui.update(bid);
if (o.status !== n.status || o.sub !== n.sub) {
jsxc.gui.roster.reorder(bid);
}
}
if (jsxc.master && key.match(new RegExp('^deletebuddy' + jsxc.storage.SEP)) && e.newValue) {
n = JSON.parse(e.newValue);
jsxc.xmpp.removeBuddy(n.jid);
jsxc.storage.removeUserItem(key);
}
if (jsxc.master && key.match(new RegExp('^buddy' + jsxc.storage.SEP))) {
n = JSON.parse(e.newValue);
o = JSON.parse(e.oldValue);
if (o.transferReq !== n.transferReq) {
jsxc.storage.updateUserItem('buddy', bid, 'transferReq', -1);
if (n.transferReq === 0) {
jsxc.otr.goPlain(bid);
}
if (n.transferReq === 1) {
jsxc.otr.goEncrypt(bid);
}
}
if (o.name !== n.name) {
jsxc.gui.roster._rename(bid, n.name);
}
}
// logout
if (key === 'sid') {
if (!e.newValue) {
// if (jsxc.master && jsxc.xmpp.conn) {
// jsxc.xmpp.conn.disconnect();
// jsxc.triggeredFromElement = true;
// }
jsxc.xmpp.logout();
}
return;
}
if (key === 'friendReq') {
n = JSON.parse(e.newValue);
if (jsxc.master && n.approve >= 0) {
jsxc.xmpp.resFriendReq(n.jid, n.approve);
}
}
if (jsxc.master && key.match(new RegExp('^add' + jsxc.storage.SEP))) {
n = JSON.parse(e.newValue);
jsxc.xmpp.addBuddy(n.username, n.alias);
}
if (key === 'roster') {
jsxc.gui.roster.toggle();
}
if (jsxc.master && key.match(new RegExp('^vcard' + jsxc.storage.SEP)) && e.newValue !== null && e.newValue.match(/^request:/)) {
jsxc.xmpp.loadVcard(bid, function(stanza) {
jsxc.storage.setUserItem('vcard', bid, {
state: 'success',
data: $('&lt;div>').append(stanza).html()
});
}, function() {
jsxc.storage.setUserItem('vcard', bid, {
state: 'error'
});
});
}
if (!jsxc.master && key.match(new RegExp('^vcard' + jsxc.storage.SEP)) && e.newValue !== null && !e.newValue.match(/^request:/)) {
n = JSON.parse(e.newValue);
if (typeof n.state !== 'undefined') {
$(document).trigger('loaded.vcard.jsxc', n);
}
jsxc.storage.removeUserItem('vcard', bid);
}
},
/**
* Save message to storage.
*
* @memberOf jsxc.storage
* @param bid
* @param direction
* @param msg
* @param encrypted
* @param forwarded
* @param sender
* @return post
*/
saveMessage: function(bid, direction, msg, encrypted, forwarded, stamp, sender) {
var chat = jsxc.storage.getUserItem('chat', bid) || [];
var uid = new Date().getTime() + ':msg';
if (chat.length > jsxc.options.get('numberOfMsg')) {
chat.pop();
}
var post = {
direction: direction,
msg: msg,
uid: uid.replace(/:/, '-'),
received: false,
encrypted: encrypted || false,
forwarded: forwarded || false,
stamp: stamp || new Date().getTime(),
sender: sender
};
chat.unshift(post);
jsxc.storage.setUserItem('chat', bid, chat);
return post;
},
/**
* Save or update buddy data.
*
* @memberOf jsxc.storage
* @param bid
* @param data
* @returns {String} Updated or created
*/
saveBuddy: function(bid, data) {
if (jsxc.storage.getUserItem('buddy', bid)) {
jsxc.storage.updateUserItem('buddy', bid, data);
return 'updated';
}
jsxc.storage.setUserItem('buddy', bid, $.extend({
jid: '',
name: '',
status: 0,
sub: 'none',
msgstate: 0,
transferReq: -1,
trust: false,
fingerprint: null,
res: [],
type: 'chat'
}, data));
return 'created';
}
};
</code></pre>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Index</a></h2><h3>Namespaces</h3><ul><li><a href="jsxc.html">jsxc</a></li><li><a href="jsxc.gui.html">gui</a></li><li><a href="jsxc.gui.dialog.html">dialog</a></li><li><a href="jsxc.gui.queryActions.html">queryActions</a></li><li><a href="jsxc.gui.roster.html">roster</a></li><li><a href="jsxc.gui.window.html">window</a></li><li><a href="jsxc.muc.html">muc</a></li><li><a href="jsxc.notification.html">notification</a></li><li><a href="jsxc.options.html">options</a></li><li><a href="jsxc.otr.html">otr</a></li><li><a href="jsxc.storage.html">storage</a></li><li><a href="jsxc.webrtc.html">webrtc</a></li><li><a href="jsxc.xmpp.html">xmpp</a></li><li><a href="jsxc.xmpp.bookmarks.html">bookmarks</a></li><li><a href="jsxc.xmpp.carbons.html">carbons</a></li></ul><h3><a href="global.html">Global</a></h3>
</nav>
<br clear="both">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.2</a> on Tue Sep 08 2015 14:08:28 GMT+0200 (CEST)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+391
Ver Arquivo
@@ -0,0 +1,391 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Source: jsxc.lib.xmpp.bookmarks.js</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Source: jsxc.lib.xmpp.bookmarks.js</h1>
<section>
<article>
<pre class="prettyprint source"><code>/**
* Load and save bookmarks according to XEP-0048.
*
* @namespace jsxc.xmpp.bookmarks
*/
jsxc.xmpp.bookmarks = {};
/**
* Determines if server is able to store bookmarks.
*
* @return {boolean} True: Server supports bookmark storage
*/
jsxc.xmpp.bookmarks.remote = function() {
return jsxc.xmpp.conn.caps && jsxc.xmpp.hasFeatureByJid(jsxc.xmpp.conn.domain, Strophe.NS.PUBSUB + "#publish");
};
/**
* Load bookmarks from pubsub.
*
* @memberOf jsxc.xmpp.bookmarks
*/
jsxc.xmpp.bookmarks.load = function() {
var caps = jsxc.xmpp.conn.caps;
var ver = caps._jidVerIndex[jsxc.xmpp.conn.domain];
if (!ver || !caps._knownCapabilities[ver]) {
// wait until we know server capabilities
$(document).on('caps.strophe', function(ev, from) {
if (from === jsxc.xmpp.conn.domain) {
jsxc.xmpp.bookmarks.load();
$(document).off(ev);
}
});
}
if (jsxc.xmpp.bookmarks.remote()) {
jsxc.xmpp.bookmarks.loadFromRemote();
} else {
jsxc.xmpp.bookmarks.loadFromLocal();
}
};
/**
* Load bookmarks from local storage.
*
* @private
*/
jsxc.xmpp.bookmarks.loadFromLocal = function() {
jsxc.debug('Load bookmarks from local storage');
var bookmarks = jsxc.storage.getUserItem('bookmarks') || [];
var bl = jsxc.storage.getUserItem('buddylist') || [];
$.each(bookmarks, function() {
var room = this;
var roomdata = jsxc.storage.getUserItem('buddy', room) || {};
bl.push(room);
jsxc.gui.roster.add(room);
if (roomdata.autojoin) {
jsxc.debug('auto join ' + room);
jsxc.xmpp.conn.muc.join(room, roomdata.nickname);
}
});
jsxc.storage.setUserItem('buddylist', bl);
};
/**
* Load bookmarks from remote storage.
*
* @private
*/
jsxc.xmpp.bookmarks.loadFromRemote = function() {
jsxc.debug('Load bookmarks from pubsub');
var bookmarks = jsxc.xmpp.conn.bookmarks;
bookmarks.get(function(stanza) {
var bl = jsxc.storage.getUserItem('buddylist');
$(stanza).find('conference').each(function() {
var conference = $(this);
var room = conference.attr('jid');
var roomName = conference.attr('name') || room;
var autojoin = conference.attr('autojoin') || false;
var nickname = conference.find('nick').text();
nickname = (nickname.length > 0) ? nickname : Strophe.getNodeFromJid(jsxc.xmpp.conn.jid);
if (autojoin === 'true') {
autojoin = true;
} else if (autojoin === 'false') {
autojoin = false;
}
var data = jsxc.storage.getUserItem('buddy', room) || {};
data = $.extend(data, {
jid: room,
name: roomName,
sub: 'both',
status: 0,
type: 'groupchat',
state: jsxc.muc.CONST.ROOMSTATE.INIT,
subject: null,
bookmarked: true,
autojoin: autojoin,
nickname: nickname
});
jsxc.storage.setUserItem('buddy', room, data);
bl.push(room);
jsxc.gui.roster.add(room);
if (autojoin) {
jsxc.debug('auto join ' + room);
jsxc.xmpp.conn.muc.join(room, nickname);
}
});
jsxc.storage.setUserItem('buddylist', bl);
}, function(stanza) {
var err = jsxc.xmpp.bookmarks.parseErr(stanza);
if (err.reasons[0] === 'item-not-found') {
jsxc.debug('create bookmark node');
bookmarks.createBookmarksNode();
} else {
jsxc.debug('[XMPP] Could not create bookmark: ' + err.type, err.reasons);
}
});
};
/**
* Parse received error.
*
* @param {string} stanza
* @return {object} err - The parsed error
* @return {string} err.type - XMPP error type
* @return {array} err.reasons - Array of error reasons
*/
jsxc.xmpp.bookmarks.parseErr = function(stanza) {
var error = $(stanza).find('error');
var type = error.attr('type');
var reasons = error.children().map(function() {
return $(this).prop('tagName');
});
return {
type: type,
reasons: reasons
};
};
/**
* Deletes the bookmark for the given room and removes it from the roster if soft is false.
*
* @param {string} room - room jid
* @param {boolean} [soft=false] - True: leave room in roster
*/
jsxc.xmpp.bookmarks.delete = function(room, soft) {
if (!soft) {
jsxc.gui.roster.purge(room);
}
if (jsxc.xmpp.bookmarks.remote()) {
jsxc.xmpp.bookmarks.deleteFromRemote(room, soft);
} else {
jsxc.xmpp.bookmarks.deleteFromLocal(room, soft);
}
};
/**
* Delete bookmark from remote storage.
*
* @private
* @param {string} room - room jid
* @param {boolean} [soft=false] - True: leave room in roster
*/
jsxc.xmpp.bookmarks.deleteFromRemote = function(room, soft) {
var bookmarks = jsxc.xmpp.conn.bookmarks;
bookmarks.delete(room, function() {
jsxc.debug('Bookmark deleted ' + room);
if (soft) {
jsxc.gui.roster.getItem(room).removeClass('jsxc_bookmarked');
jsxc.storage.updateUserItem('buddy', room, 'bookmarked', false);
jsxc.storage.updateUserItem('buddy', room, 'autojoin', false);
}
}, function(stanza) {
var err = jsxc.xmpp.bookmarks.parseErr(stanza);
jsxc.debug('[XMPP] Could not delete bookmark: ' + err.type, err.reasons);
});
};
/**
* Delete bookmark from local storage.
*
* @private
* @param {string} room - room jid
* @param {boolean} [soft=false] - True: leave room in roster
*/
jsxc.xmpp.bookmarks.deleteFromLocal = function(room, soft) {
var bookmarks = jsxc.storage.getUserItem('bookmarks');
var index = bookmarks.indexOf(room);
if (index > -1) {
bookmarks.splice(index, 1);
}
jsxc.storage.setUserItem('bookmarks', bookmarks);
if (soft) {
jsxc.gui.roster.getItem(room).removeClass('jsxc_bookmarked');
jsxc.storage.updateUserItem('buddy', room, 'bookmarked', false);
jsxc.storage.updateUserItem('buddy', room, 'autojoin', false);
}
};
/**
* Adds or overwrites bookmark for given room.
*
* @param {string} room - room jid
* @param {string} alias - room alias
* @param {string} nick - preferred user nickname
* @param {boolean} autojoin - should we join this room after login?
*/
jsxc.xmpp.bookmarks.add = function(room, alias, nick, autojoin) {
if (jsxc.xmpp.bookmarks.remote()) {
jsxc.xmpp.bookmarks.addToRemote(room, alias, nick, autojoin);
} else {
jsxc.xmpp.bookmarks.addToLocal(room, alias, nick, autojoin);
}
};
/**
* Adds or overwrites bookmark for given room in remote storage.
*
* @private
* @param {string} room - room jid
* @param {string} alias - room alias
* @param {string} nick - preferred user nickname
* @param {boolean} autojoin - should we join this room after login?
*/
jsxc.xmpp.bookmarks.addToRemote = function(room, alias, nick, autojoin) {
var bookmarks = jsxc.xmpp.conn.bookmarks;
var success = function() {
jsxc.debug('New bookmark created', room);
jsxc.gui.roster.getItem(room).addClass('jsxc_bookmarked');
jsxc.storage.updateUserItem('buddy', room, 'bookmarked', true);
jsxc.storage.updateUserItem('buddy', room, 'autojoin', autojoin);
jsxc.storage.updateUserItem('buddy', room, 'nickname', nick);
};
var error = function() {
jsxc.warn('Could not create bookmark', room);
};
bookmarks.add(room, alias, nick, autojoin, success, error);
};
/**
* Adds or overwrites bookmark for given room in local storage.
*
* @private
* @param {string} room - room jid
* @param {string} alias - room alias
* @param {string} nick - preferred user nickname
* @param {boolean} autojoin - should we join this room after login?
*/
jsxc.xmpp.bookmarks.addToLocal = function(room, alias, nick, autojoin) {
jsxc.gui.roster.getItem(room).addClass('jsxc_bookmarked');
jsxc.storage.updateUserItem('buddy', room, 'bookmarked', true);
jsxc.storage.updateUserItem('buddy', room, 'autojoin', autojoin);
jsxc.storage.updateUserItem('buddy', room, 'nickname', nick);
var bookmarks = jsxc.storage.getUserItem('bookmarks') || [];
if (bookmarks.indexOf(room) &lt; 0) {
bookmarks.push(room);
jsxc.storage.setUserItem('bookmarks', bookmarks);
}
};
/**
* Show dialog to edit bookmark.
*
* @param {string} room - room jid
*/
jsxc.xmpp.bookmarks.showDialog = function(room) {
var dialog = jsxc.gui.dialog.open(jsxc.gui.template.get('bookmarkDialog'));
var data = jsxc.storage.getUserItem('buddy', room);
$('#jsxc_room').val(room);
$('#jsxc_nickname').val(data.nickname);
$('#jsxc_bookmark').change(function() {
if ($(this).prop('checked')) {
$('#jsxc_nickname').prop('disabled', false);
$('#jsxc_autojoin').prop('disabled', false);
$('#jsxc_autojoin').parent('.checkbox').removeClass('disabled');
} else {
$('#jsxc_nickname').prop('disabled', true);
$('#jsxc_autojoin').prop('disabled', true).prop('checked', false);
$('#jsxc_autojoin').parent('.checkbox').addClass('disabled');
}
});
$('#jsxc_bookmark').prop('checked', data.bookmarked);
$('#jsxc_autojoin').prop('checked', data.autojoin);
$('#jsxc_bookmark').change();
dialog.find('form').submit(function(ev) {
ev.preventDefault();
var bookmarked = $('#jsxc_bookmark').prop('checked');
var autojoin = $('#jsxc_autojoin').prop('checked');
var nickname = $('#jsxc_nickname').val();
if (bookmarked) {
jsxc.xmpp.bookmarks.add(room, data.name, nickname, autojoin);
} else if (data.bookmarked) {
// bookmarked === false
jsxc.xmpp.bookmarks.delete(room, true);
}
jsxc.gui.dialog.close();
return false;
});
};
</code></pre>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Index</a></h2><h3>Namespaces</h3><ul><li><a href="jsxc.html">jsxc</a></li><li><a href="jsxc.gui.html">gui</a></li><li><a href="jsxc.gui.dialog.html">dialog</a></li><li><a href="jsxc.gui.queryActions.html">queryActions</a></li><li><a href="jsxc.gui.roster.html">roster</a></li><li><a href="jsxc.gui.window.html">window</a></li><li><a href="jsxc.muc.html">muc</a></li><li><a href="jsxc.notification.html">notification</a></li><li><a href="jsxc.options.html">options</a></li><li><a href="jsxc.otr.html">otr</a></li><li><a href="jsxc.storage.html">storage</a></li><li><a href="jsxc.webrtc.html">webrtc</a></li><li><a href="jsxc.xmpp.html">xmpp</a></li><li><a href="jsxc.xmpp.bookmarks.html">bookmarks</a></li><li><a href="jsxc.xmpp.carbons.html">carbons</a></li></ul><h3><a href="global.html">Global</a></h3>
</nav>
<br clear="both">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.2</a> on Tue Sep 08 2015 14:08:28 GMT+0200 (CEST)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+3362
Ver Arquivo
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+2033
Ver Arquivo
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+464
Ver Arquivo
@@ -0,0 +1,464 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Namespace: carbons</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Namespace: carbons</h1>
<section>
<header>
<h2>
<span class="ancestors"><a href="jsxc.html">jsxc</a><a href="jsxc.xmpp.html">.xmpp</a>.</span>
carbons
</h2>
</header>
<article>
<div class="container-overview">
<div class="description">Handle carbons (XEP-0280);</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="jsxc.lib.xmpp.js.html">jsxc.lib.xmpp.js</a>, <a href="jsxc.lib.xmpp.js.html#line1121">line 1121</a>
</li></ul></dd>
</dl>
</div>
<h3 class="subsection-title">Methods</h3>
<dl>
<dt>
<h4 class="name" id="disable"><span class="type-signature">&lt;static> </span>disable<span class="signature">(cb)</span><span class="type-signature"></span></h4>
</dt>
<dd>
<div class="description">
Disable carbons.
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>cb</code></td>
<td class="type">
</td>
<td class="description last">callback</td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="jsxc.lib.xmpp.js.html">jsxc.lib.xmpp.js</a>, <a href="jsxc.lib.xmpp.js.html#line1161">line 1161</a>
</li></ul></dd>
</dl>
</dd>
<dt>
<h4 class="name" id="enable"><span class="type-signature">&lt;static> </span>enable<span class="signature">(cb)</span><span class="type-signature"></span></h4>
</dt>
<dd>
<div class="description">
Enable carbons.
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>cb</code></td>
<td class="type">
</td>
<td class="description last">callback</td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="jsxc.lib.xmpp.js.html">jsxc.lib.xmpp.js</a>, <a href="jsxc.lib.xmpp.js.html#line1135">line 1135</a>
</li></ul></dd>
</dl>
</dd>
<dt>
<h4 class="name" id="refresh"><span class="type-signature">&lt;static> </span>refresh<span class="signature">(err)</span><span class="type-signature"></span></h4>
</dt>
<dd>
<div class="description">
Enable/Disable carbons depending on options key.
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>err</code></td>
<td class="type">
</td>
<td class="description last">error message</td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="jsxc.lib.xmpp.js.html">jsxc.lib.xmpp.js</a>, <a href="jsxc.lib.xmpp.js.html#line1187">line 1187</a>
</li></ul></dd>
</dl>
</dd>
</dl>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Index</a></h2><h3>Namespaces</h3><ul><li><a href="jsxc.html">jsxc</a></li><li><a href="jsxc.gui.html">gui</a></li><li><a href="jsxc.gui.dialog.html">dialog</a></li><li><a href="jsxc.gui.queryActions.html">queryActions</a></li><li><a href="jsxc.gui.roster.html">roster</a></li><li><a href="jsxc.gui.window.html">window</a></li><li><a href="jsxc.muc.html">muc</a></li><li><a href="jsxc.notification.html">notification</a></li><li><a href="jsxc.options.html">options</a></li><li><a href="jsxc.otr.html">otr</a></li><li><a href="jsxc.storage.html">storage</a></li><li><a href="jsxc.webrtc.html">webrtc</a></li><li><a href="jsxc.xmpp.html">xmpp</a></li><li><a href="jsxc.xmpp.bookmarks.html">bookmarks</a></li><li><a href="jsxc.xmpp.carbons.html">carbons</a></li></ul><h3><a href="global.html">Global</a></h3>
</nav>
<br clear="both">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.2</a> on Tue Sep 08 2015 14:08:29 GMT+0200 (CEST)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>
+2766
Ver Arquivo
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+17
Ver Arquivo
@@ -0,0 +1,17 @@
(function() {
var counter = 0;
var numbered;
var source = document.getElementsByClassName('prettyprint source');
if (source && source[0]) {
source = source[0].getElementsByTagName('code')[0];
numbered = source.innerHTML.split('\n');
numbered = numbered.map(function(item) {
counter++;
return '<span id="line' + counter + '" class="line"></span>' + item;
});
source.innerHTML = numbered.join('\n');
}
})();
+202
Ver Arquivo
@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Alguns arquivos não foram exibidos porque demasiados arquivos foram alterados neste diff Mostrar Mais