Merge branch '0.8'
Conflicts: CONTRIBUTING.rst Makefile README.rst bower.json docs/CHANGES.rst docs/doctrees/index.doctree docs/html/_sources/index.txt docs/html/index.html docs/html/searchindex.js docs/source/index.rst
This commit is contained in:
commit
1dff3ac002
3
.gitignore
vendored
3
.gitignore
vendored
@ -12,7 +12,8 @@ node_modules
|
||||
components
|
||||
docs/doctrees/environment.pickle
|
||||
tags
|
||||
test-reports
|
||||
stamp-npm
|
||||
stamp-bower
|
||||
|
||||
# OSX
|
||||
.DS_Store
|
||||
|
@ -2,7 +2,7 @@
|
||||
Contribution Guidelines
|
||||
=======================
|
||||
|
||||
Firstly, thanks for contributing to Converse.js_.
|
||||
Thanks for contributing to `Converse.js <http://conversejs.org>`_.
|
||||
|
||||
Support questions
|
||||
=================
|
||||
@ -20,21 +20,18 @@ Before submitting a pull request
|
||||
|
||||
Add tests for your bugfix or feature
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Add a test for any bug fixed or feature added. We use Jasmine
|
||||
for testing.
|
||||
|
||||
Take a look at ``tests.html`` and ``spec/MainSpec.js`` to see how
|
||||
the tests are implemented.
|
||||
Take a look at `tests.html <https://github.com/jcbrand/converse.js/blob/master/tests.html>`_
|
||||
and the `spec files <https://github.com/jcbrand/converse.js/blob/master/tests.html>`_
|
||||
to see how tests are implemented.
|
||||
|
||||
Check that the tests pass
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Check that the Jasmine tests complete sucessfully. Open tests.html in your
|
||||
browser, and the tests will run automatically.
|
||||
|
||||
On the command line you can run ``grunt test`` (if you have before run ``npm
|
||||
install``).
|
||||
Check that the Jasmine tests complete sucessfully. Open
|
||||
`tests.html <https://github.com/jcbrand/converse.js/blob/master/tests.html>`_
|
||||
in your browser, and the tests will run automatically.
|
||||
|
||||
Check your code for errors or bad habits by running JSHint
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@ -42,5 +39,3 @@ If you haven't yet done so, run ``npm install`` to install all development
|
||||
dependencies.
|
||||
|
||||
Then run ``grunt jshint`` and check the output.
|
||||
|
||||
.. _Converse.js: http://conversejs.org
|
||||
|
69
Makefile
69
Makefile
@ -1,14 +1,12 @@
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
PAPER =
|
||||
BUILDDIR = ./docs
|
||||
|
||||
BOWER ?= node_modules/.bin/bower
|
||||
BUILDDIR = ./docs
|
||||
PAPER =
|
||||
PHANTOMJS ?= node_modules/.bin/phantomjs
|
||||
SPHINXBUILD = sphinx-build
|
||||
SPHINXOPTS =
|
||||
|
||||
# Internal variables.
|
||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||
PAPEROPT_letter = -D latex_paper_size=letter
|
||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) ./docs/source
|
||||
# the i18n builder cannot share the environment and doctrees with the others
|
||||
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) ./docs/source
|
||||
@ -19,34 +17,34 @@ all: dev
|
||||
|
||||
help:
|
||||
@echo "Please use \`make <target>' where <target> is one of"
|
||||
@echo " changes to make an overview of all changed/added/deprecated items"
|
||||
@echo " devhelp to make HTML files and a Devhelp project"
|
||||
@echo " dirhtml to make HTML files named index.html in directories"
|
||||
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||
@echo " epub to export the documentation to epub"
|
||||
@echo " dev to set up the development environment"
|
||||
@echo " gettext to make PO message catalogs of the documentation"
|
||||
@echo " html to make standalone HTML files of the documentation"
|
||||
@echo " htmlhelp to make HTML files and a HTML help project from the documentation"
|
||||
@echo " info to make Texinfo files and run them through makeinfo"
|
||||
@echo " json to make JSON files"
|
||||
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||
@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
||||
@echo " linkcheck to check all external links for integrity"
|
||||
@echo " pot generates a gettext POT file to be used for translations"
|
||||
@echo " pot to generate a gettext POT file to be used for translations"
|
||||
@echo " po to generate gettext PO files for each i18n language"
|
||||
@echo " po2json to generate JSON files from the language PO files"
|
||||
@echo " release to make a new minified release"
|
||||
@echo " linkcheck to check all documentation external links for integrity"
|
||||
@echo " epub to export the documentation to epub"
|
||||
@echo " changes to make an overview of all changed/added/deprecated items added to the documentation"
|
||||
|
||||
pot:
|
||||
########################################################################
|
||||
## Translation machinery
|
||||
|
||||
pot:
|
||||
xgettext --keyword=__ --keyword=___ --from-code=UTF-8 --output=locale/converse.pot converse.js --package-name=Converse.js --copyright-holder="Jan-Carel Brand" --package-version=0.7.0 -c --language="python";
|
||||
|
||||
merge:
|
||||
po:
|
||||
find ./locale -maxdepth 1 -mindepth 1 -type d -exec msgmerge {}/LC_MESSAGES/converse.po ./locale/converse.pot -U \;
|
||||
|
||||
merge: po
|
||||
|
||||
po2json:
|
||||
find ./locale -maxdepth 1 -mindepth 1 -type d -exec po2json {}/LC_MESSAGES/converse.po {}/LC_MESSAGES/converse.json \;
|
||||
|
||||
########################################################################
|
||||
## Release management
|
||||
|
||||
release:
|
||||
sed -i s/\"version\":\ \"[0-9]\.[0-9]\.[0-9]\"/\"version\":\ \"$(VERSION)\"/ bower.json
|
||||
sed -i s/\"version\":\ \"[0-9]\.[0-9]\.[0-9]\"/\"version\":\ \"$(VERSION)\"/ package.json
|
||||
@ -57,12 +55,35 @@ release:
|
||||
sed -i "s/(Unreleased)/(`date +%Y-%m-%d`)/" docs/CHANGES.rst
|
||||
grunt minify
|
||||
|
||||
dev:
|
||||
########################################################################
|
||||
## Install dependencies
|
||||
|
||||
stamp-npm: package.json
|
||||
npm install
|
||||
touch stamp-npm
|
||||
|
||||
stamp-bower: stamp-npm bower.json
|
||||
$(BOWER) install
|
||||
touch stamp-bower
|
||||
|
||||
clean::
|
||||
rm -f stamp-npm stamp-bower
|
||||
rm -rf node_modules components
|
||||
-rm -rf $(BUILDDIR)/*
|
||||
|
||||
dev: clean
|
||||
npm install
|
||||
${BOWER} update;
|
||||
|
||||
clean:
|
||||
-rm -rf $(BUILDDIR)/*
|
||||
|
||||
########################################################################
|
||||
## Tests
|
||||
|
||||
check:: stamp-npm
|
||||
$(PHANTOMJS) node_modules/phantom-jasmine/lib/run_jasmine_test.coffee tests.html
|
||||
|
||||
########################################################################
|
||||
## Documentation
|
||||
|
||||
html:
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
|
@ -52,6 +52,8 @@ Integration into other frameworks
|
||||
`roundcube-converse.js-xmpp-plugin <https://github.com/priyadi/roundcube-converse.js-xmpp-plugin>`_ is a plugin for Roundcube Webmail.
|
||||
* `Wordpress <http://wordpress.org>`_:
|
||||
`ConverseJS <http://wordpress.org/plugins/conversejs>`_
|
||||
* `Patternslib <http://patternslib.com>`_:
|
||||
`patterns.converse`_: `patterns.converse <https://github.com/jcbrand/patterns.converse>`_ provides a Patternslib pattern for Converse.js
|
||||
|
||||
----
|
||||
Demo
|
||||
@ -64,7 +66,9 @@ Tests
|
||||
-----
|
||||
|
||||
We use behavior-driven tests written with `jasmine.js <http://pivotal.github.io/jasmine>`_.
|
||||
They can run in your browser or in the command line via `phantom.js <http://phantomjs.org>`_.
|
||||
|
||||
Open `tests.html <https://github.com/jcbrand/converse.js/blob/master/tests.html>`_
|
||||
in your browser, and the tests will run automatically.
|
||||
|
||||
-------------
|
||||
Documentation
|
||||
@ -76,8 +80,7 @@ The developer/integrator documentation can be found at `<https://conversejs.org/
|
||||
Licence
|
||||
-------
|
||||
|
||||
``Converse.js`` is released under both the `MIT <http://opensource.org/licenses/mit-license.php>`_
|
||||
and `GPL <http://opensource.org/licenses/gpl-license.php>`_ licenses.
|
||||
``Converse.js`` is released under the `Mozilla Public License (MPL) <https://www.mozilla.org/MPL/2.0/index.txt>`_.
|
||||
|
||||
-------
|
||||
Support
|
||||
|
34
bower.json
34
bower.json
@ -1,26 +1,32 @@
|
||||
{
|
||||
"name": "converse",
|
||||
"version": "0.7.4",
|
||||
"version": "0.8.0",
|
||||
"devDependencies": {
|
||||
"jasmine": "https://github.com/jcbrand/jasmine.git#1_3_x",
|
||||
"otr": "0.2.7"
|
||||
"otr": "0.2.12",
|
||||
"requirejs-text": "~2.0.10",
|
||||
"requirejs-tpl-jcbrand": "*"
|
||||
},
|
||||
"dependencies": {
|
||||
"requirejs": "2.1.8",
|
||||
"jquery": "1.8.3",
|
||||
"requirejs": "2.1.11",
|
||||
"jquery": "1.11.0",
|
||||
"jed": "0.5.4",
|
||||
"tinysort": "git://github.com/Sjeiti/TinySort.git",
|
||||
"underscore": "1.5.1",
|
||||
"backbone": "1.0.0",
|
||||
"backbone.localStorage": "1.1.6",
|
||||
"strophe": "https://github.com/jcbrand/strophejs.git#converse",
|
||||
"strophe.roster": "https://raw.github.com/jcbrand/strophejs-plugins/75c8693992bc357c699b6d615eeb396e799f5c02/roster/strophe.roster.js",
|
||||
"strophe.vcard": "https://raw.github.com/jcbrand/strophejs-plugins/75c8693992bc357c699b6d615eeb396e799f5c02/vcard/strophe.vcard.js",
|
||||
"strophe.disco": "https://raw.github.com/jcbrand/strophejs-plugins/75c8693992bc357c699b6d615eeb396e799f5c02/disco/strophe.disco.js",
|
||||
"strophe.muc": "https://raw.github.com/strophe/strophejs-plugins/02310ad1b8da2962cd05b0f4bceaecca134efed4/muc/strophe.muc.js",
|
||||
"otr": "0.2.7",
|
||||
"underscore": "1.6.0",
|
||||
"backbone": "1.1.2",
|
||||
"backbone.localStorage": "1.1.7",
|
||||
"strophe": "git@github.com:strophe/strophejs-bower.git#v1.1.3",
|
||||
"strophe.roster": "https://raw.github.com/strophe/strophejs-plugins/b1f364eb6e854ffe844c57add38e885cfeb9b498/roster/strophe.roster.js",
|
||||
"strophe.vcard": "https://raw.github.com/strophe/strophejs-plugins/f5c9e16b463610d501591452cded0359f53aae48/vcard/strophe.vcard.js",
|
||||
"strophe.disco": "https://raw.github.com/jcbrand/strophejs-plugins/75c8693992bc357c699b6d615eeb396e799f5c02/disco/strophe.disco.js",
|
||||
"strophe.muc": "https://raw.github.com/strophe/strophejs-plugins/02310ad1b8da2962cd05b0f4bceaecca134efed4/muc/strophe.muc.js",
|
||||
"otr": "0.2.12",
|
||||
"crypto-js-evanvosberg": "~3.1.2",
|
||||
"almond": "~0.2.6"
|
||||
"almond": "~0.2.9",
|
||||
"requirejs-text": "~2.0.12",
|
||||
"requirejs-tpl-jcbrand": "*",
|
||||
"momentjs": "~2.6.0",
|
||||
"jquery.browser": "~0.0.6"
|
||||
},
|
||||
"exportsOverride": {}
|
||||
}
|
||||
|
223
converse.css
223
converse.css
@ -347,27 +347,15 @@ span.spinner.hor_centered {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#conversejs {
|
||||
z-index: 99; /*--Keeps the panel on top of all other elements--*/
|
||||
position: fixed;
|
||||
bottom: 0; right: 0;
|
||||
height: 332px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
#toggle-controlbox {
|
||||
position: fixed;
|
||||
font-size: 70%;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
float: right;
|
||||
font-size: 85%;
|
||||
border-top-right-radius: 4px;
|
||||
border-top-left-radius: 4px;
|
||||
background: #e3e2e2;
|
||||
border: 1px solid #c3c3c3;
|
||||
border-bottom: none;
|
||||
padding: 1px 3px;
|
||||
background-color: rgba(83, 144, 200, 100);
|
||||
padding: 4px 8px;
|
||||
margin-right: 15px;
|
||||
height: 16px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#connecting-to-chat {
|
||||
@ -393,27 +381,34 @@ span.spinner.hor_centered {
|
||||
background-color: #2D617A;
|
||||
}
|
||||
|
||||
.chatroom .chat-body {
|
||||
height: 274px;
|
||||
.chat-body {
|
||||
background-color: white;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
border-top: 0;
|
||||
}
|
||||
|
||||
.chatbox .chat-body {
|
||||
height: -moz-calc(100% - 38px);
|
||||
height: -o-calc(100% - 38px);
|
||||
height: calc(100% - 38px);
|
||||
}
|
||||
|
||||
.chatroom .chat-body {
|
||||
height: -moz-calc(100% - 38px);
|
||||
height: -o-calc(100% - 38px);
|
||||
height: calc(100% - 38px);
|
||||
}
|
||||
|
||||
.chatroom .chat-area {
|
||||
float: left;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.chatroom .chat {
|
||||
overflow: auto;
|
||||
height: 400px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.chatroom .participants {
|
||||
float: left;
|
||||
height: 274px;
|
||||
height: 100%;
|
||||
background-color: white;
|
||||
overflow: auto;
|
||||
border-left: 1px solid #AAA;
|
||||
@ -451,12 +446,18 @@ ul.participant-list li.moderator {
|
||||
padding: 4px;
|
||||
font-size: 13px;
|
||||
color: rgb(79, 79, 79);
|
||||
height:190px;
|
||||
width: 192px;
|
||||
overflow-y:auto;
|
||||
border: 0;
|
||||
background-color: #ffffff;
|
||||
line-height: 1.3em;
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
}
|
||||
|
||||
.chat-content {
|
||||
height: -moz-calc(100% - 76px);
|
||||
height: -o-calc(100% - 76px);
|
||||
height: calc(100% - 76px);
|
||||
}
|
||||
|
||||
.chat-info {
|
||||
@ -508,11 +509,6 @@ li.chat-info {
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
div#chatrooms,
|
||||
div#login-dialog {
|
||||
height: 274px;
|
||||
}
|
||||
|
||||
p.not-implemented {
|
||||
margin-top: 3em;
|
||||
margin-left: 0.3em;
|
||||
@ -560,6 +556,10 @@ div.chat-title {
|
||||
height: 1em;
|
||||
}
|
||||
|
||||
div.chat-title a {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.chat-head-chatbox,
|
||||
.chat-head-chatroom {
|
||||
background: linear-gradient(top, rgba(206,220,231,1) 0%,rgba(79,106,114,1) 100%);
|
||||
@ -578,6 +578,9 @@ p.chatroom-topic {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
div.chat-head-chatbox a.user-custom-message {
|
||||
color: white;
|
||||
}
|
||||
.activated{
|
||||
display: block !important;
|
||||
}
|
||||
@ -623,6 +626,7 @@ dl.add-converse-contact {
|
||||
float: right;
|
||||
clear: right;
|
||||
height: 22px;
|
||||
width: 12px;
|
||||
padding: 0px 5px 0 0;
|
||||
color: rgb(79, 79, 79);
|
||||
}
|
||||
@ -642,7 +646,7 @@ form.search-xmpp-contact input {
|
||||
width: 8em;
|
||||
}
|
||||
|
||||
.oc-chat-head {
|
||||
.controlbox-head {
|
||||
margin: 0;
|
||||
color: #FFF;
|
||||
border-top-right-radius: 4px;
|
||||
@ -653,8 +657,30 @@ form.search-xmpp-contact input {
|
||||
padding: 3px 0 0 0;
|
||||
}
|
||||
|
||||
.chat-head-message-count {
|
||||
font-weight: bold;
|
||||
position: absolute;
|
||||
left: -6px;
|
||||
top: -6px;
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0.35, #f6f6f6), color-stop(1, grey) );
|
||||
background: -moz-linear-gradient(center top, yellow 5%, #f6f6f6 100%);
|
||||
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='yellow', endColorstr='#f6f6f6');
|
||||
border: 3px solid rgb(79, 106, 114);
|
||||
text-shadow: 1px 1px 0 #ccc;
|
||||
color: darkred;
|
||||
border-radius: 20%;
|
||||
padding: 2px 10px;
|
||||
font-size: 18px;
|
||||
text-align: center;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.chat-head-chatroom .chat-head-message-count {
|
||||
border: 3px solid #2D617A;
|
||||
}
|
||||
|
||||
a.configure-chatroom-button,
|
||||
a.minimize-chatbox-button,
|
||||
a.toggle-chatbox-button,
|
||||
a.close-chatbox-button {
|
||||
font-size: 10px;
|
||||
padding: 3px 3px 2px 3px;
|
||||
@ -664,8 +690,8 @@ a.close-chatbox-button {
|
||||
-moz-box-shadow:inset 0 1px 0 0 #ffffff;
|
||||
-webkit-box-shadow:inset 0 1px 0 0 #ffffff;
|
||||
box-shadow:inset 0 1px 0 0 #ffffff;
|
||||
background:-webkit-gradient( linear, left top, left bottom, color-stop(0.05, #ffffff), color-stop(1, #f6f6f6) );
|
||||
background:-moz-linear-gradient( center top, #ffffff 5%, #f6f6f6 100% );
|
||||
background:-webkit-gradient(linear, left top, left bottom, color-stop(0.05, #ffffff), color-stop(1, #f6f6f6) );
|
||||
background:-moz-linear-gradient(center top, #ffffff 5%, #f6f6f6 100%);
|
||||
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f6f6f6');
|
||||
-moz-border-radius:6px;
|
||||
-webkit-border-radius:6px;
|
||||
@ -678,21 +704,20 @@ a.close-chatbox-button {
|
||||
}
|
||||
|
||||
a.configure-chatroom-button:active,
|
||||
a.minimize-chatbox-button:active,
|
||||
a.toggle-chatbox-button:active,
|
||||
a.close-chatbox-button:active {
|
||||
position:relative;
|
||||
top:1px;
|
||||
}
|
||||
|
||||
.oc-chat-content dt {
|
||||
.controlbox-pane dt {
|
||||
margin: 0;
|
||||
padding-top: 0.5em;
|
||||
}
|
||||
|
||||
.chatroom-form-container {
|
||||
height: 100%;
|
||||
color: #666;
|
||||
padding: 5px;
|
||||
height: 262px;
|
||||
overflow-y: auto;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
@ -760,15 +785,14 @@ a.close-chatbox-button:active {
|
||||
}
|
||||
|
||||
#converse-roster {
|
||||
height: 200px;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
position: relative;
|
||||
top: 0;
|
||||
border: none;
|
||||
margin-top: 0.5em;
|
||||
margin: 0.5em 0 0 0;
|
||||
height: -moz-calc(100% - 70px);
|
||||
height: -o-calc(100% - 70px);
|
||||
height: calc(100% - 70px);
|
||||
}
|
||||
|
||||
#conversejs dd.available-chatroom {
|
||||
@ -876,12 +900,10 @@ dd.available-chatroom:hover a.room-info {
|
||||
|
||||
.chatbox,
|
||||
.chatroom {
|
||||
box-shadow: 1px 1px 5px 1px rgba(0,0,0,0.4);
|
||||
display:none;
|
||||
height: 25px;
|
||||
float: right;
|
||||
margin-right: 15px;
|
||||
z-index: 20; /* So that it's higher than the content actions */
|
||||
border-radius: 4px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.chatbox {
|
||||
@ -892,37 +914,22 @@ dd.available-chatroom:hover a.room-info {
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.oc-chat-content {
|
||||
height:274px;
|
||||
.controlbox-pane {
|
||||
padding: 0;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
}
|
||||
|
||||
.oc-chat-content dd {
|
||||
.controlbox-pane dd {
|
||||
margin-left: 0;
|
||||
margin-bottom: 0;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.oc-chat-content dd.odd {
|
||||
.controlbox-pane dd.odd {
|
||||
background-color: #DCEAC5;
|
||||
}
|
||||
|
||||
#conversejs div.controlbox-panes {
|
||||
background: -moz-linear-gradient(top, rgba(255,255,255,1) 0%, rgba(240,240,240,1) 100%); /* FF3.6+ */
|
||||
background: -ms-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(240,240,240,1) 100%); /* IE10+ */
|
||||
background: -o-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(240,240,240,1) 100%); /* Opera 11.10+ */
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,1)), color-stop(100%,rgba(240,240,240,1))); /* Chrome,Safari4+ */
|
||||
background: -webkit-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(240,240,240,1) 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: linear-gradient(top, rgba(255,255,255,1) 0%,rgba(240,240,240,1) 100%); /* W3C */
|
||||
background-color: white;
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
|
||||
form#converse-login {
|
||||
background: white;
|
||||
padding: 2em 0 0.3em 0.5em;
|
||||
@ -975,7 +982,7 @@ select#select-xmpp-status {
|
||||
|
||||
/* single tab */
|
||||
.chat-head #controlbox-tabs li {
|
||||
float:left;
|
||||
float: left;
|
||||
list-style: none;
|
||||
padding-left: 0;
|
||||
text-shadow: white 0 1px 0;
|
||||
@ -983,16 +990,16 @@ select#select-xmpp-status {
|
||||
}
|
||||
|
||||
ul#controlbox-tabs li a {
|
||||
display:block;
|
||||
font-size:12px;
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
height: 34px;
|
||||
line-height:34px;
|
||||
line-height: 34px;
|
||||
margin: 0;
|
||||
text-align:center;
|
||||
text-decoration:none;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
border-top-right-radius: 5px;
|
||||
border-top-left-radius: 5px;
|
||||
color:#666;
|
||||
color: #666;
|
||||
text-shadow: 0 1px 0 rgba(250, 250, 250, 1);
|
||||
}
|
||||
|
||||
@ -1024,6 +1031,11 @@ div#settings {
|
||||
border-bottom-right-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
width: 100%;
|
||||
height: -moz-calc(100% - 38px);
|
||||
height: -o-calc(100% - 38px);
|
||||
height: calc(100% - 38px);
|
||||
overflow-y: hidden;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
div#chatrooms {
|
||||
@ -1191,6 +1203,10 @@ form#set-custom-xmpp-status {
|
||||
padding: 1px 2px 1px 1px;
|
||||
}
|
||||
|
||||
#controlbox {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#controlbox div.xmpp-status {
|
||||
display: inline;
|
||||
}
|
||||
@ -1205,7 +1221,7 @@ form#set-custom-xmpp-status {
|
||||
.chatbox .dropdown dd { position:relative; }
|
||||
|
||||
input.custom-xmpp-status {
|
||||
width: 138px;
|
||||
width: 124px;
|
||||
}
|
||||
|
||||
form.add-xmpp-contact {
|
||||
@ -1214,7 +1230,7 @@ form.add-xmpp-contact {
|
||||
}
|
||||
|
||||
form.add-xmpp-contact input {
|
||||
width: 120px;
|
||||
width: 108px;
|
||||
}
|
||||
|
||||
.chatbox .dropdown dt a span {
|
||||
@ -1240,17 +1256,14 @@ form.add-xmpp-contact input {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.set-xmpp-status .dropdown dd ul {
|
||||
z-index: 22;
|
||||
}
|
||||
|
||||
.chatbox .dropdown a {
|
||||
height: 22px;
|
||||
width: 148px;
|
||||
display: inline-block;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.chatbox .dropdown dd ul a:hover {
|
||||
.chatbox .dropdown dd ul li:hover {
|
||||
background-color: #bed6e5;
|
||||
}
|
||||
|
||||
@ -1263,3 +1276,51 @@ form.add-xmpp-contact input {
|
||||
color: rgb(79, 79, 79);
|
||||
}
|
||||
|
||||
.set-xmpp-status .dropdown dd ul {
|
||||
z-index: 22;
|
||||
}
|
||||
|
||||
#conversejs {
|
||||
bottom: 1px;
|
||||
direction: ltr;
|
||||
height: 25px;
|
||||
left: 0;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
z-index: 30;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.box-flyout {
|
||||
background: white;
|
||||
position: absolute;
|
||||
display: block;
|
||||
bottom: 1px;
|
||||
box-shadow: 1px 1px 5px 1px rgba(0,0,0,0.4);
|
||||
border-radius: 4px;
|
||||
height: 324px;
|
||||
}
|
||||
|
||||
.box-flyout.minimized {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.chatbox .box-flyout {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.chatroom .box-flyout {
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.dragresize {
|
||||
position: absolute;
|
||||
width: 200px;
|
||||
height: 5px;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
top: 0;
|
||||
margin-left: 0;
|
||||
cursor: n-resize;
|
||||
z-index: 20;
|
||||
}
|
||||
|
1089
converse.js
1089
converse.js
File diff suppressed because it is too large
Load Diff
@ -1,12 +1,24 @@
|
||||
Changelog
|
||||
=========
|
||||
|
||||
0.8 (Unreleased)
|
||||
----------------
|
||||
|
||||
* Chat boxes and rooms can now be resized vertically. [jcbrand]
|
||||
* Upgraded many dependencies to their latest versions. [jcbrand]
|
||||
* Add new configuration setting `forward_messages <https://conversejs.org/docs/html/index.html#forward_messages>`_
|
||||
Message forwarding was before default behavior but is now optional (and disabled by default).
|
||||
[jcbrand]
|
||||
* #71 Chat boxes and rooms can be minimized. [jcbrand]
|
||||
* #132 Support for `XEP-0280: Message Carbons <https://xmpp.org/extensions/xep-0280.html'>`_.
|
||||
Configured via `enable_message_carbons <https://conversejs.org/docs/html/index.html#enable_message_carbons>`_
|
||||
[hejazee]
|
||||
|
||||
0.7.4 (2014-03-05)
|
||||
------------------
|
||||
|
||||
.. note::
|
||||
This release contains an important security fix.
|
||||
Thanks to Renaud Dubourguais from `Synacktiv http://synacktiv.com`_ for reporting the vulnerability.
|
||||
.. note:: This release contains an important security fix.
|
||||
Thanks to Renaud Dubourguais from `Synacktiv <http://synacktiv.com>`_ for reporting the vulnerability.
|
||||
|
||||
* #125 Bugfix: crypto dependencies loaded in wrong order [jcbrand]
|
||||
* Bugfix: action messages (i.e. /me) didn't work in OTR mode. [jcbrand]
|
||||
@ -26,8 +38,7 @@ Changelog
|
||||
0.7.2 (2013-12-18)
|
||||
------------------
|
||||
|
||||
.. note::
|
||||
This release contains an important security fix.
|
||||
.. note:: This release contains an important security fix.
|
||||
Thanks to hejsan for reporting the vulnerability.
|
||||
|
||||
* #48 Add event emitter support and emit events. [jcbrand]
|
||||
@ -116,9 +127,8 @@ Bugfixes:
|
||||
0.6.3 (2013-09-12)
|
||||
------------------
|
||||
|
||||
.. note::
|
||||
This release contains an important security fix. Please don't use older
|
||||
versions of the 0.6 branch.
|
||||
NB: This release contains an important security fix. Please don't use older
|
||||
versions of the 0.6 branch.
|
||||
|
||||
* French translations. [tdesvenain]
|
||||
* Bugfix: Messages were stored against buddy JID and not own JID. [jcbrand]
|
||||
@ -128,7 +138,7 @@ Bugfixes:
|
||||
|
||||
* Bugfix. The remove icon wasn't appearing in the contacts roster. [jcbrand]
|
||||
* Bugfix. With auto_subscribe=True, the "Pending Contacts" header didn't disappear
|
||||
after a new user was accepted. [jcbrand]
|
||||
after a new user was accepted. [jcbrand]
|
||||
|
||||
0.6.1 (2013-08-28)
|
||||
------------------
|
||||
|
373
docs/LICENSE.txt
Normal file
373
docs/LICENSE.txt
Normal file
@ -0,0 +1,373 @@
|
||||
Mozilla Public License Version 2.0
|
||||
==================================
|
||||
|
||||
1. Definitions
|
||||
--------------
|
||||
|
||||
1.1. "Contributor"
|
||||
means each individual or legal entity that creates, contributes to
|
||||
the creation of, or owns Covered Software.
|
||||
|
||||
1.2. "Contributor Version"
|
||||
means the combination of the Contributions of others (if any) used
|
||||
by a Contributor and that particular Contributor's Contribution.
|
||||
|
||||
1.3. "Contribution"
|
||||
means Covered Software of a particular Contributor.
|
||||
|
||||
1.4. "Covered Software"
|
||||
means Source Code Form to which the initial Contributor has attached
|
||||
the notice in Exhibit A, the Executable Form of such Source Code
|
||||
Form, and Modifications of such Source Code Form, in each case
|
||||
including portions thereof.
|
||||
|
||||
1.5. "Incompatible With Secondary Licenses"
|
||||
means
|
||||
|
||||
(a) that the initial Contributor has attached the notice described
|
||||
in Exhibit B to the Covered Software; or
|
||||
|
||||
(b) that the Covered Software was made available under the terms of
|
||||
version 1.1 or earlier of the License, but not also under the
|
||||
terms of a Secondary License.
|
||||
|
||||
1.6. "Executable Form"
|
||||
means any form of the work other than Source Code Form.
|
||||
|
||||
1.7. "Larger Work"
|
||||
means a work that combines Covered Software with other material, in
|
||||
a separate file or files, that is not Covered Software.
|
||||
|
||||
1.8. "License"
|
||||
means this document.
|
||||
|
||||
1.9. "Licensable"
|
||||
means having the right to grant, to the maximum extent possible,
|
||||
whether at the time of the initial grant or subsequently, any and
|
||||
all of the rights conveyed by this License.
|
||||
|
||||
1.10. "Modifications"
|
||||
means any of the following:
|
||||
|
||||
(a) any file in Source Code Form that results from an addition to,
|
||||
deletion from, or modification of the contents of Covered
|
||||
Software; or
|
||||
|
||||
(b) any new file in Source Code Form that contains any Covered
|
||||
Software.
|
||||
|
||||
1.11. "Patent Claims" of a Contributor
|
||||
means any patent claim(s), including without limitation, method,
|
||||
process, and apparatus claims, in any patent Licensable by such
|
||||
Contributor that would be infringed, but for the grant of the
|
||||
License, by the making, using, selling, offering for sale, having
|
||||
made, import, or transfer of either its Contributions or its
|
||||
Contributor Version.
|
||||
|
||||
1.12. "Secondary License"
|
||||
means either the GNU General Public License, Version 2.0, the GNU
|
||||
Lesser General Public License, Version 2.1, the GNU Affero General
|
||||
Public License, Version 3.0, or any later versions of those
|
||||
licenses.
|
||||
|
||||
1.13. "Source Code Form"
|
||||
means the form of the work preferred for making modifications.
|
||||
|
||||
1.14. "You" (or "Your")
|
||||
means an individual or a legal entity exercising rights under this
|
||||
License. For legal entities, "You" includes any entity that
|
||||
controls, is controlled by, or is under common control with You. For
|
||||
purposes of this definition, "control" means (a) the power, direct
|
||||
or indirect, to cause the direction or management of such entity,
|
||||
whether by contract or otherwise, or (b) ownership of more than
|
||||
fifty percent (50%) of the outstanding shares or beneficial
|
||||
ownership of such entity.
|
||||
|
||||
2. License Grants and Conditions
|
||||
--------------------------------
|
||||
|
||||
2.1. Grants
|
||||
|
||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license:
|
||||
|
||||
(a) under intellectual property rights (other than patent or trademark)
|
||||
Licensable by such Contributor to use, reproduce, make available,
|
||||
modify, display, perform, distribute, and otherwise exploit its
|
||||
Contributions, either on an unmodified basis, with Modifications, or
|
||||
as part of a Larger Work; and
|
||||
|
||||
(b) under Patent Claims of such Contributor to make, use, sell, offer
|
||||
for sale, have made, import, and otherwise transfer either its
|
||||
Contributions or its Contributor Version.
|
||||
|
||||
2.2. Effective Date
|
||||
|
||||
The licenses granted in Section 2.1 with respect to any Contribution
|
||||
become effective for each Contribution on the date the Contributor first
|
||||
distributes such Contribution.
|
||||
|
||||
2.3. Limitations on Grant Scope
|
||||
|
||||
The licenses granted in this Section 2 are the only rights granted under
|
||||
this License. No additional rights or licenses will be implied from the
|
||||
distribution or licensing of Covered Software under this License.
|
||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||
Contributor:
|
||||
|
||||
(a) for any code that a Contributor has removed from Covered Software;
|
||||
or
|
||||
|
||||
(b) for infringements caused by: (i) Your and any other third party's
|
||||
modifications of Covered Software, or (ii) the combination of its
|
||||
Contributions with other software (except as part of its Contributor
|
||||
Version); or
|
||||
|
||||
(c) under Patent Claims infringed by Covered Software in the absence of
|
||||
its Contributions.
|
||||
|
||||
This License does not grant any rights in the trademarks, service marks,
|
||||
or logos of any Contributor (except as may be necessary to comply with
|
||||
the notice requirements in Section 3.4).
|
||||
|
||||
2.4. Subsequent Licenses
|
||||
|
||||
No Contributor makes additional grants as a result of Your choice to
|
||||
distribute the Covered Software under a subsequent version of this
|
||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||
permitted under the terms of Section 3.3).
|
||||
|
||||
2.5. Representation
|
||||
|
||||
Each Contributor represents that the Contributor believes its
|
||||
Contributions are its original creation(s) or it has sufficient rights
|
||||
to grant the rights to its Contributions conveyed by this License.
|
||||
|
||||
2.6. Fair Use
|
||||
|
||||
This License is not intended to limit any rights You have under
|
||||
applicable copyright doctrines of fair use, fair dealing, or other
|
||||
equivalents.
|
||||
|
||||
2.7. Conditions
|
||||
|
||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
|
||||
in Section 2.1.
|
||||
|
||||
3. Responsibilities
|
||||
-------------------
|
||||
|
||||
3.1. Distribution of Source Form
|
||||
|
||||
All distribution of Covered Software in Source Code Form, including any
|
||||
Modifications that You create or to which You contribute, must be under
|
||||
the terms of this License. You must inform recipients that the Source
|
||||
Code Form of the Covered Software is governed by the terms of this
|
||||
License, and how they can obtain a copy of this License. You may not
|
||||
attempt to alter or restrict the recipients' rights in the Source Code
|
||||
Form.
|
||||
|
||||
3.2. Distribution of Executable Form
|
||||
|
||||
If You distribute Covered Software in Executable Form then:
|
||||
|
||||
(a) such Covered Software must also be made available in Source Code
|
||||
Form, as described in Section 3.1, and You must inform recipients of
|
||||
the Executable Form how they can obtain a copy of such Source Code
|
||||
Form by reasonable means in a timely manner, at a charge no more
|
||||
than the cost of distribution to the recipient; and
|
||||
|
||||
(b) You may distribute such Executable Form under the terms of this
|
||||
License, or sublicense it under different terms, provided that the
|
||||
license for the Executable Form does not attempt to limit or alter
|
||||
the recipients' rights in the Source Code Form under this License.
|
||||
|
||||
3.3. Distribution of a Larger Work
|
||||
|
||||
You may create and distribute a Larger Work under terms of Your choice,
|
||||
provided that You also comply with the requirements of this License for
|
||||
the Covered Software. If the Larger Work is a combination of Covered
|
||||
Software with a work governed by one or more Secondary Licenses, and the
|
||||
Covered Software is not Incompatible With Secondary Licenses, this
|
||||
License permits You to additionally distribute such Covered Software
|
||||
under the terms of such Secondary License(s), so that the recipient of
|
||||
the Larger Work may, at their option, further distribute the Covered
|
||||
Software under the terms of either this License or such Secondary
|
||||
License(s).
|
||||
|
||||
3.4. Notices
|
||||
|
||||
You may not remove or alter the substance of any license notices
|
||||
(including copyright notices, patent notices, disclaimers of warranty,
|
||||
or limitations of liability) contained within the Source Code Form of
|
||||
the Covered Software, except that You may alter any license notices to
|
||||
the extent required to remedy known factual inaccuracies.
|
||||
|
||||
3.5. Application of Additional Terms
|
||||
|
||||
You may choose to offer, and to charge a fee for, warranty, support,
|
||||
indemnity or liability obligations to one or more recipients of Covered
|
||||
Software. However, You may do so only on Your own behalf, and not on
|
||||
behalf of any Contributor. You must make it absolutely clear that any
|
||||
such warranty, support, indemnity, or liability obligation is offered by
|
||||
You alone, and You hereby agree to indemnify every Contributor for any
|
||||
liability incurred by such Contributor as a result of warranty, support,
|
||||
indemnity or liability terms You offer. You may include additional
|
||||
disclaimers of warranty and limitations of liability specific to any
|
||||
jurisdiction.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation
|
||||
---------------------------------------------------
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this
|
||||
License with respect to some or all of the Covered Software due to
|
||||
statute, judicial order, or regulation then You must: (a) comply with
|
||||
the terms of this License to the maximum extent possible; and (b)
|
||||
describe the limitations and the code they affect. Such description must
|
||||
be placed in a text file included with all distributions of the Covered
|
||||
Software under this License. Except to the extent prohibited by statute
|
||||
or regulation, such description must be sufficiently detailed for a
|
||||
recipient of ordinary skill to be able to understand it.
|
||||
|
||||
5. Termination
|
||||
--------------
|
||||
|
||||
5.1. The rights granted under this License will terminate automatically
|
||||
if You fail to comply with any of its terms. However, if You become
|
||||
compliant, then the rights granted under this License from a particular
|
||||
Contributor are reinstated (a) provisionally, unless and until such
|
||||
Contributor explicitly and finally terminates Your grants, and (b) on an
|
||||
ongoing basis, if such Contributor fails to notify You of the
|
||||
non-compliance by some reasonable means prior to 60 days after You have
|
||||
come back into compliance. Moreover, Your grants from a particular
|
||||
Contributor are reinstated on an ongoing basis if such Contributor
|
||||
notifies You of the non-compliance by some reasonable means, this is the
|
||||
first time You have received notice of non-compliance with this License
|
||||
from such Contributor, and You become compliant prior to 30 days after
|
||||
Your receipt of the notice.
|
||||
|
||||
5.2. If You initiate litigation against any entity by asserting a patent
|
||||
infringement claim (excluding declaratory judgment actions,
|
||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||
directly or indirectly infringes any patent, then the rights granted to
|
||||
You by any and all Contributors for the Covered Software under Section
|
||||
2.1 of this License shall terminate.
|
||||
|
||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
|
||||
end user license agreements (excluding distributors and resellers) which
|
||||
have been validly granted by You or Your distributors under this License
|
||||
prior to termination shall survive termination.
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 6. Disclaimer of Warranty *
|
||||
* ------------------------- *
|
||||
* *
|
||||
* Covered Software is provided under this License on an "as is" *
|
||||
* basis, without warranty of any kind, either expressed, implied, or *
|
||||
* statutory, including, without limitation, warranties that the *
|
||||
* Covered Software is free of defects, merchantable, fit for a *
|
||||
* particular purpose or non-infringing. The entire risk as to the *
|
||||
* quality and performance of the Covered Software is with You. *
|
||||
* Should any Covered Software prove defective in any respect, You *
|
||||
* (not any Contributor) assume the cost of any necessary servicing, *
|
||||
* repair, or correction. This disclaimer of warranty constitutes an *
|
||||
* essential part of this License. No use of any Covered Software is *
|
||||
* authorized under this License except under this disclaimer. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 7. Limitation of Liability *
|
||||
* -------------------------- *
|
||||
* *
|
||||
* Under no circumstances and under no legal theory, whether tort *
|
||||
* (including negligence), contract, or otherwise, shall any *
|
||||
* Contributor, or anyone who distributes Covered Software as *
|
||||
* permitted above, be liable to You for any direct, indirect, *
|
||||
* special, incidental, or consequential damages of any character *
|
||||
* including, without limitation, damages for lost profits, loss of *
|
||||
* goodwill, work stoppage, computer failure or malfunction, or any *
|
||||
* and all other commercial damages or losses, even if such party *
|
||||
* shall have been informed of the possibility of such damages. This *
|
||||
* limitation of liability shall not apply to liability for death or *
|
||||
* personal injury resulting from such party's negligence to the *
|
||||
* extent applicable law prohibits such limitation. Some *
|
||||
* jurisdictions do not allow the exclusion or limitation of *
|
||||
* incidental or consequential damages, so this exclusion and *
|
||||
* limitation may not apply to You. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
8. Litigation
|
||||
-------------
|
||||
|
||||
Any litigation relating to this License may be brought only in the
|
||||
courts of a jurisdiction where the defendant maintains its principal
|
||||
place of business and such litigation shall be governed by laws of that
|
||||
jurisdiction, without reference to its conflict-of-law provisions.
|
||||
Nothing in this Section shall prevent a party's ability to bring
|
||||
cross-claims or counter-claims.
|
||||
|
||||
9. Miscellaneous
|
||||
----------------
|
||||
|
||||
This License represents the complete agreement concerning the subject
|
||||
matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent
|
||||
necessary to make it enforceable. Any law or regulation which provides
|
||||
that the language of a contract shall be construed against the drafter
|
||||
shall not be used to construe this License against a Contributor.
|
||||
|
||||
10. Versions of the License
|
||||
---------------------------
|
||||
|
||||
10.1. New Versions
|
||||
|
||||
Mozilla Foundation is the license steward. Except as provided in Section
|
||||
10.3, no one other than the license steward has the right to modify or
|
||||
publish new versions of this License. Each version will be given a
|
||||
distinguishing version number.
|
||||
|
||||
10.2. Effect of New Versions
|
||||
|
||||
You may distribute the Covered Software under the terms of the version
|
||||
of the License under which You originally received the Covered Software,
|
||||
or under the terms of any subsequent version published by the license
|
||||
steward.
|
||||
|
||||
10.3. Modified Versions
|
||||
|
||||
If you create software not governed by this License, and you want to
|
||||
create a new license for such software, you may create and use a
|
||||
modified version of this License if you rename the license and remove
|
||||
any references to the name of the license steward (except to note that
|
||||
such modified license differs from this License).
|
||||
|
||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||
Licenses
|
||||
|
||||
If You choose to distribute Source Code Form that is Incompatible With
|
||||
Secondary Licenses under the terms of this version of the License, the
|
||||
notice described in Exhibit B of this License must be attached.
|
||||
|
||||
Exhibit A - Source Code Form License Notice
|
||||
-------------------------------------------
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular
|
||||
file, then You may include the notice in a location (such as a LICENSE
|
||||
file in a relevant directory) where a recipient would be likely to look
|
||||
for such a notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
|
||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
||||
---------------------------------------------------------
|
||||
|
||||
This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
defined by the Mozilla Public License, v. 2.0.
|
@ -1,18 +0,0 @@
|
||||
Converse.js
|
||||
A web-based XMPP instant messaging client.
|
||||
|
||||
Copyright (C) 2012 Jan-Carel Brand.
|
||||
http://opkode.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
@ -1,25 +0,0 @@
|
||||
Converse.js
|
||||
A web-based XMPP instant messaging client.
|
||||
|
||||
Copyright (C) 2012 Jan-Carel Brand.
|
||||
http://opkode.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
|
Binary file not shown.
@ -1,4 +1,4 @@
|
||||
# Sphinx build info version 1
|
||||
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
|
||||
config: 0660e50cf30718622673fcf0e779dfd4
|
||||
config: ec38a6fc765fb5f09e06d01a6497e5a9
|
||||
tags: fbb0d17656682115ca4d033fb2f83ba1
|
||||
|
@ -392,8 +392,8 @@ follow the instructions below to create this folder and fetch Converse's
|
||||
3rd-party dependencies.
|
||||
|
||||
|
||||
Install Node.js and development dependencies
|
||||
============================================
|
||||
Install the development and front-end dependencies
|
||||
==================================================
|
||||
|
||||
We use development tools (`Grunt <http://gruntjs.com>`_ and `Bower <http://bower.io>`_)
|
||||
which depend on Node.js and npm (the Node package manager).
|
||||
@ -401,43 +401,38 @@ which depend on Node.js and npm (the Node package manager).
|
||||
If you don't have Node.js installed, you can download and install the latest
|
||||
version `here <https://nodejs.org/download>`_.
|
||||
|
||||
Once you have Node.js installed, run the following command inside the Converse.js
|
||||
Also make sure you have ``git`` installed. `Details <http://git-scm.com/book/en/Getting-Started-Installing-Git>`_.
|
||||
|
||||
Once you have *Node.js* and *git* installed, run the following command inside the Converse.js
|
||||
directory:
|
||||
|
||||
::
|
||||
|
||||
npm install
|
||||
make dev
|
||||
|
||||
This will install all the development dependencies for Converse.js. If you are
|
||||
curious to know what these are, take a look at whats under the *devDependencies* key in
|
||||
`package.json <https://github.com/jcbrand/converse.js/blob/master/package.json>`_.
|
||||
This will first install the Node.js development tools (like Grunt and Bower)
|
||||
and then use Bower to install all of Converse.js's front-end dependencies.
|
||||
|
||||
Install 3rd party dependencies
|
||||
==============================
|
||||
The front-end dependencies are those javascript files on which
|
||||
Converse.js directly depends and which will therefore be loaded in the browser.
|
||||
|
||||
Make sure you have ``git`` installed. `Details <http://git-scm.com/book/en/Getting-Started-Installing-Git>`_.
|
||||
If you are curious to know what the different dependencies are:
|
||||
|
||||
After running ``npm install``, you will now have Grunt and Bower installed.
|
||||
* Development dependencies:
|
||||
Take a look at whats under the *devDependencies* key in
|
||||
`package.json <https://github.com/jcbrand/converse.js/blob/master/package.json>`_.
|
||||
|
||||
We use Bower to manage Converse's front-end dependencies (e.g. Javascript that
|
||||
should get loaded in the browser).
|
||||
* Front-end dependencies:
|
||||
See *dependencies* in
|
||||
`bower.json <https://github.com/jcbrand/converse.js/blob/master/bower.json>`_.
|
||||
|
||||
To fetch these dependencies, run:
|
||||
.. Note:
|
||||
After running ```make dev```, you should now have a new directory *components*,
|
||||
which contains all the front-end dependencies of Converse.js.
|
||||
If this directory does NOT exist, something must have gone wrong.
|
||||
Double-check the output of ```make dev``` to see if there are any errors
|
||||
listed.
|
||||
|
||||
::
|
||||
|
||||
grunt fetch
|
||||
|
||||
If you don't have grunt installed globally, you need to specify the relative
|
||||
path:
|
||||
|
||||
::
|
||||
|
||||
./node_modules/.bin/grunt fetch
|
||||
|
||||
This will call Bower in the background to fetch all the front-end
|
||||
dependencies (like backbone.js, strophe.js etc.) and then put them in the
|
||||
*components* folder.
|
||||
|
||||
With AMD and require.js (recommended)
|
||||
=====================================
|
||||
@ -580,7 +575,7 @@ To do this for ALL languages, run:
|
||||
|
||||
::
|
||||
|
||||
make merge
|
||||
make po
|
||||
|
||||
The resulting PO file is then what gets translated.
|
||||
|
||||
@ -807,6 +802,12 @@ Here are the different events that are emitted:
|
||||
|
||||
Triggered whenever the roster view (i.e. the rendered HTML) has changed.
|
||||
|
||||
* **onChatBoxClosed**
|
||||
|
||||
``converse.on('onChatBoxClosed', function (chatbox) { ... });``
|
||||
|
||||
Triggered when a chat box has been closed.
|
||||
|
||||
* **onChatBoxFocused**
|
||||
|
||||
``converse.on('onChatBoxFocused', function (chatbox) { ... });``
|
||||
@ -819,11 +820,11 @@ Here are the different events that are emitted:
|
||||
|
||||
Triggered when a chat box has been opened.
|
||||
|
||||
* **onChatBoxClosed**
|
||||
* **onChatBoxToggled**
|
||||
|
||||
``converse.on('onChatBoxClosed', function (chatbox) { ... });``
|
||||
``converse.on('onChatBoxToggled', function (chatbox) { ... });``
|
||||
|
||||
Triggered when a chat box has been closed.
|
||||
Triggered when a chat box has been minimized or maximized.
|
||||
|
||||
* **onStatusChanged**
|
||||
|
||||
@ -967,9 +968,18 @@ Default = ``false``
|
||||
|
||||
If set to true, debugging output will be logged to the browser console.
|
||||
|
||||
enable_message_carbons
|
||||
----------------------
|
||||
|
||||
Default = ``false``
|
||||
|
||||
Support for `XEP-0280: Message Carbons <https://xmpp.org/extensions/xep-0280.html>`_
|
||||
|
||||
expose_rid_and_sid
|
||||
------------------
|
||||
|
||||
Default = ``false``
|
||||
|
||||
Allow the prebind tokens, RID (request ID) and SID (session ID), to be exposed
|
||||
globally via the API. This allows other scripts served on the same page to use
|
||||
these values.
|
||||
@ -977,6 +987,19 @@ these values.
|
||||
*Beware*: a malicious script could use these tokens to assume your identity
|
||||
and inject fake chat messages.
|
||||
|
||||
forward_messages
|
||||
----------------
|
||||
|
||||
Default = ``false``
|
||||
|
||||
If set to ``true``, sent messages will also be forwarded to other connected
|
||||
XMPP resources (e.g. chat clients) of the same user.
|
||||
|
||||
This is useful for example if converse.js is running in multiple tabs of the
|
||||
browser and you want sent messages to appear in all of them.
|
||||
|
||||
See also `XEP 0297: Stanza Forwarding <http://www.xmpp.org/extensions/xep-0297.html>`_
|
||||
|
||||
fullname
|
||||
--------
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>Index — Converse.js 0.7.4 documentation</title>
|
||||
<title>Index — Converse.js 0.8.0 documentation</title>
|
||||
|
||||
<link rel="stylesheet" href="_static/stylesheet.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
@ -17,7 +17,7 @@
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '',
|
||||
VERSION: '0.7.4',
|
||||
VERSION: '0.8.0',
|
||||
COLLAPSE_INDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
@ -26,7 +26,7 @@
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/underscore.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="Converse.js 0.7.4 documentation" href="index.html" />
|
||||
<link rel="top" title="Converse.js 0.8.0 documentation" href="index.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="header_wrap" class="outer">
|
||||
@ -51,7 +51,7 @@
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="#" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li><a href="index.html">Converse.js 0.7.4 documentation</a> »</li>
|
||||
<li><a href="index.html">Converse.js 0.8.0 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<section id="main_content" class="inner">
|
||||
@ -80,7 +80,7 @@
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="#" title="General Index"
|
||||
>index</a></li>
|
||||
<li><a href="index.html">Converse.js 0.7.4 documentation</a> »</li>
|
||||
<li><a href="index.html">Converse.js 0.8.0 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -7,7 +7,7 @@
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>Quickstart (to get a demo up and running) — Converse.js 0.7.4 documentation</title>
|
||||
<title>Quickstart (to get a demo up and running) — Converse.js 0.8.0 documentation</title>
|
||||
|
||||
<link rel="stylesheet" href="_static/stylesheet.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
@ -15,7 +15,7 @@
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '',
|
||||
VERSION: '0.7.4',
|
||||
VERSION: '0.8.0',
|
||||
COLLAPSE_INDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
@ -24,7 +24,7 @@
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/underscore.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="Converse.js 0.7.4 documentation" href="#" />
|
||||
<link rel="top" title="Converse.js 0.8.0 documentation" href="#" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="header_wrap" class="outer">
|
||||
@ -49,7 +49,7 @@
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li><a href="#">Converse.js 0.7.4 documentation</a> »</li>
|
||||
<li><a href="#">Converse.js 0.8.0 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<section id="main_content" class="inner">
|
||||
@ -87,61 +87,62 @@
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#development" id="id16">Development</a><ul>
|
||||
<li><a class="reference internal" href="#install-node-js-and-development-dependencies" id="id17">Install Node.js and development dependencies</a></li>
|
||||
<li><a class="reference internal" href="#install-3rd-party-dependencies" id="id18">Install 3rd party dependencies</a></li>
|
||||
<li><a class="reference internal" href="#with-amd-and-require-js-recommended" id="id19">With AMD and require.js (recommended)</a></li>
|
||||
<li><a class="reference internal" href="#without-amd-and-require-js" id="id20">Without AMD and require.js</a></li>
|
||||
<li><a class="reference internal" href="#before-submitting-a-pull-request" id="id21">Before submitting a pull request</a><ul>
|
||||
<li><a class="reference internal" href="#add-tests-for-your-bugfix-or-feature" id="id22">Add tests for your bugfix or feature</a></li>
|
||||
<li><a class="reference internal" href="#check-that-the-tests-pass" id="id23">Check that the tests pass</a></li>
|
||||
<li><a class="reference internal" href="#check-your-code-for-errors-or-bad-habits-by-running-jshint" id="id24">Check your code for errors or bad habits by running JSHint</a></li>
|
||||
<li><a class="reference internal" href="#install-the-development-and-front-end-dependencies" id="id17">Install the development and front-end dependencies</a></li>
|
||||
<li><a class="reference internal" href="#with-amd-and-require-js-recommended" id="id18">With AMD and require.js (recommended)</a></li>
|
||||
<li><a class="reference internal" href="#without-amd-and-require-js" id="id19">Without AMD and require.js</a></li>
|
||||
<li><a class="reference internal" href="#before-submitting-a-pull-request" id="id20">Before submitting a pull request</a><ul>
|
||||
<li><a class="reference internal" href="#add-tests-for-your-bugfix-or-feature" id="id21">Add tests for your bugfix or feature</a></li>
|
||||
<li><a class="reference internal" href="#check-that-the-tests-pass" id="id22">Check that the tests pass</a></li>
|
||||
<li><a class="reference internal" href="#check-your-code-for-errors-or-bad-habits-by-running-jshint" id="id23">Check your code for errors or bad habits by running JSHint</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#minification" id="id25">Minification</a><ul>
|
||||
<li><a class="reference internal" href="#minifying-javascript-and-css" id="id26">Minifying Javascript and CSS</a></li>
|
||||
<li><a class="reference internal" href="#minification" id="id24">Minification</a><ul>
|
||||
<li><a class="reference internal" href="#minifying-javascript-and-css" id="id25">Minifying Javascript and CSS</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#translations" id="id27">Translations</a></li>
|
||||
<li><a class="reference internal" href="#translations" id="id26">Translations</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#troubleshooting" id="id28">Troubleshooting</a><ul>
|
||||
<li><a class="reference internal" href="#conflicts-with-other-javascript-libraries" id="id29">Conflicts with other Javascript libraries</a><ul>
|
||||
<li><a class="reference internal" href="#problem" id="id30">Problem:</a></li>
|
||||
<li><a class="reference internal" href="#solution" id="id31">Solution:</a></li>
|
||||
<li><a class="reference internal" href="#troubleshooting" id="id27">Troubleshooting</a><ul>
|
||||
<li><a class="reference internal" href="#conflicts-with-other-javascript-libraries" id="id28">Conflicts with other Javascript libraries</a><ul>
|
||||
<li><a class="reference internal" href="#problem" id="id29">Problem:</a></li>
|
||||
<li><a class="reference internal" href="#solution" id="id30">Solution:</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#events" id="id32">Events</a><ul>
|
||||
<li><a class="reference internal" href="#event-methods" id="id33">Event Methods</a></li>
|
||||
<li><a class="reference internal" href="#event-types" id="id34">Event Types</a></li>
|
||||
<li><a class="reference internal" href="#events" id="id31">Events</a><ul>
|
||||
<li><a class="reference internal" href="#event-methods" id="id32">Event Methods</a></li>
|
||||
<li><a class="reference internal" href="#event-types" id="id33">Event Types</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#configuration" id="id35">Configuration</a><ul>
|
||||
<li><a class="reference internal" href="#configuration-variables" id="id36">Configuration variables</a><ul>
|
||||
<li><a class="reference internal" href="#allow-contact-requests" id="id37">allow_contact_requests</a></li>
|
||||
<li><a class="reference internal" href="#allow-muc" id="id38">allow_muc</a></li>
|
||||
<li><a class="reference internal" href="#animate" id="id39">animate</a></li>
|
||||
<li><a class="reference internal" href="#auto-list-rooms" id="id40">auto_list_rooms</a></li>
|
||||
<li><a class="reference internal" href="#auto-reconnect" id="id41">auto_reconnect</a></li>
|
||||
<li><a class="reference internal" href="#auto-subscribe" id="id42">auto_subscribe</a></li>
|
||||
<li><a class="reference internal" href="#bosh-service-url" id="id43">bosh_service_url</a></li>
|
||||
<li><a class="reference internal" href="#cache-otr-key" id="id44">cache_otr_key</a></li>
|
||||
<li><a class="reference internal" href="#debug" id="id45">debug</a></li>
|
||||
<li><a class="reference internal" href="#configuration" id="id34">Configuration</a><ul>
|
||||
<li><a class="reference internal" href="#configuration-variables" id="id35">Configuration variables</a><ul>
|
||||
<li><a class="reference internal" href="#allow-contact-requests" id="id36">allow_contact_requests</a></li>
|
||||
<li><a class="reference internal" href="#allow-muc" id="id37">allow_muc</a></li>
|
||||
<li><a class="reference internal" href="#animate" id="id38">animate</a></li>
|
||||
<li><a class="reference internal" href="#auto-list-rooms" id="id39">auto_list_rooms</a></li>
|
||||
<li><a class="reference internal" href="#auto-reconnect" id="id40">auto_reconnect</a></li>
|
||||
<li><a class="reference internal" href="#auto-subscribe" id="id41">auto_subscribe</a></li>
|
||||
<li><a class="reference internal" href="#bosh-service-url" id="id42">bosh_service_url</a></li>
|
||||
<li><a class="reference internal" href="#cache-otr-key" id="id43">cache_otr_key</a></li>
|
||||
<li><a class="reference internal" href="#debug" id="id44">debug</a></li>
|
||||
<li><a class="reference internal" href="#enable-message-carbons" id="id45">enable_message_carbons</a></li>
|
||||
<li><a class="reference internal" href="#expose-rid-and-sid" id="id46">expose_rid_and_sid</a></li>
|
||||
<li><a class="reference internal" href="#fullname" id="id47">fullname</a></li>
|
||||
<li><a class="reference internal" href="#hide-muc-server" id="id48">hide_muc_server</a></li>
|
||||
<li><a class="reference internal" href="#i18n" id="id49">i18n</a></li>
|
||||
<li><a class="reference internal" href="#prebind" id="id50">prebind</a></li>
|
||||
<li><a class="reference internal" href="#show-controlbox-by-default" id="id51">show_controlbox_by_default</a></li>
|
||||
<li><a class="reference internal" href="#show-call-button" id="id52">show_call_button</a></li>
|
||||
<li><a class="reference internal" href="#show-only-online-users" id="id53">show_only_online_users</a></li>
|
||||
<li><a class="reference internal" href="#use-otr-by-default" id="id54">use_otr_by_default</a></li>
|
||||
<li><a class="reference internal" href="#use-vcards" id="id55">use_vcards</a></li>
|
||||
<li><a class="reference internal" href="#xhr-custom-status" id="id56">xhr_custom_status</a></li>
|
||||
<li><a class="reference internal" href="#xhr-custom-status-url" id="id57">xhr_custom_status_url</a></li>
|
||||
<li><a class="reference internal" href="#xhr-user-search" id="id58">xhr_user_search</a></li>
|
||||
<li><a class="reference internal" href="#xhr-user-search-url" id="id59">xhr_user_search_url</a></li>
|
||||
<li><a class="reference internal" href="#forward-messages" id="id47">forward_messages</a></li>
|
||||
<li><a class="reference internal" href="#fullname" id="id48">fullname</a></li>
|
||||
<li><a class="reference internal" href="#hide-muc-server" id="id49">hide_muc_server</a></li>
|
||||
<li><a class="reference internal" href="#i18n" id="id50">i18n</a></li>
|
||||
<li><a class="reference internal" href="#prebind" id="id51">prebind</a></li>
|
||||
<li><a class="reference internal" href="#show-controlbox-by-default" id="id52">show_controlbox_by_default</a></li>
|
||||
<li><a class="reference internal" href="#show-call-button" id="id53">show_call_button</a></li>
|
||||
<li><a class="reference internal" href="#show-only-online-users" id="id54">show_only_online_users</a></li>
|
||||
<li><a class="reference internal" href="#use-otr-by-default" id="id55">use_otr_by_default</a></li>
|
||||
<li><a class="reference internal" href="#use-vcards" id="id56">use_vcards</a></li>
|
||||
<li><a class="reference internal" href="#xhr-custom-status" id="id57">xhr_custom_status</a></li>
|
||||
<li><a class="reference internal" href="#xhr-custom-status-url" id="id58">xhr_custom_status_url</a></li>
|
||||
<li><a class="reference internal" href="#xhr-user-search" id="id59">xhr_user_search</a></li>
|
||||
<li><a class="reference internal" href="#xhr-user-search-url" id="id60">xhr_user_search_url</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
@ -447,39 +448,41 @@ communications privacy, then you’re much better off using native software.
|
||||
notice that there are references to a missing <em>components</em> folder. Please
|
||||
follow the instructions below to create this folder and fetch Converse’s
|
||||
3rd-party dependencies.</p>
|
||||
<div class="section" id="install-node-js-and-development-dependencies">
|
||||
<h2><a class="toc-backref" href="#id17">Install Node.js and development dependencies</a><a class="headerlink" href="#install-node-js-and-development-dependencies" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="section" id="install-the-development-and-front-end-dependencies">
|
||||
<h2><a class="toc-backref" href="#id17">Install the development and front-end dependencies</a><a class="headerlink" href="#install-the-development-and-front-end-dependencies" title="Permalink to this headline">¶</a></h2>
|
||||
<p>We use development tools (<a class="reference external" href="http://gruntjs.com">Grunt</a> and <a class="reference external" href="http://bower.io">Bower</a>)
|
||||
which depend on Node.js and npm (the Node package manager).</p>
|
||||
<p>If you don’t have Node.js installed, you can download and install the latest
|
||||
version <a class="reference external" href="https://nodejs.org/download">here</a>.</p>
|
||||
<p>Once you have Node.js installed, run the following command inside the Converse.js
|
||||
<p>Also make sure you have <tt class="docutils literal"><span class="pre">git</span></tt> installed. <a class="reference external" href="http://git-scm.com/book/en/Getting-Started-Installing-Git">Details</a>.</p>
|
||||
<p>Once you have <em>Node.js</em> and <em>git</em> installed, run the following command inside the Converse.js
|
||||
directory:</p>
|
||||
<div class="highlight-python"><pre>npm install</pre>
|
||||
<div class="highlight-python"><pre>make dev</pre>
|
||||
</div>
|
||||
<p>This will install all the development dependencies for Converse.js. If you are
|
||||
curious to know what these are, take a look at whats under the <em>devDependencies</em> key in
|
||||
<p>This will first install the Node.js development tools (like Grunt and Bower)
|
||||
and then use Bower to install all of Converse.js’s front-end dependencies.</p>
|
||||
<p>The front-end dependencies are those javascript files on which
|
||||
Converse.js directly depends and which will therefore be loaded in the browser.</p>
|
||||
<p>If you are curious to know what the different dependencies are:</p>
|
||||
<ul>
|
||||
<li><dl class="first docutils">
|
||||
<dt>Development dependencies:</dt>
|
||||
<dd><p class="first last">Take a look at whats under the <em>devDependencies</em> key in
|
||||
<a class="reference external" href="https://github.com/jcbrand/converse.js/blob/master/package.json">package.json</a>.</p>
|
||||
</div>
|
||||
<div class="section" id="install-3rd-party-dependencies">
|
||||
<h2><a class="toc-backref" href="#id18">Install 3rd party dependencies</a><a class="headerlink" href="#install-3rd-party-dependencies" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Make sure you have <tt class="docutils literal"><span class="pre">git</span></tt> installed. <a class="reference external" href="http://git-scm.com/book/en/Getting-Started-Installing-Git">Details</a>.</p>
|
||||
<p>After running <tt class="docutils literal"><span class="pre">npm</span> <span class="pre">install</span></tt>, you will now have Grunt and Bower installed.</p>
|
||||
<p>We use Bower to manage Converse’s front-end dependencies (e.g. Javascript that
|
||||
should get loaded in the browser).</p>
|
||||
<p>To fetch these dependencies, run:</p>
|
||||
<div class="highlight-python"><pre>grunt fetch</pre>
|
||||
</div>
|
||||
<p>If you don’t have grunt installed globally, you need to specify the relative
|
||||
path:</p>
|
||||
<div class="highlight-python"><pre>./node_modules/.bin/grunt fetch</pre>
|
||||
</div>
|
||||
<p>This will call Bower in the background to fetch all the front-end
|
||||
dependencies (like backbone.js, strophe.js etc.) and then put them in the
|
||||
<em>components</em> folder.</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li><dl class="first docutils">
|
||||
<dt>Front-end dependencies:</dt>
|
||||
<dd><p class="first last">See <em>dependencies</em> in
|
||||
<a class="reference external" href="https://github.com/jcbrand/converse.js/blob/master/bower.json">bower.json</a>.</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="with-amd-and-require-js-recommended">
|
||||
<h2><a class="toc-backref" href="#id19">With AMD and require.js (recommended)</a><a class="headerlink" href="#with-amd-and-require-js-recommended" title="Permalink to this headline">¶</a></h2>
|
||||
<h2><a class="toc-backref" href="#id18">With AMD and require.js (recommended)</a><a class="headerlink" href="#with-amd-and-require-js-recommended" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Converse.js uses <a class="reference external" href="http://requirejs.org">require.js</a> to asynchronously load dependencies.</p>
|
||||
<p>If you want to develop or customize converse.js, you’ll want to load the
|
||||
non-minified javascript files.</p>
|
||||
@ -492,7 +495,7 @@ attribute on the <em>script</em> tag), which will in turn cause converse.js to b
|
||||
parsed.</p>
|
||||
</div>
|
||||
<div class="section" id="without-amd-and-require-js">
|
||||
<h2><a class="toc-backref" href="#id20">Without AMD and require.js</a><a class="headerlink" href="#without-amd-and-require-js" title="Permalink to this headline">¶</a></h2>
|
||||
<h2><a class="toc-backref" href="#id19">Without AMD and require.js</a><a class="headerlink" href="#without-amd-and-require-js" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Converse.js can also be used without require.js. If you for some reason prefer
|
||||
to use it this way, please refer to
|
||||
<a class="reference external" href="https://github.com/jcbrand/converse.js/blob/master/non_amd.html">non_amd.html</a>
|
||||
@ -500,9 +503,9 @@ for an example of how and in what order all the Javascript files that converse.j
|
||||
depends on need to be loaded.</p>
|
||||
</div>
|
||||
<div class="section" id="before-submitting-a-pull-request">
|
||||
<h2><a class="toc-backref" href="#id21">Before submitting a pull request</a><a class="headerlink" href="#before-submitting-a-pull-request" title="Permalink to this headline">¶</a></h2>
|
||||
<h2><a class="toc-backref" href="#id20">Before submitting a pull request</a><a class="headerlink" href="#before-submitting-a-pull-request" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="section" id="add-tests-for-your-bugfix-or-feature">
|
||||
<h3><a class="toc-backref" href="#id22">Add tests for your bugfix or feature</a><a class="headerlink" href="#add-tests-for-your-bugfix-or-feature" title="Permalink to this headline">¶</a></h3>
|
||||
<h3><a class="toc-backref" href="#id21">Add tests for your bugfix or feature</a><a class="headerlink" href="#add-tests-for-your-bugfix-or-feature" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Add a test for any bug fixed or feature added. We use Jasmine
|
||||
for testing.</p>
|
||||
<p>Take a look at <tt class="docutils literal"><span class="pre">tests.html</span></tt> and <tt class="docutils literal"><span class="pre">spec/MainSpec.js</span></tt> to see how
|
||||
@ -511,7 +514,7 @@ the tests are implemented.</p>
|
||||
<a class="reference external" href="http://opkode.com/contact">contact me</a> and I’ll be happy to help.</p>
|
||||
</div>
|
||||
<div class="section" id="check-that-the-tests-pass">
|
||||
<h3><a class="toc-backref" href="#id23">Check that the tests pass</a><a class="headerlink" href="#check-that-the-tests-pass" title="Permalink to this headline">¶</a></h3>
|
||||
<h3><a class="toc-backref" href="#id22">Check that the tests pass</a><a class="headerlink" href="#check-that-the-tests-pass" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Check that the Jasmine tests complete sucessfully. Open
|
||||
<a class="reference external" href="https://github.com/jcbrand/converse.js/blob/master/tests.html">tests.html</a>
|
||||
in your browser, and the tests will run automatically.</p>
|
||||
@ -520,7 +523,7 @@ in your browser, and the tests will run automatically.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="check-your-code-for-errors-or-bad-habits-by-running-jshint">
|
||||
<h3><a class="toc-backref" href="#id24">Check your code for errors or bad habits by running JSHint</a><a class="headerlink" href="#check-your-code-for-errors-or-bad-habits-by-running-jshint" title="Permalink to this headline">¶</a></h3>
|
||||
<h3><a class="toc-backref" href="#id23">Check your code for errors or bad habits by running JSHint</a><a class="headerlink" href="#check-your-code-for-errors-or-bad-habits-by-running-jshint" title="Permalink to this headline">¶</a></h3>
|
||||
<p><a class="reference external" href="http://jshint.com">JSHint</a> will do a static analysis of your code and hightlight potential errors
|
||||
and/or bad habits.</p>
|
||||
<div class="highlight-python"><pre>grunt jshint</pre>
|
||||
@ -531,9 +534,9 @@ and/or bad habits.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="minification">
|
||||
<h2><a class="toc-backref" href="#id25">Minification</a><a class="headerlink" href="#minification" title="Permalink to this headline">¶</a></h2>
|
||||
<h2><a class="toc-backref" href="#id24">Minification</a><a class="headerlink" href="#minification" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="section" id="minifying-javascript-and-css">
|
||||
<h3><a class="toc-backref" href="#id26">Minifying Javascript and CSS</a><a class="headerlink" href="#minifying-javascript-and-css" title="Permalink to this headline">¶</a></h3>
|
||||
<h3><a class="toc-backref" href="#id25">Minifying Javascript and CSS</a><a class="headerlink" href="#minifying-javascript-and-css" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Please make sure to read the section <a class="reference internal" href="#development">Development</a> and that you have installed
|
||||
all development dependencies (long story short, you can run <tt class="docutils literal"><span class="pre">npm</span> <span class="pre">install</span></tt>
|
||||
and then <tt class="docutils literal"><span class="pre">grunt</span> <span class="pre">fetch</span></tt>).</p>
|
||||
@ -550,7 +553,7 @@ using <a class="reference external" href="https://github.com/jrburke/almond">alm
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="translations">
|
||||
<h2><a class="toc-backref" href="#id27">Translations</a><a class="headerlink" href="#translations" title="Permalink to this headline">¶</a></h2>
|
||||
<h2><a class="toc-backref" href="#id26">Translations</a><a class="headerlink" href="#translations" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="admonition note">
|
||||
<p class="first admonition-title">Note</p>
|
||||
<p class="last">Translations take up a lot of space and will bloat your minified file.
|
||||
@ -576,7 +579,7 @@ function like so:</p>
|
||||
<div class="highlight-python"><pre>msgmerge ./locale/de/LC_MESSAGES/converse.po ./locale/converse.pot -U</pre>
|
||||
</div>
|
||||
<p>To do this for ALL languages, run:</p>
|
||||
<div class="highlight-python"><pre>make merge</pre>
|
||||
<div class="highlight-python"><pre>make po</pre>
|
||||
</div>
|
||||
<p>The resulting PO file is then what gets translated.</p>
|
||||
<p>If you’ve created a new PO file, please make sure to add the following
|
||||
@ -627,18 +630,18 @@ those hoops you had to jump through.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="troubleshooting">
|
||||
<h1><a class="toc-backref" href="#id28">Troubleshooting</a><a class="headerlink" href="#troubleshooting" title="Permalink to this headline">¶</a></h1>
|
||||
<h1><a class="toc-backref" href="#id27">Troubleshooting</a><a class="headerlink" href="#troubleshooting" title="Permalink to this headline">¶</a></h1>
|
||||
<div class="section" id="conflicts-with-other-javascript-libraries">
|
||||
<h2><a class="toc-backref" href="#id29">Conflicts with other Javascript libraries</a><a class="headerlink" href="#conflicts-with-other-javascript-libraries" title="Permalink to this headline">¶</a></h2>
|
||||
<h2><a class="toc-backref" href="#id28">Conflicts with other Javascript libraries</a><a class="headerlink" href="#conflicts-with-other-javascript-libraries" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="section" id="problem">
|
||||
<h3><a class="toc-backref" href="#id30">Problem:</a><a class="headerlink" href="#problem" title="Permalink to this headline">¶</a></h3>
|
||||
<h3><a class="toc-backref" href="#id29">Problem:</a><a class="headerlink" href="#problem" title="Permalink to this headline">¶</a></h3>
|
||||
<p>You are using other Javascript libraries (like JQuery plugins), and
|
||||
get errors like these in your browser console:</p>
|
||||
<div class="highlight-python"><pre>Uncaught TypeError: Object [object Object] has no method 'xxx' from example.js</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="solution">
|
||||
<h3><a class="toc-backref" href="#id31">Solution:</a><a class="headerlink" href="#solution" title="Permalink to this headline">¶</a></h3>
|
||||
<h3><a class="toc-backref" href="#id30">Solution:</a><a class="headerlink" href="#solution" title="Permalink to this headline">¶</a></h3>
|
||||
<p>First, find out which object is referred to by <tt class="docutils literal"><span class="pre">Object</span> <span class="pre">[object</span> <span class="pre">Object]</span></tt>.</p>
|
||||
<p>It will probably be the jQuery object <tt class="docutils literal"><span class="pre">$</span></tt> or perhaps the underscore.js object <tt class="docutils literal"><span class="pre">_</span></tt>.</p>
|
||||
<p>For the purpose of demonstration, I’m going to assume its <tt class="docutils literal"><span class="pre">$</span></tt>, but the same
|
||||
@ -680,11 +683,11 @@ jQuery plugins must load after jQuery).</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="events">
|
||||
<h1><a class="toc-backref" href="#id32">Events</a><a class="headerlink" href="#events" title="Permalink to this headline">¶</a></h1>
|
||||
<h1><a class="toc-backref" href="#id31">Events</a><a class="headerlink" href="#events" title="Permalink to this headline">¶</a></h1>
|
||||
<p>Converse.js emits events to which you can subscribe from your own Javascript.</p>
|
||||
<p>Concerning events, the following methods are available:</p>
|
||||
<div class="section" id="event-methods">
|
||||
<h2><a class="toc-backref" href="#id33">Event Methods</a><a class="headerlink" href="#event-methods" title="Permalink to this headline">¶</a></h2>
|
||||
<h2><a class="toc-backref" href="#id32">Event Methods</a><a class="headerlink" href="#event-methods" title="Permalink to this headline">¶</a></h2>
|
||||
<ul>
|
||||
<li><p class="first"><strong>on(eventName, callback)</strong>:</p>
|
||||
<blockquote>
|
||||
@ -728,7 +731,7 @@ exactly once.</p>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="event-types">
|
||||
<h2><a class="toc-backref" href="#id34">Event Types</a><a class="headerlink" href="#event-types" title="Permalink to this headline">¶</a></h2>
|
||||
<h2><a class="toc-backref" href="#id33">Event Types</a><a class="headerlink" href="#event-types" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Here are the different events that are emitted:</p>
|
||||
<ul>
|
||||
<li><p class="first"><strong>onInitialized</strong></p>
|
||||
@ -768,6 +771,12 @@ got all its ducks in a row.</p>
|
||||
<p>Triggered whenever the roster view (i.e. the rendered HTML) has changed.</p>
|
||||
</div></blockquote>
|
||||
</li>
|
||||
<li><p class="first"><strong>onChatBoxClosed</strong></p>
|
||||
<blockquote>
|
||||
<div><p><tt class="docutils literal"><span class="pre">converse.on('onChatBoxClosed',</span> <span class="pre">function</span> <span class="pre">(chatbox)</span> <span class="pre">{</span> <span class="pre">...</span> <span class="pre">});</span></tt></p>
|
||||
<p>Triggered when a chat box has been closed.</p>
|
||||
</div></blockquote>
|
||||
</li>
|
||||
<li><p class="first"><strong>onChatBoxFocused</strong></p>
|
||||
<blockquote>
|
||||
<div><p><tt class="docutils literal"><span class="pre">converse.on('onChatBoxFocused',</span> <span class="pre">function</span> <span class="pre">(chatbox)</span> <span class="pre">{</span> <span class="pre">...</span> <span class="pre">});</span></tt></p>
|
||||
@ -780,10 +789,10 @@ got all its ducks in a row.</p>
|
||||
<p>Triggered when a chat box has been opened.</p>
|
||||
</div></blockquote>
|
||||
</li>
|
||||
<li><p class="first"><strong>onChatBoxClosed</strong></p>
|
||||
<li><p class="first"><strong>onChatBoxToggled</strong></p>
|
||||
<blockquote>
|
||||
<div><p><tt class="docutils literal"><span class="pre">converse.on('onChatBoxClosed',</span> <span class="pre">function</span> <span class="pre">(chatbox)</span> <span class="pre">{</span> <span class="pre">...</span> <span class="pre">});</span></tt></p>
|
||||
<p>Triggered when a chat box has been closed.</p>
|
||||
<div><p><tt class="docutils literal"><span class="pre">converse.on('onChatBoxToggled',</span> <span class="pre">function</span> <span class="pre">(chatbox)</span> <span class="pre">{</span> <span class="pre">...</span> <span class="pre">});</span></tt></p>
|
||||
<p>Triggered when a chat box has been minimized or maximized.</p>
|
||||
</div></blockquote>
|
||||
</li>
|
||||
<li><p class="first"><strong>onStatusChanged</strong></p>
|
||||
@ -814,7 +823,7 @@ got all its ducks in a row.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="configuration">
|
||||
<h1><a class="toc-backref" href="#id35">Configuration</a><a class="headerlink" href="#configuration" title="Permalink to this headline">¶</a></h1>
|
||||
<h1><a class="toc-backref" href="#id34">Configuration</a><a class="headerlink" href="#configuration" title="Permalink to this headline">¶</a></h1>
|
||||
<p>The included minified JS and CSS files can be used for demoing or testing, but
|
||||
you’ll want to configure <em>Converse.js</em> to suit your needs before you deploy it
|
||||
on your website.</p>
|
||||
@ -828,9 +837,9 @@ all the available configuration settings.</p>
|
||||
JS file so that it will include the new settings. Please refer to the
|
||||
<a class="reference internal" href="#minification">Minification</a> section for more info on how to do this.</p>
|
||||
<div class="section" id="configuration-variables">
|
||||
<h2><a class="toc-backref" href="#id36">Configuration variables</a><a class="headerlink" href="#configuration-variables" title="Permalink to this headline">¶</a></h2>
|
||||
<h2><a class="toc-backref" href="#id35">Configuration variables</a><a class="headerlink" href="#configuration-variables" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="section" id="allow-contact-requests">
|
||||
<h3><a class="toc-backref" href="#id37">allow_contact_requests</a><a class="headerlink" href="#allow-contact-requests" title="Permalink to this headline">¶</a></h3>
|
||||
<h3><a class="toc-backref" href="#id36">allow_contact_requests</a><a class="headerlink" href="#allow-contact-requests" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Default = <tt class="docutils literal"><span class="pre">true</span></tt></p>
|
||||
<p>Allow users to add one another as contacts. If this is set to false, the
|
||||
<strong>Add a contact</strong> widget, <strong>Contact Requests</strong> and <strong>Pending Contacts</strong> roster
|
||||
@ -838,18 +847,18 @@ sections will all not appear. Additionally, all incoming contact requests will b
|
||||
ignored.</p>
|
||||
</div>
|
||||
<div class="section" id="allow-muc">
|
||||
<h3><a class="toc-backref" href="#id38">allow_muc</a><a class="headerlink" href="#allow-muc" title="Permalink to this headline">¶</a></h3>
|
||||
<h3><a class="toc-backref" href="#id37">allow_muc</a><a class="headerlink" href="#allow-muc" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Default = <tt class="docutils literal"><span class="pre">true</span></tt></p>
|
||||
<p>Allow multi-user chat (muc) in chatrooms. Setting this to <tt class="docutils literal"><span class="pre">false</span></tt> will remove
|
||||
the <tt class="docutils literal"><span class="pre">Chatrooms</span></tt> tab from the control box.</p>
|
||||
</div>
|
||||
<div class="section" id="animate">
|
||||
<h3><a class="toc-backref" href="#id39">animate</a><a class="headerlink" href="#animate" title="Permalink to this headline">¶</a></h3>
|
||||
<h3><a class="toc-backref" href="#id38">animate</a><a class="headerlink" href="#animate" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Default = <tt class="docutils literal"><span class="pre">true</span></tt></p>
|
||||
<p>Show animations, for example when opening and closing chat boxes.</p>
|
||||
</div>
|
||||
<div class="section" id="auto-list-rooms">
|
||||
<h3><a class="toc-backref" href="#id40">auto_list_rooms</a><a class="headerlink" href="#auto-list-rooms" title="Permalink to this headline">¶</a></h3>
|
||||
<h3><a class="toc-backref" href="#id39">auto_list_rooms</a><a class="headerlink" href="#auto-list-rooms" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Default = <tt class="docutils literal"><span class="pre">false</span></tt></p>
|
||||
<p>If true, and the XMPP server on which the current user is logged in supports
|
||||
multi-user chat, then a list of rooms on that server will be fetched.</p>
|
||||
@ -859,24 +868,24 @@ features, number of occupants etc.), so on servers with many rooms this
|
||||
option will create lots of extra connection traffic.</p>
|
||||
</div>
|
||||
<div class="section" id="auto-reconnect">
|
||||
<h3><a class="toc-backref" href="#id41">auto_reconnect</a><a class="headerlink" href="#auto-reconnect" title="Permalink to this headline">¶</a></h3>
|
||||
<h3><a class="toc-backref" href="#id40">auto_reconnect</a><a class="headerlink" href="#auto-reconnect" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Default = <tt class="docutils literal"><span class="pre">true</span></tt></p>
|
||||
<p>Automatically reconnect to the XMPP server if the connection drops
|
||||
unexpectedly.</p>
|
||||
</div>
|
||||
<div class="section" id="auto-subscribe">
|
||||
<h3><a class="toc-backref" href="#id42">auto_subscribe</a><a class="headerlink" href="#auto-subscribe" title="Permalink to this headline">¶</a></h3>
|
||||
<h3><a class="toc-backref" href="#id41">auto_subscribe</a><a class="headerlink" href="#auto-subscribe" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Default = <tt class="docutils literal"><span class="pre">false</span></tt></p>
|
||||
<p>If true, the user will automatically subscribe back to any contact requests.</p>
|
||||
</div>
|
||||
<div class="section" id="bosh-service-url">
|
||||
<h3><a class="toc-backref" href="#id43">bosh_service_url</a><a class="headerlink" href="#bosh-service-url" title="Permalink to this headline">¶</a></h3>
|
||||
<h3><a class="toc-backref" href="#id42">bosh_service_url</a><a class="headerlink" href="#bosh-service-url" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Connections to an XMPP server depend on a BOSH connection manager which acts as
|
||||
a middle man between HTTP and XMPP.</p>
|
||||
<p>See <a class="reference external" href="http://metajack.im/2008/09/08/which-bosh-server-do-you-need">here</a> for more information.</p>
|
||||
</div>
|
||||
<div class="section" id="cache-otr-key">
|
||||
<h3><a class="toc-backref" href="#id44">cache_otr_key</a><a class="headerlink" href="#cache-otr-key" title="Permalink to this headline">¶</a></h3>
|
||||
<h3><a class="toc-backref" href="#id43">cache_otr_key</a><a class="headerlink" href="#cache-otr-key" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Default = <tt class="docutils literal"><span class="pre">false</span></tt></p>
|
||||
<p>Let the <a class="reference external" href="https://otr.cypherpunks.ca">OTR (Off-the-record encryption)</a> private
|
||||
key be cached in your browser’s session storage.</p>
|
||||
@ -895,37 +904,52 @@ current session. Previous sessions however cannot be decrypted.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="debug">
|
||||
<h3><a class="toc-backref" href="#id45">debug</a><a class="headerlink" href="#debug" title="Permalink to this headline">¶</a></h3>
|
||||
<h3><a class="toc-backref" href="#id44">debug</a><a class="headerlink" href="#debug" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Default = <tt class="docutils literal"><span class="pre">false</span></tt></p>
|
||||
<p>If set to true, debugging output will be logged to the browser console.</p>
|
||||
</div>
|
||||
<div class="section" id="enable-message-carbons">
|
||||
<h3><a class="toc-backref" href="#id45">enable_message_carbons</a><a class="headerlink" href="#enable-message-carbons" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Default = <tt class="docutils literal"><span class="pre">false</span></tt></p>
|
||||
<p>Support for <a class="reference external" href="https://xmpp.org/extensions/xep-0280.html">XEP-0280: Message Carbons</a></p>
|
||||
</div>
|
||||
<div class="section" id="expose-rid-and-sid">
|
||||
<h3><a class="toc-backref" href="#id46">expose_rid_and_sid</a><a class="headerlink" href="#expose-rid-and-sid" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Default = <tt class="docutils literal"><span class="pre">false</span></tt></p>
|
||||
<p>Allow the prebind tokens, RID (request ID) and SID (session ID), to be exposed
|
||||
globally via the API. This allows other scripts served on the same page to use
|
||||
these values.</p>
|
||||
<p><em>Beware</em>: a malicious script could use these tokens to assume your identity
|
||||
and inject fake chat messages.</p>
|
||||
</div>
|
||||
<div class="section" id="forward-messages">
|
||||
<h3><a class="toc-backref" href="#id47">forward_messages</a><a class="headerlink" href="#forward-messages" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Default = <tt class="docutils literal"><span class="pre">false</span></tt></p>
|
||||
<p>If set to <tt class="docutils literal"><span class="pre">true</span></tt>, sent messages will also be forwarded to other connected
|
||||
XMPP resources (e.g. chat clients) of the same user.</p>
|
||||
<p>This is useful for example if converse.js is running in multiple tabs of the
|
||||
browser and you want sent messages to appear in all of them.</p>
|
||||
<p>See also <a class="reference external" href="http://www.xmpp.org/extensions/xep-0297.html">XEP 0297: Stanza Forwarding</a></p>
|
||||
</div>
|
||||
<div class="section" id="fullname">
|
||||
<h3><a class="toc-backref" href="#id47">fullname</a><a class="headerlink" href="#fullname" title="Permalink to this headline">¶</a></h3>
|
||||
<h3><a class="toc-backref" href="#id48">fullname</a><a class="headerlink" href="#fullname" title="Permalink to this headline">¶</a></h3>
|
||||
<p>If you are using prebinding, can specify the fullname of the currently
|
||||
logged in user, otherwise the user’s vCard will be fetched.</p>
|
||||
</div>
|
||||
<div class="section" id="hide-muc-server">
|
||||
<h3><a class="toc-backref" href="#id48">hide_muc_server</a><a class="headerlink" href="#hide-muc-server" title="Permalink to this headline">¶</a></h3>
|
||||
<h3><a class="toc-backref" href="#id49">hide_muc_server</a><a class="headerlink" href="#hide-muc-server" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Default = <tt class="docutils literal"><span class="pre">false</span></tt></p>
|
||||
<p>Hide the <tt class="docutils literal"><span class="pre">server</span></tt> input field of the form inside the <tt class="docutils literal"><span class="pre">Room</span></tt> panel of the
|
||||
controlbox. Useful if you want to restrict users to a specific XMPP server of
|
||||
your choosing.</p>
|
||||
</div>
|
||||
<div class="section" id="i18n">
|
||||
<h3><a class="toc-backref" href="#id49">i18n</a><a class="headerlink" href="#i18n" title="Permalink to this headline">¶</a></h3>
|
||||
<h3><a class="toc-backref" href="#id50">i18n</a><a class="headerlink" href="#i18n" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Specify the locale/language. The language must be in the <tt class="docutils literal"><span class="pre">locales</span></tt> object. Refer to
|
||||
<tt class="docutils literal"><span class="pre">./locale/locales.js</span></tt> to see which locales are supported.</p>
|
||||
</div>
|
||||
<div class="section" id="prebind">
|
||||
<h3><a class="toc-backref" href="#id50">prebind</a><a class="headerlink" href="#prebind" title="Permalink to this headline">¶</a></h3>
|
||||
<h3><a class="toc-backref" href="#id51">prebind</a><a class="headerlink" href="#prebind" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Default = <tt class="docutils literal"><span class="pre">false</span></tt></p>
|
||||
<p>Use this option when you want to attach to an existing XMPP connection that was
|
||||
already authenticated (usually on the backend before page load).</p>
|
||||
@ -938,7 +962,7 @@ values as <tt class="docutils literal"><span class="pre">jid</span></tt>, <tt cl
|
||||
<p>Additionally, you have to specify <tt class="docutils literal"><span class="pre">bosh_service_url</span></tt>.</p>
|
||||
</div>
|
||||
<div class="section" id="show-controlbox-by-default">
|
||||
<h3><a class="toc-backref" href="#id51">show_controlbox_by_default</a><a class="headerlink" href="#show-controlbox-by-default" title="Permalink to this headline">¶</a></h3>
|
||||
<h3><a class="toc-backref" href="#id52">show_controlbox_by_default</a><a class="headerlink" href="#show-controlbox-by-default" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Default = <tt class="docutils literal"><span class="pre">false</span></tt></p>
|
||||
<p>The “controlbox” refers to the special chatbox containing your contacts roster,
|
||||
status widget, chatrooms and other controls.</p>
|
||||
@ -948,7 +972,7 @@ the page with class <em>toggle-online-users</em>.</p>
|
||||
page load.</p>
|
||||
</div>
|
||||
<div class="section" id="show-call-button">
|
||||
<h3><a class="toc-backref" href="#id52">show_call_button</a><a class="headerlink" href="#show-call-button" title="Permalink to this headline">¶</a></h3>
|
||||
<h3><a class="toc-backref" href="#id53">show_call_button</a><a class="headerlink" href="#show-call-button" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Default = <tt class="docutils literal"><span class="pre">false</span></tt></p>
|
||||
<p>Enable to display a call button on the chatbox toolbar.</p>
|
||||
<p>When the call button is pressed, it will emit an event that can be used by a third-party library to initiate a call.</p>
|
||||
@ -962,26 +986,26 @@ page load.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="show-only-online-users">
|
||||
<h3><a class="toc-backref" href="#id53">show_only_online_users</a><a class="headerlink" href="#show-only-online-users" title="Permalink to this headline">¶</a></h3>
|
||||
<h3><a class="toc-backref" href="#id54">show_only_online_users</a><a class="headerlink" href="#show-only-online-users" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Default = <tt class="docutils literal"><span class="pre">false</span></tt></p>
|
||||
<p>If set to <tt class="docutils literal"><span class="pre">true</span></tt>, only online users will be shown in the contacts roster.
|
||||
Users with any other status (e.g. away, busy etc.) will not be shown.</p>
|
||||
</div>
|
||||
<div class="section" id="use-otr-by-default">
|
||||
<h3><a class="toc-backref" href="#id54">use_otr_by_default</a><a class="headerlink" href="#use-otr-by-default" title="Permalink to this headline">¶</a></h3>
|
||||
<h3><a class="toc-backref" href="#id55">use_otr_by_default</a><a class="headerlink" href="#use-otr-by-default" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Default = <tt class="docutils literal"><span class="pre">false</span></tt></p>
|
||||
<p>If set to <tt class="docutils literal"><span class="pre">true</span></tt>, Converse.js will automatically try to initiate an OTR (off-the-record)
|
||||
encrypted chat session every time you open a chat box.</p>
|
||||
</div>
|
||||
<div class="section" id="use-vcards">
|
||||
<h3><a class="toc-backref" href="#id55">use_vcards</a><a class="headerlink" href="#use-vcards" title="Permalink to this headline">¶</a></h3>
|
||||
<h3><a class="toc-backref" href="#id56">use_vcards</a><a class="headerlink" href="#use-vcards" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Default = <tt class="docutils literal"><span class="pre">true</span></tt></p>
|
||||
<p>Determines whether the XMPP server will be queried for roster contacts’ VCards
|
||||
or not. VCards contain extra personal information such as your fullname and
|
||||
avatar image.</p>
|
||||
</div>
|
||||
<div class="section" id="xhr-custom-status">
|
||||
<h3><a class="toc-backref" href="#id56">xhr_custom_status</a><a class="headerlink" href="#xhr-custom-status" title="Permalink to this headline">¶</a></h3>
|
||||
<h3><a class="toc-backref" href="#id57">xhr_custom_status</a><a class="headerlink" href="#xhr-custom-status" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Default = <tt class="docutils literal"><span class="pre">false</span></tt></p>
|
||||
<div class="admonition note">
|
||||
<p class="first admonition-title">Note</p>
|
||||
@ -991,7 +1015,7 @@ avatar image.</p>
|
||||
remote server.</p>
|
||||
</div>
|
||||
<div class="section" id="xhr-custom-status-url">
|
||||
<h3><a class="toc-backref" href="#id57">xhr_custom_status_url</a><a class="headerlink" href="#xhr-custom-status-url" title="Permalink to this headline">¶</a></h3>
|
||||
<h3><a class="toc-backref" href="#id58">xhr_custom_status_url</a><a class="headerlink" href="#xhr-custom-status-url" title="Permalink to this headline">¶</a></h3>
|
||||
<div class="admonition note">
|
||||
<p class="first admonition-title">Note</p>
|
||||
<p class="last">XHR stands for XMLHTTPRequest, and is meant here in the AJAX sense (Asynchronous Javascript and XML).</p>
|
||||
@ -1003,7 +1027,7 @@ message will be made.</p>
|
||||
<p>The message itself is sent in the request under the key <tt class="docutils literal"><span class="pre">msg</span></tt>.</p>
|
||||
</div>
|
||||
<div class="section" id="xhr-user-search">
|
||||
<h3><a class="toc-backref" href="#id58">xhr_user_search</a><a class="headerlink" href="#xhr-user-search" title="Permalink to this headline">¶</a></h3>
|
||||
<h3><a class="toc-backref" href="#id59">xhr_user_search</a><a class="headerlink" href="#xhr-user-search" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Default = <tt class="docutils literal"><span class="pre">false</span></tt></p>
|
||||
<div class="admonition note">
|
||||
<p class="first admonition-title">Note</p>
|
||||
@ -1020,7 +1044,7 @@ message will be made.</p>
|
||||
corresponds to a matched user and needs the keys <tt class="docutils literal"><span class="pre">id</span></tt> and <tt class="docutils literal"><span class="pre">fullname</span></tt>.</p>
|
||||
</div>
|
||||
<div class="section" id="xhr-user-search-url">
|
||||
<h3><a class="toc-backref" href="#id59">xhr_user_search_url</a><a class="headerlink" href="#xhr-user-search-url" title="Permalink to this headline">¶</a></h3>
|
||||
<h3><a class="toc-backref" href="#id60">xhr_user_search_url</a><a class="headerlink" href="#xhr-user-search-url" title="Permalink to this headline">¶</a></h3>
|
||||
<div class="admonition note">
|
||||
<p class="first admonition-title">Note</p>
|
||||
<p class="last">XHR stands for XMLHTTPRequest, and is meant here in the AJAX sense (Asynchronous Javascript and XML).</p>
|
||||
@ -1046,7 +1070,7 @@ The query string will be included in the request with <tt class="docutils litera
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li><a href="#">Converse.js 0.7.4 documentation</a> »</li>
|
||||
<li><a href="#">Converse.js 0.8.0 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Sphinx inventory version 2
|
||||
# Project: Converse.js
|
||||
# Version: 0.7.4
|
||||
# Version: 0.8.0
|
||||
# The remainder of this file is compressed using zlib.
|
||||
xÚmÎÁ
|
||||
à à{Ÿ"°³ƒ]÷;
|
||||
|
@ -7,7 +7,7 @@
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>Search — Converse.js 0.7.4 documentation</title>
|
||||
<title>Search — Converse.js 0.8.0 documentation</title>
|
||||
|
||||
<link rel="stylesheet" href="_static/stylesheet.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
@ -15,7 +15,7 @@
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '',
|
||||
VERSION: '0.7.4',
|
||||
VERSION: '0.8.0',
|
||||
COLLAPSE_INDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
@ -25,7 +25,7 @@
|
||||
<script type="text/javascript" src="_static/underscore.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<script type="text/javascript" src="_static/searchtools.js"></script>
|
||||
<link rel="top" title="Converse.js 0.7.4 documentation" href="index.html" />
|
||||
<link rel="top" title="Converse.js 0.8.0 documentation" href="index.html" />
|
||||
<script type="text/javascript">
|
||||
jQuery(function() { Search.loadIndex("searchindex.js"); });
|
||||
</script>
|
||||
@ -55,7 +55,7 @@
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li><a href="index.html">Converse.js 0.7.4 documentation</a> »</li>
|
||||
<li><a href="index.html">Converse.js 0.8.0 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<section id="main_content" class="inner">
|
||||
@ -100,7 +100,7 @@
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li><a href="index.html">Converse.js 0.7.4 documentation</a> »</li>
|
||||
<li><a href="index.html">Converse.js 0.8.0 documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
File diff suppressed because one or more lines are too long
@ -48,9 +48,9 @@ copyright = u'2013, JC Brand'
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '0.7.4'
|
||||
version = '0.8.0'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '0.7.4'
|
||||
release = '0.8.0'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
@ -392,8 +392,8 @@ follow the instructions below to create this folder and fetch Converse's
|
||||
3rd-party dependencies.
|
||||
|
||||
|
||||
Install Node.js and development dependencies
|
||||
============================================
|
||||
Install the development and front-end dependencies
|
||||
==================================================
|
||||
|
||||
We use development tools (`Grunt <http://gruntjs.com>`_ and `Bower <http://bower.io>`_)
|
||||
which depend on Node.js and npm (the Node package manager).
|
||||
@ -401,43 +401,38 @@ which depend on Node.js and npm (the Node package manager).
|
||||
If you don't have Node.js installed, you can download and install the latest
|
||||
version `here <https://nodejs.org/download>`_.
|
||||
|
||||
Once you have Node.js installed, run the following command inside the Converse.js
|
||||
Also make sure you have ``git`` installed. `Details <http://git-scm.com/book/en/Getting-Started-Installing-Git>`_.
|
||||
|
||||
Once you have *Node.js* and *git* installed, run the following command inside the Converse.js
|
||||
directory:
|
||||
|
||||
::
|
||||
|
||||
npm install
|
||||
make dev
|
||||
|
||||
This will install all the development dependencies for Converse.js. If you are
|
||||
curious to know what these are, take a look at whats under the *devDependencies* key in
|
||||
`package.json <https://github.com/jcbrand/converse.js/blob/master/package.json>`_.
|
||||
This will first install the Node.js development tools (like Grunt and Bower)
|
||||
and then use Bower to install all of Converse.js's front-end dependencies.
|
||||
|
||||
Install 3rd party dependencies
|
||||
==============================
|
||||
The front-end dependencies are those javascript files on which
|
||||
Converse.js directly depends and which will therefore be loaded in the browser.
|
||||
|
||||
Make sure you have ``git`` installed. `Details <http://git-scm.com/book/en/Getting-Started-Installing-Git>`_.
|
||||
If you are curious to know what the different dependencies are:
|
||||
|
||||
After running ``npm install``, you will now have Grunt and Bower installed.
|
||||
* Development dependencies:
|
||||
Take a look at whats under the *devDependencies* key in
|
||||
`package.json <https://github.com/jcbrand/converse.js/blob/master/package.json>`_.
|
||||
|
||||
We use Bower to manage Converse's front-end dependencies (e.g. Javascript that
|
||||
should get loaded in the browser).
|
||||
* Front-end dependencies:
|
||||
See *dependencies* in
|
||||
`bower.json <https://github.com/jcbrand/converse.js/blob/master/bower.json>`_.
|
||||
|
||||
To fetch these dependencies, run:
|
||||
.. Note:
|
||||
After running ```make dev```, you should now have a new directory *components*,
|
||||
which contains all the front-end dependencies of Converse.js.
|
||||
If this directory does NOT exist, something must have gone wrong.
|
||||
Double-check the output of ```make dev``` to see if there are any errors
|
||||
listed.
|
||||
|
||||
::
|
||||
|
||||
grunt fetch
|
||||
|
||||
If you don't have grunt installed globally, you need to specify the relative
|
||||
path:
|
||||
|
||||
::
|
||||
|
||||
./node_modules/.bin/grunt fetch
|
||||
|
||||
This will call Bower in the background to fetch all the front-end
|
||||
dependencies (like backbone.js, strophe.js etc.) and then put them in the
|
||||
*components* folder.
|
||||
|
||||
With AMD and require.js (recommended)
|
||||
=====================================
|
||||
@ -580,7 +575,7 @@ To do this for ALL languages, run:
|
||||
|
||||
::
|
||||
|
||||
make merge
|
||||
make po
|
||||
|
||||
The resulting PO file is then what gets translated.
|
||||
|
||||
@ -807,6 +802,12 @@ Here are the different events that are emitted:
|
||||
|
||||
Triggered whenever the roster view (i.e. the rendered HTML) has changed.
|
||||
|
||||
* **onChatBoxClosed**
|
||||
|
||||
``converse.on('onChatBoxClosed', function (chatbox) { ... });``
|
||||
|
||||
Triggered when a chat box has been closed.
|
||||
|
||||
* **onChatBoxFocused**
|
||||
|
||||
``converse.on('onChatBoxFocused', function (chatbox) { ... });``
|
||||
@ -819,11 +820,11 @@ Here are the different events that are emitted:
|
||||
|
||||
Triggered when a chat box has been opened.
|
||||
|
||||
* **onChatBoxClosed**
|
||||
* **onChatBoxToggled**
|
||||
|
||||
``converse.on('onChatBoxClosed', function (chatbox) { ... });``
|
||||
``converse.on('onChatBoxToggled', function (chatbox) { ... });``
|
||||
|
||||
Triggered when a chat box has been closed.
|
||||
Triggered when a chat box has been minimized or maximized.
|
||||
|
||||
* **onStatusChanged**
|
||||
|
||||
@ -967,9 +968,18 @@ Default = ``false``
|
||||
|
||||
If set to true, debugging output will be logged to the browser console.
|
||||
|
||||
enable_message_carbons
|
||||
----------------------
|
||||
|
||||
Default = ``false``
|
||||
|
||||
Support for `XEP-0280: Message Carbons <https://xmpp.org/extensions/xep-0280.html>`_
|
||||
|
||||
expose_rid_and_sid
|
||||
------------------
|
||||
|
||||
Default = ``false``
|
||||
|
||||
Allow the prebind tokens, RID (request ID) and SID (session ID), to be exposed
|
||||
globally via the API. This allows other scripts served on the same page to use
|
||||
these values.
|
||||
@ -977,6 +987,19 @@ these values.
|
||||
*Beware*: a malicious script could use these tokens to assume your identity
|
||||
and inject fake chat messages.
|
||||
|
||||
forward_messages
|
||||
----------------
|
||||
|
||||
Default = ``false``
|
||||
|
||||
If set to ``true``, sent messages will also be forwarded to other connected
|
||||
XMPP resources (e.g. chat clients) of the same user.
|
||||
|
||||
This is useful for example if converse.js is running in multiple tabs of the
|
||||
browser and you want sent messages to appear in all of them.
|
||||
|
||||
See also `XEP 0297: Stanza Forwarding <http://www.xmpp.org/extensions/xep-0297.html>`_
|
||||
|
||||
fullname
|
||||
--------
|
||||
|
||||
|
@ -7,8 +7,8 @@
|
||||
<meta name="description" content="Converse.js: A chat client for your website" />
|
||||
<link rel="stylesheet" type="text/css" media="screen" href="stylesheets/stylesheet.css">
|
||||
<link rel="stylesheet" type="text/css" media="screen" href="converse.css">
|
||||
<!--<script data-main="main" src="components/requirejs/require.js"></script>-->
|
||||
<script src="builds/converse.min.js"></script>
|
||||
<script data-main="main" src="components/requirejs/require.js"></script>
|
||||
<!-- <script src="builds/converse.min.js"></script> -->
|
||||
<title>Converse.js</title>
|
||||
</head>
|
||||
|
||||
@ -149,8 +149,7 @@
|
||||
</ul>
|
||||
|
||||
<h2>Licence</h2>
|
||||
<p><strong>Converse.js</strong> is released under both the <a href="http://opensource.org/licenses/mit-license.php" target="_blank">MIT</a>
|
||||
and <a href="http://opensource.org/licenses/GPL-2.0" target="_blank">GPL</a> licenses.</p>
|
||||
<p><strong>Converse.js</strong> is released under the <a href="https://www.mozilla.org/MPL/2.0/index.txt" target="_blank">Mozilla Public License (MPL)</a>.
|
||||
|
||||
<h2>Tips</h2>
|
||||
<p><strong>Bitcoin address:</strong> 16FsPqE9DhFTryxrUenpsGX4LJ1TPu8GqS</p>
|
||||
|
30
main.js
30
main.js
@ -1,11 +1,15 @@
|
||||
require.config({
|
||||
config = {
|
||||
paths: {
|
||||
"jquery": "components/jquery/jquery",
|
||||
"locales": "locale/locales",
|
||||
"jquery": "components/jquery/dist/jquery",
|
||||
"jquery.tinysort": "components/tinysort/src/jquery.tinysort",
|
||||
"jquery.browser": "components/jquery.browser/dist/jquery.browser",
|
||||
"locales": "locale/locales",
|
||||
"underscore": "components/underscore/underscore",
|
||||
"backbone": "components/backbone/backbone",
|
||||
"backbone.localStorage": "components/backbone.localStorage/backbone.localStorage",
|
||||
"text": 'components/requirejs-text/text',
|
||||
"tpl": 'components/requirejs-tpl-jcbrand/tpl',
|
||||
"converse-templates": "src/templates",
|
||||
"strophe": "components/strophe/strophe",
|
||||
"strophe.muc": "components/strophe.muc/index",
|
||||
"strophe.roster": "components/strophe.roster/index",
|
||||
@ -26,10 +30,19 @@ require.config({
|
||||
"crypto.mode-ctr": "components/otr/vendor/cryptojs/mode-ctr",
|
||||
"crypto": "src/crypto",
|
||||
"eventemitter": "components/otr/build/dep/eventemitter",
|
||||
"moment": "components/momentjs/moment",
|
||||
"otr": "components/otr/build/otr",
|
||||
"converse-dependencies": "src/deps-full"
|
||||
},
|
||||
|
||||
tpl: {
|
||||
// Use Mustache style syntax for variable interpolation
|
||||
templateSettings: {
|
||||
evaluate : /\{\[([\s\S]+?)\]\}/g,
|
||||
interpolate : /\{\{([\s\S]+?)\}\}/g
|
||||
}
|
||||
},
|
||||
|
||||
// define module dependencies for modules not using define
|
||||
shim: {
|
||||
'backbone': {
|
||||
@ -61,8 +74,11 @@ require.config({
|
||||
'strophe.roster': { deps: ['strophe'] },
|
||||
'strophe.vcard': { deps: ['strophe'] }
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
require(["jquery", "converse"], function(require, $, converse) {
|
||||
window.converse = converse;
|
||||
});
|
||||
if (typeof(require) !== 'undefined') {
|
||||
require.config(config);
|
||||
require(["jquery", "converse"], function(require, $, converse) {
|
||||
window.converse = converse;
|
||||
});
|
||||
}
|
||||
|
@ -1,15 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset='utf-8' />
|
||||
<meta http-equiv="X-UA-Compatible" content="chrome=1" />
|
||||
<meta name="description" content="Converse.js: Open Source Browser-Based Instant Messaging" />
|
||||
<link rel="stylesheet" type="text/css" media="screen" href="stylesheets/stylesheet.css">
|
||||
<link rel="stylesheet" type="text/css" media="screen" href="converse.css">
|
||||
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
|
||||
<title>Converse.js Mockup</title>
|
||||
<title id="pageTitle">Converse.js: Mockup</title>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta name="description" content="Converse.js: Chat Client for Websites" />
|
||||
<link type="text/css" rel="stylesheet" href="../stylesheets/stylesheet.css">
|
||||
<link type="text/css" rel="stylesheet" href="../converse.css">
|
||||
<script src="../components/jquery/jquery.min.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- HEADER -->
|
||||
<div id="header_wrap" class="outer">
|
||||
@ -19,16 +18,21 @@
|
||||
</header>
|
||||
</div>
|
||||
|
||||
<div id="conversejs" style="width: 100%;">
|
||||
<div id="conversejs">
|
||||
<a id="toggle-controlbox" href="#" class="chat toggle-online-users">
|
||||
<span class="conn-feedback">Toggle Chat</span>
|
||||
<span style="display: none" id="online-count">(0)</span>
|
||||
</a>
|
||||
|
||||
<div id="controlbox" class="chatbox" style="opacity: 1; display: inline;">
|
||||
<div class="chat-head oc-chat-head">
|
||||
<ul id="controlbox-tabs">
|
||||
<li><a class="current" href="#login">Sign in</a></li>
|
||||
</ul>
|
||||
<a class="close-chatbox-button icon-close"></a>
|
||||
<a class="minimize-chatbox-button icon-minus"></a>
|
||||
</div>
|
||||
<div class="controlbox-panes">
|
||||
<div class="box-flyout">
|
||||
<div class="dragresize dragresize-tm"></div>
|
||||
<div class="chat-head controlbox-head">
|
||||
<ul id="controlbox-tabs">
|
||||
<li><a class="current" href="#login">Sign in</a></li>
|
||||
</ul>
|
||||
<a class="close-chatbox-button icon-close"></a>
|
||||
</div>
|
||||
<div id="login-dialog">
|
||||
<form id="converse-login">
|
||||
<label>XMPP/Jabber Username:</label><input type="text" id="jid">
|
||||
@ -40,16 +44,16 @@
|
||||
</div>
|
||||
|
||||
<div id="controlbox" class="chatbox" style="opacity: 1; display: inline;">
|
||||
<div class="chat-head oc-chat-head">
|
||||
<ul id="controlbox-tabs">
|
||||
<li><a class="s current" href="#users">Contacts</a></li>
|
||||
<li><a class="s" href="#chatrooms">Rooms</a></li>
|
||||
</ul>
|
||||
<a class="close-chatbox-button icon-close"></a>
|
||||
<a class="minimize-chatbox-button icon-minus"></a>
|
||||
</div>
|
||||
<div class="controlbox-panes">
|
||||
<div id="users" class="oc-chat-content" style="display: block;">
|
||||
<div class="box-flyout">
|
||||
<div class="dragresize dragresize-tm"></div>
|
||||
<div class="chat-head controlbox-head">
|
||||
<ul id="controlbox-tabs">
|
||||
<li><a class="s current" href="#users">Contacts</a></li>
|
||||
<li><a class="s" href="#chatrooms">Rooms</a></li>
|
||||
</ul>
|
||||
<a class="close-chatbox-button icon-close"></a>
|
||||
</div>
|
||||
<div id="users" class="controlbox-pane" style="display: block;">
|
||||
<form class="set-xmpp-status" action="" method="post">
|
||||
<span id="xmpp-status-holder">
|
||||
<dl id="target" class="dropdown">
|
||||
@ -157,152 +161,83 @@
|
||||
</dl>
|
||||
</div>
|
||||
<div id="chatrooms" style="display: none;">
|
||||
<form class="add-chatroom" action="" method="post">
|
||||
<input type="text" name="chatroom" class="new-chatroom-name" placeholder="Room name">
|
||||
<input type="text" name="nick" class="new-chatroom-nick" placeholder="Nickname">
|
||||
<input type="text" name="server" class="new-chatroom-server" placeholder="Server">
|
||||
<input type="submit" name="join" value="Join">
|
||||
<input type="button" name="show" id="show-rooms" value="Show rooms" style="display: inline-block;">
|
||||
</form>
|
||||
<dl id="available-chatrooms">
|
||||
<dt>Rooms on conference.opkode.im</dt>
|
||||
<dd class="available-chatroom">
|
||||
<a class="open-room"
|
||||
data-room-jid="converse.js@conference.opkode.im"
|
||||
title="Click to open this room" href="#">Special chatroom with a long name (2)</a>
|
||||
<a class="room-info icon-room-info"
|
||||
data-room-jid="converse.js@conference.opkode.im"
|
||||
title="Show more information on this room" href="#"> </a>
|
||||
<div class="room-info">
|
||||
<p class="room-info"><strong>Description:</strong></p>
|
||||
<p class="room-info"><strong>Occupants:</strong> 2</p>
|
||||
<p class="room-info"><strong>Features:</strong> </p>
|
||||
<ul>
|
||||
<li class="room-info">Moderated</li><li class="room-info">Open room</li>
|
||||
<li class="room-info">Permanent room</li><li class="room-info">Public</li>
|
||||
<li class="room-info">Semi-anonymous</li>
|
||||
<li class="room-info">Requires authentication <span class="icon-lock"></span></li>
|
||||
<p></p>
|
||||
</ul>
|
||||
</div>
|
||||
</dd>
|
||||
</dl>
|
||||
<form class="add-chatroom" action="" method="post">
|
||||
<input type="text" name="chatroom" class="new-chatroom-name" placeholder="Room name">
|
||||
<input type="text" name="nick" class="new-chatroom-nick" placeholder="Nickname">
|
||||
<input type="text" name="server" class="new-chatroom-server" placeholder="Server">
|
||||
<input type="submit" name="join" value="Join">
|
||||
<input type="button" name="show" id="show-rooms" value="Show rooms" style="display: inline-block;">
|
||||
</form>
|
||||
<dl id="available-chatrooms">
|
||||
<dt>Rooms on conference.opkode.im</dt>
|
||||
<dd class="available-chatroom">
|
||||
<a class="open-room"
|
||||
data-room-jid="converse.js@conference.opkode.im"
|
||||
title="Click to open this room" href="#">Special chatroom with a long name (2)</a>
|
||||
<a class="room-info icon-room-info"
|
||||
data-room-jid="converse.js@conference.opkode.im"
|
||||
title="Show more information on this room" href="#"> </a>
|
||||
<div class="room-info">
|
||||
<p class="room-info"><strong>Description:</strong></p>
|
||||
<p class="room-info"><strong>Occupants:</strong> 2</p>
|
||||
<p class="room-info"><strong>Features:</strong> </p>
|
||||
<ul>
|
||||
<li class="room-info">Moderated</li><li class="room-info">Open room</li>
|
||||
<li class="room-info">Permanent room</li><li class="room-info">Public</li>
|
||||
<li class="room-info">Semi-anonymous</li>
|
||||
<li class="room-info">Requires authentication <span class="icon-lock"></span></li>
|
||||
<p></p>
|
||||
</ul>
|
||||
</div>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="chatbox" id="37c0c87392010303765fe36b05c0967d62c6b70f" style="opacity: 1; display: inline;">
|
||||
<div class="chat-head chat-head-chatbox">
|
||||
<a class="close-chatbox-button icon-close"></a>
|
||||
<a class="minimize-chatbox-button icon-minus"></a>
|
||||
|
||||
<a href="http://opkode.com" target="_blank" class="user">
|
||||
<div class="chatbox" id="37c0c87392010303765fe36b05c0967d62c6b70f">
|
||||
<div class="box-flyout">
|
||||
<div class="dragresize dragresize-tm"></div>
|
||||
<div class="chat-head chat-head-chatbox">
|
||||
<a class="close-chatbox-button icon-close"></a>
|
||||
<a class="toggle-chatbox-button icon-minus"></a>
|
||||
<canvas height="33px" width="33px" class="avatar" style="background-color: black"></canvas>
|
||||
<div class="chat-title"> JC Brand </div>
|
||||
</a>
|
||||
<p class="user-custom-message" title="10000ft in the air">10000ft in the air</p>
|
||||
<p></p>
|
||||
</div>
|
||||
<div class="chat-content">
|
||||
<div class="chat-info"><strong>/help</strong>:This is an info message</div>
|
||||
<div class="chat-error">This is an error message</div>
|
||||
<div class="chat-message">
|
||||
<span class="chat-message-me">09:35 me: </span>
|
||||
<span class="chat-message-content">
|
||||
Hello world
|
||||
<span class="icon-smiley"></span>
|
||||
</span>
|
||||
<div class="chat-title">
|
||||
<a href="http://opkode.com" target="_blank" class="user">
|
||||
JC Brand
|
||||
</a>
|
||||
</div>
|
||||
<p class="user-custom-message" title="10000ft in the air">10000ft in the air</p>
|
||||
</div>
|
||||
<div class="chat-message ">
|
||||
<span class="chat-message-them">19:25 Benedict-John: </span>
|
||||
<span class="chat-message-content">Dagsê</span>
|
||||
</div>
|
||||
<div class="chat-message">
|
||||
<span class="chat-message-me">19:39 me: </span>
|
||||
<span class="chat-message-content">This is a relatively long message to check that wrapping works as expected.</span>
|
||||
</div>
|
||||
<div class="chat-message">
|
||||
<span class="chat-message-me">19:42 me: </span>
|
||||
<span class="chat-message-content">Supercalifragilisticexpialidociousstillnotlongenough</span>
|
||||
</div>
|
||||
<div class="chat-event">JC Brand is busy</div>
|
||||
<div class="chat-message ">
|
||||
<span class="chat-message-me">19:43 me: </span>
|
||||
<span class="chat-message-content">Another message to check that scrolling works.</span>
|
||||
</div>
|
||||
</div>
|
||||
<form class="sendXMPPMessage" action="" method="post">
|
||||
<ul class="chat-toolbar no-text-select">
|
||||
<li class="toggle-smiley icon-happy" title="Insert a smilery">
|
||||
<ul>
|
||||
<li><a class="icon-smiley" href="#" data-emoticon=":)"></a></li>
|
||||
<li><a class="icon-wink" href="#" data-emoticon=";)"></a></li>
|
||||
<li><a class="icon-grin" href="#" data-emoticon=":D"></a></li>
|
||||
<li><a class="icon-tongue" href="#" data-emoticon=":P"></a></li>
|
||||
<li><a class="icon-cool" href="#" data-emoticon="8)"></a></li>
|
||||
<li><a class="icon-evil" href="#" data-emoticon=">:)"></a></li>
|
||||
<li><a class="icon-confused" href="#" data-emoticon=":S"></a></li>
|
||||
<li><a class="icon-wondering" href="#" data-emoticon=":\"></a></li>
|
||||
<li><a class="icon-angry" href="#" data-emoticon=">:("></a></li>
|
||||
<li><a class="icon-sad" href="#" data-emoticon=":("></a></li>
|
||||
<li><a class="icon-shocked" href="#" data-emoticon=":O"></a></li>
|
||||
<li><a class="icon-thumbs-up" href="#" data-emoticon="(^.^)b"></a></li>
|
||||
<li><a class="icon-heart" href="#" data-emoticon="<3"></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toggle-otr unencrypted" title="Turn on 'off-the-record' chat encryption">
|
||||
<span class="chat-toolbar-text">unencrypted</span>
|
||||
<span class="icon-unlocked"></span>
|
||||
<ul>
|
||||
<li><a href="#">Start private conversation</a></li>
|
||||
<li><a href="#">End private conversation</a></li>
|
||||
<li><a href="#">Authenticate buddy</a></li>
|
||||
<li><a href="http://www.cypherpunks.ca/otr/help/3.2.0/levels.php" target="_blank">What's this?</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<textarea type="text" class="chat-textarea" placeholder="Personal message"></textarea>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="chatroom" id="4a77380f1cd9d392627b0e1469688f9ca44e9392" style="opacity: 1; display: inline;">
|
||||
<div class="chat-head chat-head-chatroom">
|
||||
<a class="close-chatbox-button icon-close"></a>
|
||||
<a class="minimize-chatbox-button icon-minus"></a>
|
||||
<a class="configure-chatroom-button icon-wrench" style=""></a>
|
||||
|
||||
<div class="chat-title"> Chatroom </div>
|
||||
<p class="chatroom-topic"></p>
|
||||
<p></p>
|
||||
</div>
|
||||
<div class="chat-body">
|
||||
<div class="chat-area">
|
||||
<div class="chat-body">
|
||||
<div class="chat-content">
|
||||
<time class="chat-date" datetime="2013-06-04T00:00:00.000Z">Tue Jun 04 2013</time>
|
||||
<div class="chat-message ">
|
||||
<span class="chat-message-room">18:50 luke: </span>
|
||||
<span class="chat-message-content">leia: hi :)</span>
|
||||
<div class="chat-info"><strong>/help</strong>:This is an info message</div>
|
||||
<div class="chat-error">This is an error message</div>
|
||||
<div class="chat-message">
|
||||
<span class="chat-message-me">09:35 me: </span>
|
||||
<span class="chat-message-content">
|
||||
Hello world
|
||||
<span class="icon-smiley"></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="chat-message ">
|
||||
<span class="chat-message-room">19:40 leia: </span>
|
||||
<span class="chat-message-content">
|
||||
I'll be gone for a while, will be back in about an hour</span>
|
||||
<span class="chat-message-them">19:25 Benedict-John: </span>
|
||||
<span class="chat-message-content">Dagsê</span>
|
||||
</div>
|
||||
<div class="chat-message ">
|
||||
<span class="chat-message-room">19:40 Obi-wan Kenobi, Jedi Master: </span>
|
||||
<span class="chat-message-content">
|
||||
I'll be gone for a while, will be back in about an hour</span>
|
||||
<div class="chat-message">
|
||||
<span class="chat-message-me">19:39 me: </span>
|
||||
<span class="chat-message-content">This is a relatively long message to check that wrapping works as expected.</span>
|
||||
</div>
|
||||
<div class="chat-message">
|
||||
<span class="chat-message-me">19:42 me: </span>
|
||||
<span class="chat-message-content">Supercalifragilisticexpialidociousstillnotlongenough</span>
|
||||
</div>
|
||||
<div class="chat-event">JC Brand is busy</div>
|
||||
<div class="chat-message ">
|
||||
<span class="chat-message-room">19:43 Obi-wan Kenobi, Jedi Master: </span>
|
||||
<span class="chat-message-me">19:43 me: </span>
|
||||
<span class="chat-message-content">Another message to check that scrolling works.</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form class="sendXMPPMessage" action="" method="post">
|
||||
<ul class="chat-toolbar no-text-select">
|
||||
<li class="toggle-smiley icon-happy" title="Insert a smilery">
|
||||
@ -322,47 +257,120 @@
|
||||
<li><a class="icon-heart" href="#" data-emoticon="<3"></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toggle-otr unencrypted" title="Turn on 'off-the-record' chat encryption">
|
||||
<span class="chat-toolbar-text">unencrypted</span>
|
||||
<span class="icon-unlocked"></span>
|
||||
<ul>
|
||||
<li><a href="#">Start private conversation</a></li>
|
||||
<li><a href="#">End private conversation</a></li>
|
||||
<li><a href="#">Authenticate buddy</a></li>
|
||||
<li><a href="http://www.cypherpunks.ca/otr/help/3.2.0/levels.php" target="_blank">What's this?</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<textarea type="text" class="chat-textarea" placeholder="Message"></textarea>
|
||||
</form>
|
||||
</div>
|
||||
<div class="participants">
|
||||
<ul class="participant-list">
|
||||
<li class="participant" title="This user can send messages in this room">Obi-wan Kenobi, Jedi Master</li>
|
||||
<li class="participant" title="This user can send messages in this room">jabber the hut</li>
|
||||
<li class="participant" title="This user can send messages in this room">leia</li>
|
||||
<li class="moderator" title="This user is a moderator">luke</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="chatroom" id="6d8627960a0cb066d9216742f3edccc3dbbf85a9" style="opacity: 1; display: inline;">
|
||||
<div class="chat-head chat-head-chatroom">
|
||||
<a class="close-chatbox-button icon-close"></a>
|
||||
<a class="minimize-chatbox-button icon-minus"></a>
|
||||
<a class="configure-chatroom-button" style="display:none"> </a>
|
||||
<div class="chat-title"> Restricted Chatroom</div>
|
||||
<p class="chatroom-topic"></p>
|
||||
<p></p>
|
||||
</div>
|
||||
<div class="chat-body">
|
||||
<div class="chatroom-form-container">
|
||||
<form class="chatroom-form">
|
||||
<legend>This chatroom requires a password</legend>
|
||||
<label>Password: <input type="password" name="password"></label>
|
||||
<textarea type="text" class="chat-textarea" placeholder="Personal message"></textarea>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="toggle-controlbox">
|
||||
<a href="#" class="chat toggle-online-users">
|
||||
<strong class="conn-feedback">Toggle chat</strong> <strong style="display: none" id="online-count">(0)</strong>
|
||||
</a>
|
||||
<div class="chatroom" id="4a77380f1cd9d392627b0e1469688f9ca44e9392">
|
||||
<div class="box-flyout">
|
||||
<div class="dragresize dragresize-tm"></div>
|
||||
<div class="chat-head chat-head-chatroom">
|
||||
<a class="close-chatbox-button icon-close"></a>
|
||||
<a class="toggle-chatbox-button icon-minus"></a>
|
||||
<a class="configure-chatroom-button icon-wrench" style=""></a>
|
||||
|
||||
<div class="chat-title"> Chatroom </div>
|
||||
<p class="chatroom-topic">May the force be with you</p>
|
||||
</div>
|
||||
<div class="chat-body">
|
||||
<div class="chat-area">
|
||||
<div class="chat-content">
|
||||
<time class="chat-date" datetime="2013-06-04T00:00:00.000Z">Tue Jun 04 2013</time>
|
||||
<div class="chat-message ">
|
||||
<span class="chat-message-room">18:50 luke: </span>
|
||||
<span class="chat-message-content">leia: hi :)</span>
|
||||
</div>
|
||||
<div class="chat-message ">
|
||||
<span class="chat-message-room">19:40 leia: </span>
|
||||
<span class="chat-message-content">
|
||||
I'll be gone for a while, will be back in about an hour</span>
|
||||
</div>
|
||||
<div class="chat-message ">
|
||||
<span class="chat-message-room">19:40 Obi-wan Kenobi, Jedi Master: </span>
|
||||
<span class="chat-message-content">
|
||||
I'll be gone for a while, will be back in about an hour</span>
|
||||
</div>
|
||||
<div class="chat-message">
|
||||
<span class="chat-message-me">19:42 me: </span>
|
||||
<span class="chat-message-content">Supercalifragilisticexpialidociousstillnotlongenough</span>
|
||||
</div>
|
||||
<div class="chat-message ">
|
||||
<span class="chat-message-room">19:43 Obi-wan Kenobi, Jedi Master: </span>
|
||||
<span class="chat-message-content">Another message to check that scrolling works.</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form class="sendXMPPMessage" action="" method="post">
|
||||
<ul class="chat-toolbar no-text-select">
|
||||
<li class="toggle-smiley icon-happy" title="Insert a smilery">
|
||||
<ul>
|
||||
<li><a class="icon-smiley" href="#" data-emoticon=":)"></a></li>
|
||||
<li><a class="icon-wink" href="#" data-emoticon=";)"></a></li>
|
||||
<li><a class="icon-grin" href="#" data-emoticon=":D"></a></li>
|
||||
<li><a class="icon-tongue" href="#" data-emoticon=":P"></a></li>
|
||||
<li><a class="icon-cool" href="#" data-emoticon="8)"></a></li>
|
||||
<li><a class="icon-evil" href="#" data-emoticon=">:)"></a></li>
|
||||
<li><a class="icon-confused" href="#" data-emoticon=":S"></a></li>
|
||||
<li><a class="icon-wondering" href="#" data-emoticon=":\"></a></li>
|
||||
<li><a class="icon-angry" href="#" data-emoticon=">:("></a></li>
|
||||
<li><a class="icon-sad" href="#" data-emoticon=":("></a></li>
|
||||
<li><a class="icon-shocked" href="#" data-emoticon=":O"></a></li>
|
||||
<li><a class="icon-thumbs-up" href="#" data-emoticon="(^.^)b"></a></li>
|
||||
<li><a class="icon-heart" href="#" data-emoticon="<3"></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<textarea type="text" class="chat-textarea" placeholder="Message"></textarea>
|
||||
</form>
|
||||
</div>
|
||||
<div class="participants">
|
||||
<ul class="participant-list">
|
||||
<li class="participant" title="This user can send messages in this room">Obi-wan Kenobi, Jedi Master</li>
|
||||
<li class="participant" title="This user can send messages in this room">jabber the hut</li>
|
||||
<li class="participant" title="This user can send messages in this room">leia</li>
|
||||
<li class="moderator" title="This user is a moderator">luke</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="chatroom" id="6d8627960a0cb066d9216742f3edccc3dbbf85a9">
|
||||
<div class="box-flyout">
|
||||
<div class="dragresize dragresize-tm"></div>
|
||||
<div class="chat-head chat-head-chatroom">
|
||||
<a class="close-chatbox-button icon-close"></a>
|
||||
<a class="toggle-chatbox-button icon-minus"></a>
|
||||
<a class="configure-chatroom-button" style="display:none"> </a>
|
||||
<div class="chat-title"> Restricted Chatroom</div>
|
||||
<p class="chatroom-topic"></p>
|
||||
<p></p>
|
||||
</div>
|
||||
<div class="chat-body">
|
||||
<div class="chatroom-form-container">
|
||||
<form class="chatroom-form">
|
||||
<!-- TODO: Make this a long form that scrolls -->
|
||||
<legend>This chatroom requires a password</legend>
|
||||
<label>Password: <input type="password" name="password"></label>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
@ -416,10 +424,25 @@ $(document).ready(function () {
|
||||
}
|
||||
|
||||
$(function() {
|
||||
$('.close-chatbox-button').click(function(ev) {
|
||||
var $grandparent = $(ev.target).parent().parent().parent();
|
||||
$grandparent.hide(300, function () {
|
||||
// Webkit fix
|
||||
document.getElementById('conversejs').style.display = 'none';
|
||||
document.getElementById('conversejs').offsetHeight; // no need to store this anywhere, the reference is enough
|
||||
document.getElementById('conversejs').style.display = 'block';
|
||||
});
|
||||
});
|
||||
|
||||
$('.minimize-chatbox-button').click(function(ev) {
|
||||
$(ev.target).parent().parent().find('div.chat-content').toggle();
|
||||
$(ev.target).parent().parent().find('form.sendXMPPMessage').toggle();
|
||||
$('.toggle-chatbox-button').click(function(ev) {
|
||||
var $grandparent = $(ev.target).parent().parent().parent();
|
||||
$grandparent.find('.chat-body').slideToggle(300);
|
||||
var flyout = $grandparent.find('.box-flyout');
|
||||
if (flyout.hasClass('minimized')) {
|
||||
flyout.removeClass('minimized');
|
||||
} else {
|
||||
flyout.addClass('minimized');
|
||||
}
|
||||
});
|
||||
|
||||
// Clickable Dropdown
|
274
mockup/minimized.html
Normal file
274
mockup/minimized.html
Normal file
@ -0,0 +1,274 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title id="pageTitle">Converse.js: Mockup of minimized chats</title>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta name="description" content="Converse.js: Chat Client for Websites" />
|
||||
<link type="text/css" rel="stylesheet" href="../stylesheets/stylesheet.css">
|
||||
<link type="text/css" rel="stylesheet" href="../converse.css">
|
||||
<script src="../components/jquery/jquery.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- HEADER -->
|
||||
<div id="header_wrap" class="outer">
|
||||
<header class="inner">
|
||||
<h1 id="project_title"><a href="http://conversejs.org">Converse.js</a></h1>
|
||||
<h2 id="project_tagline">Static Mockup</h2>
|
||||
</header>
|
||||
</div>
|
||||
|
||||
<div id="conversejs">
|
||||
|
||||
<div class="chatbox" id="37c0c87392010303765fe36b05c0967d62c6b70f">
|
||||
<div class="box-flyout minimized">
|
||||
<div class="dragresize dragresize-tm"></div>
|
||||
<div class="chat-head chat-head-chatbox">
|
||||
<div class="chat-head-message-count" style="display:block">3</div>
|
||||
<a class="close-chatbox-button icon-close"></a>
|
||||
<a class="toggle-chatbox-button icon-minus"></a>
|
||||
<canvas height="33px" width="33px" class="avatar" style="background-color: black"></canvas>
|
||||
<div class="chat-title">
|
||||
<a href="http://opkode.com" target="_blank" class="user">
|
||||
JC Brand
|
||||
</a>
|
||||
</div>
|
||||
<p class="user-custom-message" title="10000ft in the air">10000ft in the air</p>
|
||||
|
||||
</div>
|
||||
<div class="chat-body" style="display: none">
|
||||
<div class="chat-content">
|
||||
<div class="chat-info"><strong>/help</strong>:This is an info message</div>
|
||||
<div class="chat-error">This is an error message</div>
|
||||
<div class="chat-message">
|
||||
<span class="chat-message-me">09:35 me: </span>
|
||||
<span class="chat-message-content">
|
||||
Hello world
|
||||
<span class="icon-smiley"></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="chat-message ">
|
||||
<span class="chat-message-them">19:25 Benedict-John: </span>
|
||||
<span class="chat-message-content">Dagsê</span>
|
||||
</div>
|
||||
<div class="chat-message">
|
||||
<span class="chat-message-me">19:39 me: </span>
|
||||
<span class="chat-message-content">This is a relatively long message to check that wrapping works as expected.</span>
|
||||
</div>
|
||||
<div class="chat-message">
|
||||
<span class="chat-message-me">19:42 me: </span>
|
||||
<span class="chat-message-content">Supercalifragilisticexpialidociousstillnotlongenough</span>
|
||||
</div>
|
||||
<div class="chat-event">JC Brand is busy</div>
|
||||
<div class="chat-message ">
|
||||
<span class="chat-message-me">19:43 me: </span>
|
||||
<span class="chat-message-content">Another message to check that scrolling works.</span>
|
||||
</div>
|
||||
</div>
|
||||
<form class="sendXMPPMessage" action="" method="post">
|
||||
<ul class="chat-toolbar no-text-select">
|
||||
<li class="toggle-smiley icon-happy" title="Insert a smilery">
|
||||
<ul>
|
||||
<li><a class="icon-smiley" href="#" data-emoticon=":)"></a></li>
|
||||
<li><a class="icon-wink" href="#" data-emoticon=";)"></a></li>
|
||||
<li><a class="icon-grin" href="#" data-emoticon=":D"></a></li>
|
||||
<li><a class="icon-tongue" href="#" data-emoticon=":P"></a></li>
|
||||
<li><a class="icon-cool" href="#" data-emoticon="8)"></a></li>
|
||||
<li><a class="icon-evil" href="#" data-emoticon=">:)"></a></li>
|
||||
<li><a class="icon-confused" href="#" data-emoticon=":S"></a></li>
|
||||
<li><a class="icon-wondering" href="#" data-emoticon=":\"></a></li>
|
||||
<li><a class="icon-angry" href="#" data-emoticon=">:("></a></li>
|
||||
<li><a class="icon-sad" href="#" data-emoticon=":("></a></li>
|
||||
<li><a class="icon-shocked" href="#" data-emoticon=":O"></a></li>
|
||||
<li><a class="icon-thumbs-up" href="#" data-emoticon="(^.^)b"></a></li>
|
||||
<li><a class="icon-heart" href="#" data-emoticon="<3"></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toggle-otr unencrypted" title="Turn on 'off-the-record' chat encryption">
|
||||
<span class="chat-toolbar-text">unencrypted</span>
|
||||
<span class="icon-unlocked"></span>
|
||||
<ul>
|
||||
<li><a href="#">Start private conversation</a></li>
|
||||
<li><a href="#">End private conversation</a></li>
|
||||
<li><a href="#">Authenticate buddy</a></li>
|
||||
<li><a href="http://www.cypherpunks.ca/otr/help/3.2.0/levels.php" target="_blank">What's this?</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<textarea type="text" class="chat-textarea" placeholder="Personal message"></textarea>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="chatroom" id="4a77380f1cd9d392627b0e1469688f9ca44e9392">
|
||||
<div class="box-flyout minimized">
|
||||
<div class="dragresize dragresize-tm"></div>
|
||||
<div class="chat-head chat-head-chatroom">
|
||||
<div class="chat-head-message-count" style="display:block">42</div>
|
||||
<a class="close-chatbox-button icon-close"></a>
|
||||
<a class="toggle-chatbox-button icon-minus"></a>
|
||||
<a class="configure-chatroom-button icon-wrench" style=""></a>
|
||||
<div class="chat-title"> Chatroom </div>
|
||||
<p class="chatroom-topic">May the force be with you</p>
|
||||
</div>
|
||||
<div class="chat-body" style="display: none">
|
||||
<div class="chat-area">
|
||||
<div class="chat-content">
|
||||
<time class="chat-date" datetime="2013-06-04T00:00:00.000Z">Tue Jun 04 2013</time>
|
||||
<div class="chat-message ">
|
||||
<span class="chat-message-room">18:50 luke: </span>
|
||||
<span class="chat-message-content">leia: hi :)</span>
|
||||
</div>
|
||||
<div class="chat-message ">
|
||||
<span class="chat-message-room">19:40 leia: </span>
|
||||
<span class="chat-message-content">
|
||||
I'll be gone for a while, will be back in about an hour</span>
|
||||
</div>
|
||||
<div class="chat-message ">
|
||||
<span class="chat-message-room">19:40 Obi-wan Kenobi, Jedi Master: </span>
|
||||
<span class="chat-message-content">
|
||||
I'll be gone for a while, will be back in about an hour</span>
|
||||
</div>
|
||||
<div class="chat-message">
|
||||
<span class="chat-message-me">19:42 me: </span>
|
||||
<span class="chat-message-content">Supercalifragilisticexpialidociousstillnotlongenough</span>
|
||||
</div>
|
||||
<div class="chat-message ">
|
||||
<span class="chat-message-room">19:43 Obi-wan Kenobi, Jedi Master: </span>
|
||||
<span class="chat-message-content">Another message to check that scrolling works.</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form class="sendXMPPMessage" action="" method="post">
|
||||
<ul class="chat-toolbar no-text-select">
|
||||
<li class="toggle-smiley icon-happy" title="Insert a smilery">
|
||||
<ul>
|
||||
<li><a class="icon-smiley" href="#" data-emoticon=":)"></a></li>
|
||||
<li><a class="icon-wink" href="#" data-emoticon=";)"></a></li>
|
||||
<li><a class="icon-grin" href="#" data-emoticon=":D"></a></li>
|
||||
<li><a class="icon-tongue" href="#" data-emoticon=":P"></a></li>
|
||||
<li><a class="icon-cool" href="#" data-emoticon="8)"></a></li>
|
||||
<li><a class="icon-evil" href="#" data-emoticon=">:)"></a></li>
|
||||
<li><a class="icon-confused" href="#" data-emoticon=":S"></a></li>
|
||||
<li><a class="icon-wondering" href="#" data-emoticon=":\"></a></li>
|
||||
<li><a class="icon-angry" href="#" data-emoticon=">:("></a></li>
|
||||
<li><a class="icon-sad" href="#" data-emoticon=":("></a></li>
|
||||
<li><a class="icon-shocked" href="#" data-emoticon=":O"></a></li>
|
||||
<li><a class="icon-thumbs-up" href="#" data-emoticon="(^.^)b"></a></li>
|
||||
<li><a class="icon-heart" href="#" data-emoticon="<3"></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<textarea type="text" class="chat-textarea" placeholder="Message"></textarea>
|
||||
</form>
|
||||
</div>
|
||||
<div class="participants">
|
||||
<ul class="participant-list">
|
||||
<li class="participant" title="This user can send messages in this room">Obi-wan Kenobi, Jedi Master</li>
|
||||
<li class="participant" title="This user can send messages in this room">jabber the hut</li>
|
||||
<li class="participant" title="This user can send messages in this room">leia</li>
|
||||
<li class="moderator" title="This user is a moderator">luke</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
$('a[href=#chatrooms]').click(function (ev) {
|
||||
switchTab(ev);
|
||||
});
|
||||
$('a[href=#users]').click(function (ev) {
|
||||
switchTab(ev);
|
||||
});
|
||||
|
||||
$("a.choose-xmpp-status").click(function (ev) {
|
||||
ev.preventDefault();
|
||||
$(ev.target).parent().parent().siblings('dd').find('ul').toggle('fast');
|
||||
});
|
||||
|
||||
$("a.change-xmpp-status-message").click(function (ev) {
|
||||
ev.preventDefault();
|
||||
var form = ''+
|
||||
'<form id="set-custom-xmpp-status">' +
|
||||
'<input type="text" class="custom-xmpp-status"I am online"'+
|
||||
'placeholder="I am online"/>' +
|
||||
'<button type="submit">Save</button>' +
|
||||
'</form>';
|
||||
|
||||
$(ev.target).closest('.xmpp-status').replaceWith(form);
|
||||
$(ev.target).closest('.custom-xmpp-status').focus().focus();
|
||||
});
|
||||
|
||||
$('.toggle-xmpp-contact-form').click(function (ev) {
|
||||
ev.preventDefault();
|
||||
$(ev.target).parent().parent().find('.search-xmpp').toggle('fast', function () {
|
||||
if ($(this).is(':visible')) {
|
||||
$(this).find('input.username').focus();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var switchTab = function (ev) {
|
||||
ev.preventDefault();
|
||||
var $tab = $(ev.target),
|
||||
$sibling = $tab.parent().siblings('li').children('a'),
|
||||
$tab_panel = $($tab.attr('href')),
|
||||
$sibling_panel = $($sibling.attr('href'));
|
||||
|
||||
$sibling_panel.fadeOut('fast', function () {
|
||||
$sibling.removeClass('current');
|
||||
$tab.addClass('current');
|
||||
$tab_panel.fadeIn('fast', function () {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$(function() {
|
||||
$('.close-chatbox-button').click(function(ev) {
|
||||
var $grandparent = $(ev.target).parent().parent().parent();
|
||||
$grandparent.hide(300, function () {
|
||||
// Webkit fix
|
||||
document.getElementById('conversejs').style.display = 'none';
|
||||
document.getElementById('conversejs').offsetHeight; // no need to store this anywhere, the reference is enough
|
||||
document.getElementById('conversejs').style.display = 'block';
|
||||
});
|
||||
});
|
||||
|
||||
$('.toggle-chatbox-button').click(function(ev) {
|
||||
var $grandparent = $(ev.target).parent().parent().parent();
|
||||
$grandparent.find('.chat-body').slideToggle(300);
|
||||
var flyout = $grandparent.find('.box-flyout');
|
||||
if (flyout.hasClass('minimized')) {
|
||||
flyout.removeClass('minimized');
|
||||
} else {
|
||||
flyout.addClass('minimized');
|
||||
}
|
||||
});
|
||||
|
||||
// Clickable Dropdown
|
||||
$('.toggle-otr').click(function(e) {
|
||||
$('.toggle-otr ul').slideToggle(200);
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
$('.toggle-smiley').click(function(e) {
|
||||
$(e.target).find('ul').slideToggle(200);
|
||||
e.stopPropagation();
|
||||
});
|
||||
$(document).click(function() {
|
||||
if ($('.toggle-otr ul').is(':visible')) {
|
||||
$('.toggle-otr ul', this).slideUp(200);
|
||||
}
|
||||
if ($('.toggle-smiley ul').is(':visible')) {
|
||||
$('.toggle-smiley ul', this).slideUp(200);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
</html>
|
20
package.json
20
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "converse.js",
|
||||
"version": "0.7.4",
|
||||
"version": "0.8.0",
|
||||
"description": "Browser based XMPP instant messaging client",
|
||||
"main": "main.js",
|
||||
"directories": {
|
||||
@ -27,16 +27,16 @@
|
||||
"url": "https://github.com/jcbrand/converse.js/issues"
|
||||
},
|
||||
"devDependencies": {
|
||||
"grunt-cli": "~0.1.9",
|
||||
"grunt": "~0.4.1",
|
||||
"grunt-contrib-jshint": "~0.6.0",
|
||||
"phantomjs": "~1.9.1-0",
|
||||
"jasmine-reporters": "~0.2.1",
|
||||
"bower": "~1.0.0",
|
||||
"grunt-contrib-requirejs": "~0.4.1",
|
||||
"grunt-contrib-cssmin": "~0.6.1"
|
||||
"grunt-cli": "~0.1.13",
|
||||
"grunt": "~0.4.4",
|
||||
"grunt-contrib-jshint": "~0.10.0",
|
||||
"phantom-jasmine": "0.1.8",
|
||||
"phantomjs": "~1.9.7-1",
|
||||
"bower": "latest",
|
||||
"grunt-contrib-requirejs": "~0.4.3",
|
||||
"grunt-contrib-cssmin": "~0.9.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"requirejs": "~2.1.8"
|
||||
"requirejs": "~2.1.11"
|
||||
}
|
||||
}
|
||||
|
314
spec/chatbox.js
314
spec/chatbox.js
@ -10,13 +10,23 @@
|
||||
return describe("Chatboxes", $.proxy(function(mock, utils) {
|
||||
describe("A Chatbox", $.proxy(function () {
|
||||
beforeEach(function () {
|
||||
utils.closeAllChatBoxes();
|
||||
utils.removeControlBox();
|
||||
converse.roster.localStorage._clear();
|
||||
utils.initConverse();
|
||||
utils.createCurrentContacts();
|
||||
utils.openControlBox();
|
||||
utils.openContactsPanel();
|
||||
runs(function () {
|
||||
utils.closeAllChatBoxes();
|
||||
utils.removeControlBox();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {
|
||||
converse.roster.localStorage._clear();
|
||||
utils.initConverse();
|
||||
utils.createCurrentContacts();
|
||||
utils.openControlBox();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {
|
||||
utils.openContactsPanel();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {});
|
||||
});
|
||||
|
||||
it("is created when you click on a roster item", $.proxy(function () {
|
||||
@ -29,7 +39,7 @@
|
||||
for (i=0; i<online_contacts.length; i++) {
|
||||
$el = $(online_contacts[i]);
|
||||
jid = $el.text().replace(' ','.').toLowerCase() + '@localhost';
|
||||
view = this.rosterview.rosteritemviews[jid];
|
||||
view = this.rosterview.get(jid);
|
||||
spyOn(view, 'openChat').andCallThrough();
|
||||
view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
|
||||
$el.click();
|
||||
@ -40,63 +50,124 @@
|
||||
|
||||
it("can be saved to, and retrieved from, localStorage", $.proxy(function () {
|
||||
spyOn(converse, 'emit');
|
||||
utils.closeControlBox();
|
||||
expect(converse.emit).toHaveBeenCalledWith('onChatBoxClosed', jasmine.any(Object));
|
||||
|
||||
// First, we open 6 more chatboxes (controlbox is already open)
|
||||
utils.openChatBoxes(6);
|
||||
// We instantiate a new ChatBoxes collection, which by default
|
||||
// will be empty.
|
||||
var newchatboxes = new this.ChatBoxes();
|
||||
expect(newchatboxes.length).toEqual(0);
|
||||
// The chatboxes will then be fetched from localStorage inside the
|
||||
// onConnected method
|
||||
newchatboxes.onConnected();
|
||||
expect(newchatboxes.length).toEqual(6);
|
||||
// Check that the chatboxes items retrieved from localStorage
|
||||
// have the same attributes values as the original ones.
|
||||
attrs = ['id', 'box_id', 'visible'];
|
||||
for (i=0; i<attrs.length; i++) {
|
||||
new_attrs = _.pluck(_.pluck(newchatboxes.models, 'attributes'), attrs[i]);
|
||||
old_attrs = _.pluck(_.pluck(this.chatboxes.models, 'attributes'), attrs[i]);
|
||||
expect(_.isEqual(new_attrs, old_attrs)).toEqual(true);
|
||||
}
|
||||
this.rosterview.render();
|
||||
runs(function () {
|
||||
utils.openControlBox();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {
|
||||
utils.openChatBoxes(6);
|
||||
// We instantiate a new ChatBoxes collection, which by default
|
||||
// will be empty.
|
||||
var newchatboxes = new this.ChatBoxes();
|
||||
expect(newchatboxes.length).toEqual(0);
|
||||
// The chatboxes will then be fetched from localStorage inside the
|
||||
// onConnected method
|
||||
newchatboxes.onConnected();
|
||||
expect(newchatboxes.length).toEqual(7);
|
||||
// Check that the chatboxes items retrieved from localStorage
|
||||
// have the same attributes values as the original ones.
|
||||
attrs = ['id', 'box_id', 'visible'];
|
||||
for (i=0; i<attrs.length; i++) {
|
||||
new_attrs = _.pluck(_.pluck(newchatboxes.models, 'attributes'), attrs[i]);
|
||||
old_attrs = _.pluck(_.pluck(this.chatboxes.models, 'attributes'), attrs[i]);
|
||||
expect(_.isEqual(new_attrs, old_attrs)).toEqual(true);
|
||||
}
|
||||
this.rosterview.render();
|
||||
}.bind(converse));
|
||||
}, converse));
|
||||
|
||||
it("can be closed again by clicking a DOM element with class 'close-chatbox-button'", $.proxy(function () {
|
||||
it("can be closed by clicking a DOM element with class 'close-chatbox-button'", $.proxy(function () {
|
||||
var chatbox = utils.openChatBoxes(1)[0],
|
||||
controlview = this.chatboxviews.get('controlbox'), // The controlbox is currently open
|
||||
chatview = this.chatboxviews.get(chatbox.get('jid'));
|
||||
spyOn(chatview, 'closeChat').andCallThrough();
|
||||
spyOn(controlview, 'closeChat').andCallThrough();
|
||||
spyOn(converse, 'emit');
|
||||
var chatbox, view, $el,
|
||||
num_open_chats = this.chatboxes.length;
|
||||
for (i=0; i<num_open_chats; i++) {
|
||||
chatbox = this.chatboxes.models[0];
|
||||
view = this.chatboxesview.views[chatbox.get('id')];
|
||||
spyOn(view, 'closeChat').andCallThrough();
|
||||
view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
|
||||
view.$el.find('.close-chatbox-button').click();
|
||||
expect(view.closeChat).toHaveBeenCalled();
|
||||
|
||||
// We need to rebind all events otherwise our spy won't be called
|
||||
controlview.delegateEvents();
|
||||
chatview.delegateEvents();
|
||||
|
||||
runs(function () {
|
||||
controlview.$el.find('.close-chatbox-button').click();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {
|
||||
expect(controlview.closeChat).toHaveBeenCalled();
|
||||
expect(converse.emit).toHaveBeenCalledWith('onChatBoxClosed', jasmine.any(Object));
|
||||
}
|
||||
expect(converse.emit.callCount, 1);
|
||||
chatview.$el.find('.close-chatbox-button').click();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {
|
||||
expect(chatview.closeChat).toHaveBeenCalled();
|
||||
expect(converse.emit).toHaveBeenCalledWith('onChatBoxClosed', jasmine.any(Object));
|
||||
expect(converse.emit.callCount, 2);
|
||||
});
|
||||
}, converse));
|
||||
|
||||
it("can be toggled by clicking a DOM element with class 'toggle-chatbox-button'", function () {
|
||||
var chatbox = utils.openChatBoxes(1)[0],
|
||||
chatview = this.chatboxviews.get(chatbox.get('jid'));
|
||||
spyOn(chatview, 'toggleChatBox').andCallThrough();
|
||||
spyOn(converse, 'emit');
|
||||
// We need to rebind all events otherwise our spy won't be called
|
||||
chatview.delegateEvents();
|
||||
|
||||
runs(function () {
|
||||
chatview.$el.find('.toggle-chatbox-button').click();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {
|
||||
expect(chatview.toggleChatBox).toHaveBeenCalled();
|
||||
expect(converse.emit).toHaveBeenCalledWith('onChatBoxToggled', jasmine.any(Object));
|
||||
expect(converse.emit.callCount, 2);
|
||||
expect(chatview.$el.find('.chat-body').is(':visible')).toBeFalsy();
|
||||
expect(chatview.$el.find('.toggle-chatbox-button').hasClass('icon-minus')).toBeFalsy();
|
||||
expect(chatview.$el.find('.toggle-chatbox-button').hasClass('icon-plus')).toBeTruthy();
|
||||
expect(chatview.model.get('minimized')).toBeTruthy();
|
||||
chatview.$el.find('.toggle-chatbox-button').click();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {
|
||||
expect(chatview.toggleChatBox).toHaveBeenCalled();
|
||||
expect(converse.emit).toHaveBeenCalledWith('onChatBoxToggled', jasmine.any(Object));
|
||||
expect(chatview.$el.find('.chat-body').is(':visible')).toBeTruthy();
|
||||
expect(chatview.$el.find('.toggle-chatbox-button').hasClass('icon-minus')).toBeTruthy();
|
||||
expect(chatview.$el.find('.toggle-chatbox-button').hasClass('icon-plus')).toBeFalsy();
|
||||
expect(chatview.model.get('minimized')).toBeFalsy();
|
||||
expect(converse.emit.callCount, 3);
|
||||
});
|
||||
}.bind(converse));
|
||||
|
||||
it("will be removed from localStorage when closed", $.proxy(function () {
|
||||
spyOn(converse, 'emit');
|
||||
this.chatboxes.localStorage._clear();
|
||||
utils.closeControlBox();
|
||||
expect(converse.chatboxes.length).toEqual(0);
|
||||
utils.openChatBoxes(6);
|
||||
expect(converse.chatboxes.length).toEqual(6);
|
||||
expect(converse.emit).toHaveBeenCalledWith('onChatBoxOpened', jasmine.any(Object));
|
||||
utils.closeAllChatBoxes();
|
||||
expect(converse.chatboxes.length).toEqual(0);
|
||||
expect(converse.emit).toHaveBeenCalledWith('onChatBoxClosed', jasmine.any(Object));
|
||||
var newchatboxes = new this.ChatBoxes();
|
||||
expect(newchatboxes.length).toEqual(0);
|
||||
// onConnected will fetch chatboxes in localStorage, but
|
||||
// because there aren't any open chatboxes, there won't be any
|
||||
// in localStorage either.
|
||||
newchatboxes.onConnected();
|
||||
expect(newchatboxes.length).toEqual(0);
|
||||
runs(function () {
|
||||
utils.closeControlBox();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {
|
||||
expect(converse.emit).toHaveBeenCalledWith('onChatBoxClosed', jasmine.any(Object));
|
||||
expect(converse.chatboxes.length).toEqual(0);
|
||||
utils.openChatBoxes(6);
|
||||
expect(converse.chatboxes.length).toEqual(6);
|
||||
expect(converse.emit).toHaveBeenCalledWith('onChatBoxOpened', jasmine.any(Object));
|
||||
utils.closeAllChatBoxes();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {
|
||||
expect(converse.chatboxes.length).toEqual(0);
|
||||
expect(converse.emit).toHaveBeenCalledWith('onChatBoxClosed', jasmine.any(Object));
|
||||
var newchatboxes = new this.ChatBoxes();
|
||||
expect(newchatboxes.length).toEqual(0);
|
||||
// onConnected will fetch chatboxes in localStorage, but
|
||||
// because there aren't any open chatboxes, there won't be any
|
||||
// in localStorage either. XXX except for the controlbox
|
||||
newchatboxes.onConnected();
|
||||
expect(newchatboxes.length).toEqual(1);
|
||||
expect(newchatboxes.models[0].id).toBe("controlbox");
|
||||
}.bind(converse));
|
||||
}, converse));
|
||||
|
||||
describe("A chat toolbar", $.proxy(function () {
|
||||
@ -104,7 +175,7 @@
|
||||
var contact_jid = mock.cur_names[2].replace(' ','.').toLowerCase() + '@localhost';
|
||||
utils.openChatBoxFor(contact_jid);
|
||||
var chatbox = this.chatboxes.get(contact_jid);
|
||||
var view = this.chatboxesview.views[contact_jid];
|
||||
var view = this.chatboxviews.get(contact_jid);
|
||||
expect(chatbox).toBeDefined();
|
||||
expect(view).toBeDefined();
|
||||
var $toolbar = view.$el.find('ul.chat-toolbar');
|
||||
@ -116,7 +187,7 @@
|
||||
var contact_jid = mock.cur_names[2].replace(' ','.').toLowerCase() + '@localhost';
|
||||
utils.openChatBoxFor(contact_jid);
|
||||
var chatbox = this.chatboxes.get(contact_jid);
|
||||
var view = this.chatboxesview.views[contact_jid];
|
||||
var view = this.chatboxviews.get(contact_jid);
|
||||
var $toolbar = view.$el.find('ul.chat-toolbar');
|
||||
var $textarea = view.$el.find('textarea.chat-textarea');
|
||||
expect($toolbar.children('li.toggle-smiley').length).toBe(1);
|
||||
@ -148,7 +219,7 @@
|
||||
expect($($items[10]).children('a').data('emoticon')).toBe(':O');
|
||||
expect($($items[11]).children('a').data('emoticon')).toBe('(^.^)b');
|
||||
expect($($items[12]).children('a').data('emoticon')).toBe('<3');
|
||||
$items[0].click();
|
||||
$items.first().click();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {
|
||||
@ -176,7 +247,7 @@
|
||||
var contact_jid = mock.cur_names[2].replace(' ','.').toLowerCase() + '@localhost';
|
||||
utils.openChatBoxFor(contact_jid);
|
||||
var chatbox = this.chatboxes.get(contact_jid);
|
||||
var view = this.chatboxesview.views[contact_jid];
|
||||
var view = this.chatboxviews.get(contact_jid);
|
||||
var $toolbar = view.$el.find('ul.chat-toolbar');
|
||||
expect($toolbar.children('li.toggle-otr').length).toBe(1);
|
||||
// Register spies
|
||||
@ -202,7 +273,7 @@
|
||||
var contact_jid = mock.cur_names[2].replace(' ','.').toLowerCase() + '@localhost';
|
||||
utils.openChatBoxFor(contact_jid);
|
||||
var chatbox = this.chatboxes.get(contact_jid);
|
||||
var view = this.chatboxesview.views[contact_jid];
|
||||
var view = this.chatboxviews.get(contact_jid);
|
||||
var $toolbar = view.$el.find('ul.chat-toolbar');
|
||||
var callButton = $toolbar.find('.toggle-call');
|
||||
|
||||
@ -245,11 +316,11 @@
|
||||
this.chatboxes.onMessage(msg);
|
||||
expect(converse.emit).toHaveBeenCalledWith('onMessage', msg);
|
||||
}, converse));
|
||||
waits(300);
|
||||
waits(250);
|
||||
runs($.proxy(function () {
|
||||
// Check that the chatbox and its view now exist
|
||||
var chatbox = this.chatboxes.get(sender_jid);
|
||||
var chatboxview = this.chatboxesview.views[sender_jid];
|
||||
var chatboxview = this.chatboxviews.get(sender_jid);
|
||||
expect(chatbox).toBeDefined();
|
||||
expect(chatboxview).toBeDefined();
|
||||
// Check that the message was received and check the
|
||||
@ -272,17 +343,84 @@
|
||||
}, converse));
|
||||
}, converse));
|
||||
|
||||
it("will indate when it has a time difference of more than a day between it and it's predecessor", $.proxy(function () {
|
||||
it("received for a minimized chat box will increment a counter on its header", $.proxy(function () {
|
||||
var contact_name = mock.cur_names[0];
|
||||
var contact_jid = contact_name.replace(' ','.').toLowerCase() + '@localhost';
|
||||
spyOn(this, 'emit');
|
||||
runs(function () {
|
||||
utils.openChatBoxFor(contact_jid);
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {
|
||||
var chatview = converse.chatboxviews.get(contact_jid);
|
||||
expect(chatview.model.get('minimized')).toBeFalsy();
|
||||
chatview.$el.find('.toggle-chatbox-button').click();
|
||||
});
|
||||
waits(250);
|
||||
runs($.proxy(function () {
|
||||
var chatview = this.chatboxviews.get(contact_jid);
|
||||
expect(chatview.model.get('minimized')).toBeTruthy();
|
||||
var message = 'This message is sent to a minimized chatbox';
|
||||
var sender_jid = mock.cur_names[0].replace(' ','.').toLowerCase() + '@localhost';
|
||||
msg = $msg({
|
||||
from: sender_jid,
|
||||
to: this.connection.jid,
|
||||
type: 'chat',
|
||||
id: (new Date()).getTime()
|
||||
}).c('body').t(message).up()
|
||||
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree();
|
||||
this.chatboxes.onMessage(msg);
|
||||
expect(this.emit).toHaveBeenCalledWith('onMessage', msg);
|
||||
}, converse));
|
||||
waits(250);
|
||||
runs($.proxy(function () {
|
||||
var chatview = this.chatboxviews.get(contact_jid);
|
||||
var $count = chatview.$el.find('.chat-head-message-count');
|
||||
expect(chatview.model.get('minimized')).toBeTruthy();
|
||||
expect($count.is(':visible')).toBeTruthy();
|
||||
expect($count.data('count')).toBe(1);
|
||||
expect($count.html()).toBe('1');
|
||||
this.chatboxes.onMessage(
|
||||
$msg({
|
||||
from: mock.cur_names[0].replace(' ','.').toLowerCase() + '@localhost',
|
||||
to: this.connection.jid,
|
||||
type: 'chat',
|
||||
id: (new Date()).getTime()
|
||||
}).c('body').t('This message is also sent to a minimized chatbox').up()
|
||||
.c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree()
|
||||
);
|
||||
}, converse));
|
||||
waits(100);
|
||||
runs($.proxy(function () {
|
||||
var chatview = this.chatboxviews.get(contact_jid);
|
||||
var $count = chatview.$el.find('.chat-head-message-count');
|
||||
expect(chatview.model.get('minimized')).toBeTruthy();
|
||||
expect($count.is(':visible')).toBeTruthy();
|
||||
expect($count.data('count')).toBe(2);
|
||||
expect($count.html()).toBe('2');
|
||||
chatview.$el.find('.toggle-chatbox-button').click();
|
||||
}, converse));
|
||||
waits(250);
|
||||
runs($.proxy(function () {
|
||||
var chatview = this.chatboxviews.get(contact_jid);
|
||||
var $count = chatview.$el.find('.chat-head-message-count');
|
||||
expect(chatview.model.get('minimized')).toBeFalsy();
|
||||
expect($count.is(':visible')).toBeFalsy();
|
||||
expect($count.data('count')).toBe(0);
|
||||
expect($count.html()).toBe('0');
|
||||
}, converse));
|
||||
}, converse));
|
||||
|
||||
it("will indicate when it has a time difference of more than a day between it and its predecessor", $.proxy(function () {
|
||||
spyOn(converse, 'emit');
|
||||
var contact_name = mock.cur_names[1];
|
||||
var contact_jid = contact_name.replace(' ','.').toLowerCase() + '@localhost';
|
||||
utils.openChatBoxFor(contact_jid);
|
||||
utils.clearChatBoxMessages(contact_jid);
|
||||
|
||||
var one_day_ago = new Date(new Date().setDate(new Date().getDate()-1));
|
||||
var message = 'This is a day old message';
|
||||
var chatbox = this.chatboxes.get(contact_jid);
|
||||
var chatboxview = this.chatboxesview.views[contact_jid];
|
||||
var chatboxview = this.chatboxviews.get(contact_jid);
|
||||
var $chat_content = chatboxview.$el.find('.chat-content');
|
||||
var msg_obj;
|
||||
var msg_txt;
|
||||
@ -323,11 +461,10 @@
|
||||
// props.
|
||||
var $time = $chat_content.find('time');
|
||||
var message_date = new Date();
|
||||
message_date.setUTCHours(0,0,0,0);
|
||||
expect($time.length).toEqual(1);
|
||||
expect($time.attr('class')).toEqual('chat-date');
|
||||
expect($time.attr('datetime')).toEqual(converse.toISOString(message_date));
|
||||
expect($time.text()).toEqual(message_date.toString().substring(0,15));
|
||||
expect($time.attr('datetime')).toEqual(moment(message_date).format("YYYY-MM-DD"));
|
||||
expect($time.text()).toEqual(moment(message_date).format("dddd, MMMM Do YYYY"));
|
||||
|
||||
// Normal checks for the 2nd message
|
||||
expect(chatbox.messages.length).toEqual(2);
|
||||
@ -345,24 +482,28 @@
|
||||
it("can be sent from a chatbox, and will appear inside it", $.proxy(function () {
|
||||
spyOn(converse, 'emit');
|
||||
var contact_jid = mock.cur_names[0].replace(' ','.').toLowerCase() + '@localhost';
|
||||
utils.openChatBoxFor(contact_jid);
|
||||
expect(converse.emit).toHaveBeenCalledWith('onChatBoxOpened', jasmine.any(Object));
|
||||
var view = this.chatboxesview.views[contact_jid];
|
||||
var message = 'This message is sent from this chatbox';
|
||||
spyOn(view, 'sendMessage').andCallThrough();
|
||||
utils.sendMessage(view, message);
|
||||
expect(view.sendMessage).toHaveBeenCalled();
|
||||
expect(view.model.messages.length, 2);
|
||||
expect(converse.emit.callCount).toEqual(2);
|
||||
expect(converse.emit.mostRecentCall.args, ['onMessageSend', message]);
|
||||
var txt = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-message-content').text();
|
||||
expect(txt).toEqual(message);
|
||||
runs(function () {
|
||||
utils.openChatBoxFor(contact_jid);
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {
|
||||
expect(converse.emit).toHaveBeenCalledWith('onChatBoxFocused', jasmine.any(Object));
|
||||
var view = this.chatboxviews.get(contact_jid);
|
||||
var message = 'This message is sent from this chatbox';
|
||||
spyOn(view, 'sendMessage').andCallThrough();
|
||||
utils.sendMessage(view, message);
|
||||
expect(view.sendMessage).toHaveBeenCalled();
|
||||
expect(view.model.messages.length, 2);
|
||||
expect(converse.emit.callCount).toEqual(3);
|
||||
expect(converse.emit.mostRecentCall.args, ['onMessageSend', message]);
|
||||
expect(view.$el.find('.chat-content').find('.chat-message').last().find('.chat-message-content').text()).toEqual(message);
|
||||
}.bind(converse));
|
||||
}, converse));
|
||||
|
||||
it("is sanitized to prevent Javascript injection attacks", $.proxy(function () {
|
||||
var contact_jid = mock.cur_names[0].replace(' ','.').toLowerCase() + '@localhost';
|
||||
utils.openChatBoxFor(contact_jid);
|
||||
var view = this.chatboxesview.views[contact_jid];
|
||||
var view = this.chatboxviews.get(contact_jid);
|
||||
var message = '<p>This message contains <em>some</em> <b>markup</b></p>';
|
||||
spyOn(view, 'sendMessage').andCallThrough();
|
||||
utils.sendMessage(view, message);
|
||||
@ -375,7 +516,7 @@
|
||||
it("can contain hyperlinks, which will be clickable", $.proxy(function () {
|
||||
var contact_jid = mock.cur_names[0].replace(' ','.').toLowerCase() + '@localhost';
|
||||
utils.openChatBoxFor(contact_jid);
|
||||
var view = this.chatboxesview.views[contact_jid];
|
||||
var view = this.chatboxviews.get(contact_jid);
|
||||
var message = 'This message contains a hyperlink: www.opkode.com';
|
||||
spyOn(view, 'sendMessage').andCallThrough();
|
||||
utils.sendMessage(view, message);
|
||||
@ -388,7 +529,7 @@
|
||||
it("will have properly escaped URLs", $.proxy(function () {
|
||||
var contact_jid = mock.cur_names[0].replace(' ','.').toLowerCase() + '@localhost';
|
||||
utils.openChatBoxFor(contact_jid);
|
||||
var view = this.chatboxesview.views[contact_jid];
|
||||
var view = this.chatboxviews.get(contact_jid);
|
||||
spyOn(view, 'sendMessage').andCallThrough();
|
||||
|
||||
var message = "http://www.opkode.com/'onmouseover='alert(1)'whatever";
|
||||
@ -438,7 +579,7 @@
|
||||
spyOn(converse, 'emit');
|
||||
var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||
utils.openChatBoxFor(contact_jid);
|
||||
var view = this.chatboxesview.views[contact_jid];
|
||||
var view = this.chatboxviews.get(contact_jid);
|
||||
var message = 'This message is another sent from this chatbox';
|
||||
// Lets make sure there is at least one message already
|
||||
// (e.g for when this test is run on its own).
|
||||
@ -487,7 +628,8 @@
|
||||
it("is cleared when the window is focused", $.proxy(function () {
|
||||
spyOn(converse, 'clearMsgCounter').andCallThrough();
|
||||
runs(function () {
|
||||
$(window).trigger('focus');
|
||||
$(window).triggerHandler('blur');
|
||||
$(window).triggerHandler('focus');
|
||||
});
|
||||
waits(50);
|
||||
runs(function () {
|
||||
|
190
spec/chatroom.js
190
spec/chatroom.js
@ -10,12 +10,39 @@
|
||||
return describe("ChatRooms", $.proxy(function (mock, utils) {
|
||||
describe("A Chat Room", $.proxy(function () {
|
||||
beforeEach(function () {
|
||||
utils.closeAllChatBoxes();
|
||||
utils.createNewChatRoom('lounge', 'dummy');
|
||||
runs(function () {
|
||||
utils.closeAllChatBoxes();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {
|
||||
utils.openControlBox();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {
|
||||
utils.openRoomsPanel();
|
||||
});
|
||||
waits(501);
|
||||
runs(function () {
|
||||
// Open a new chatroom
|
||||
var roomspanel = converse.chatboxviews.get('controlbox').roomspanel;
|
||||
var $input = roomspanel.$el.find('input.new-chatroom-name');
|
||||
var $nick = roomspanel.$el.find('input.new-chatroom-nick');
|
||||
var $server = roomspanel.$el.find('input.new-chatroom-server');
|
||||
$input.val('lounge');
|
||||
$nick.val('dummy');
|
||||
$server.val('muc.localhost');
|
||||
roomspanel.$el.find('form').submit();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {
|
||||
utils.closeControlBox();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {});
|
||||
});
|
||||
|
||||
it("shows users currently present in the room", $.proxy(function () {
|
||||
var chatroomview = this.chatboxesview.views['lounge@muc.localhost'],
|
||||
var chatroomview = this.chatboxviews.get('lounge@muc.localhost'),
|
||||
$participant_list;
|
||||
var roster = {}, room = {}, i;
|
||||
for (i=0; i<mock.chatroom_names.length-1; i++) {
|
||||
@ -30,7 +57,7 @@
|
||||
}, converse));
|
||||
|
||||
it("indicates moderators by means of a special css class and tooltip", $.proxy(function () {
|
||||
var chatroomview = this.chatboxesview.views['lounge@muc.localhost'];
|
||||
var chatroomview = this.chatboxviews.get('lounge@muc.localhost');
|
||||
var roster = {}, idx = mock.chatroom_names.length-1;
|
||||
roster[mock.chatroom_names[idx]] = {};
|
||||
roster[mock.chatroom_names[idx]].role = 'moderator';
|
||||
@ -44,7 +71,7 @@
|
||||
|
||||
it("shows received groupchat messages", $.proxy(function () {
|
||||
spyOn(converse, 'emit');
|
||||
var view = this.chatboxesview.views['lounge@muc.localhost'];
|
||||
var view = this.chatboxviews.get('lounge@muc.localhost');
|
||||
if (!view.$el.find('.chat-area').length) { view.renderChatArea(); }
|
||||
var nick = mock.chatroom_names[0];
|
||||
var text = 'This is a received message';
|
||||
@ -63,7 +90,7 @@
|
||||
|
||||
it("shows sent groupchat messages", $.proxy(function () {
|
||||
spyOn(converse, 'emit');
|
||||
var view = this.chatboxesview.views['lounge@muc.localhost'];
|
||||
var view = this.chatboxviews.get('lounge@muc.localhost');
|
||||
if (!view.$el.find('.chat-area').length) { view.renderChatArea(); }
|
||||
var nick = mock.chatroom_names[0];
|
||||
var text = 'This is a sent message';
|
||||
@ -88,39 +115,82 @@
|
||||
it("can be saved to, and retrieved from, localStorage", $.proxy(function () {
|
||||
// We instantiate a new ChatBoxes collection, which by default
|
||||
// will be empty.
|
||||
utils.openControlBox();
|
||||
var newchatboxes = new this.ChatBoxes();
|
||||
expect(newchatboxes.length).toEqual(0);
|
||||
// The chatboxes will then be fetched from localStorage inside the
|
||||
// onConnected method
|
||||
newchatboxes.onConnected();
|
||||
expect(newchatboxes.length).toEqual(1);
|
||||
expect(newchatboxes.length).toEqual(2); // XXX: Includes controlbox, is this a bug?
|
||||
// Check that the chatrooms retrieved from localStorage
|
||||
// have the same attributes values as the original ones.
|
||||
attrs = ['id', 'box_id', 'visible'];
|
||||
for (i=0; i<attrs.length; i++) {
|
||||
new_attrs = _.pluck(_.pluck(newchatboxes.models, 'attributes'), attrs[i]);
|
||||
old_attrs = _.pluck(_.pluck(this.chatboxes.models, 'attributes'), attrs[i]);
|
||||
expect(_.isEqual(new_attrs, old_attrs)).toEqual(true);
|
||||
// FIXME: should have have to sort here? Order must
|
||||
// probably be the same...
|
||||
// This should be fixed once the controlbox always opens
|
||||
// only on the right.
|
||||
expect(_.isEqual(new_attrs.sort(), old_attrs.sort())).toEqual(true);
|
||||
}
|
||||
this.rosterview.render();
|
||||
}, converse));
|
||||
|
||||
it("can be toggled by clicking a DOM element with class 'toggle-chatbox-button'", function () {
|
||||
var view = this.chatboxviews.get('lounge@muc.localhost'),
|
||||
chatroom = view.model, $el;
|
||||
spyOn(view, 'toggleChatBox').andCallThrough();
|
||||
spyOn(converse, 'emit');
|
||||
view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
|
||||
runs(function () {
|
||||
view.$el.find('.toggle-chatbox-button').click();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {
|
||||
expect(view.toggleChatBox).toHaveBeenCalled();
|
||||
expect(converse.emit).toHaveBeenCalledWith('onChatBoxToggled', jasmine.any(Object));
|
||||
expect(converse.emit.callCount, 2);
|
||||
expect(view.$el.find('.chat-body').is(':visible')).toBeFalsy();
|
||||
expect(view.$el.find('.toggle-chatbox-button').hasClass('icon-minus')).toBeFalsy();
|
||||
expect(view.$el.find('.toggle-chatbox-button').hasClass('icon-plus')).toBeTruthy();
|
||||
expect(view.model.get('minimized')).toBeTruthy();
|
||||
view.$el.find('.toggle-chatbox-button').click();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {
|
||||
expect(view.toggleChatBox).toHaveBeenCalled();
|
||||
expect(converse.emit).toHaveBeenCalledWith('onChatBoxToggled', jasmine.any(Object));
|
||||
expect(view.$el.find('.chat-body').is(':visible')).toBeTruthy();
|
||||
expect(view.$el.find('.toggle-chatbox-button').hasClass('icon-minus')).toBeTruthy();
|
||||
expect(view.$el.find('.toggle-chatbox-button').hasClass('icon-plus')).toBeFalsy();
|
||||
expect(view.model.get('minimized')).toBeFalsy();
|
||||
expect(converse.emit.callCount, 3);
|
||||
});
|
||||
}.bind(converse));
|
||||
|
||||
|
||||
it("can be closed again by clicking a DOM element with class 'close-chatbox-button'", $.proxy(function () {
|
||||
var view = this.chatboxesview.views['lounge@muc.localhost'], chatroom = view.model, $el;
|
||||
var view = this.chatboxviews.get('lounge@muc.localhost'), chatroom = view.model, $el;
|
||||
spyOn(view, 'closeChat').andCallThrough();
|
||||
spyOn(converse, 'emit');
|
||||
spyOn(converse.connection.muc, 'leave');
|
||||
view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
|
||||
view.$el.find('.close-chatbox-button').click();
|
||||
expect(view.closeChat).toHaveBeenCalled();
|
||||
expect(converse.connection.muc.leave).toHaveBeenCalled();
|
||||
expect(converse.emit).toHaveBeenCalledWith('onChatBoxClosed', jasmine.any(Object));
|
||||
runs(function () {
|
||||
view.$el.find('.close-chatbox-button').click();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {
|
||||
expect(view.closeChat).toHaveBeenCalled();
|
||||
expect(this.connection.muc.leave).toHaveBeenCalled();
|
||||
expect(this.emit).toHaveBeenCalledWith('onChatBoxClosed', jasmine.any(Object));
|
||||
}.bind(converse));
|
||||
}, converse));
|
||||
}, converse));
|
||||
|
||||
describe("When attempting to enter a chatroom", $.proxy(function () {
|
||||
beforeEach($.proxy(function () {
|
||||
var roomspanel = this.chatboxesview.views.controlbox.roomspanel;
|
||||
var roomspanel = this.chatboxviews.get('controlbox').roomspanel;
|
||||
var $input = roomspanel.$el.find('input.new-chatroom-name');
|
||||
var $nick = roomspanel.$el.find('input.new-chatroom-nick');
|
||||
var $server = roomspanel.$el.find('input.new-chatroom-server');
|
||||
@ -131,21 +201,21 @@
|
||||
}, converse));
|
||||
|
||||
afterEach($.proxy(function () {
|
||||
var view = this.chatboxesview.views['problematic@muc.localhost'];
|
||||
var view = this.chatboxviews.get('problematic@muc.localhost');
|
||||
view.closeChat();
|
||||
}, converse));
|
||||
|
||||
it("will show an error message if the room requires a password", $.proxy(function () {
|
||||
var presence = $pres().attrs({
|
||||
from:'coven@chat.shakespeare.lit/thirdwitch',
|
||||
id:'n13mt3l',
|
||||
to:'hag66@shakespeare.lit/pda',
|
||||
type:'error'})
|
||||
from:'coven@chat.shakespeare.lit/thirdwitch',
|
||||
id:'n13mt3l',
|
||||
to:'hag66@shakespeare.lit/pda',
|
||||
type:'error'})
|
||||
.c('x').attrs({xmlns:'http://jabber.org/protocol/muc'}).up()
|
||||
.c('error').attrs({by:'coven@chat.shakespeare.lit', type:'auth'})
|
||||
.c('not-authorized').attrs({xmlns:'urn:ietf:params:xml:ns:xmpp-stanzas'}).nodeTree;
|
||||
|
||||
var view = this.chatboxesview.views['problematic@muc.localhost'];
|
||||
var view = this.chatboxviews.get('problematic@muc.localhost');
|
||||
spyOn(view, 'renderPasswordForm').andCallThrough();
|
||||
runs(function () {
|
||||
view.onChatRoomPresence(presence, {'nick': 'dummy'});
|
||||
@ -161,14 +231,14 @@
|
||||
|
||||
it("will show an error message if the room is members-only and the user not included", $.proxy(function () {
|
||||
var presence = $pres().attrs({
|
||||
from:'coven@chat.shakespeare.lit/thirdwitch',
|
||||
id:'n13mt3l',
|
||||
to:'hag66@shakespeare.lit/pda',
|
||||
type:'error'})
|
||||
from:'coven@chat.shakespeare.lit/thirdwitch',
|
||||
id:'n13mt3l',
|
||||
to:'hag66@shakespeare.lit/pda',
|
||||
type:'error'})
|
||||
.c('x').attrs({xmlns:'http://jabber.org/protocol/muc'}).up()
|
||||
.c('error').attrs({by:'coven@chat.shakespeare.lit', type:'auth'})
|
||||
.c('registration-required').attrs({xmlns:'urn:ietf:params:xml:ns:xmpp-stanzas'}).nodeTree;
|
||||
var view = this.chatboxesview.views['problematic@muc.localhost'];
|
||||
var view = this.chatboxviews.get('problematic@muc.localhost');
|
||||
spyOn(view, 'showErrorMessage').andCallThrough();
|
||||
view.onChatRoomPresence(presence, {'nick': 'dummy'});
|
||||
expect(view.$el.find('.chat-body p').text()).toBe('You are not on the member list of this room');
|
||||
@ -176,14 +246,14 @@
|
||||
|
||||
it("will show an error message if the user has been banned", $.proxy(function () {
|
||||
var presence = $pres().attrs({
|
||||
from:'coven@chat.shakespeare.lit/thirdwitch',
|
||||
id:'n13mt3l',
|
||||
to:'hag66@shakespeare.lit/pda',
|
||||
type:'error'})
|
||||
from:'coven@chat.shakespeare.lit/thirdwitch',
|
||||
id:'n13mt3l',
|
||||
to:'hag66@shakespeare.lit/pda',
|
||||
type:'error'})
|
||||
.c('x').attrs({xmlns:'http://jabber.org/protocol/muc'}).up()
|
||||
.c('error').attrs({by:'coven@chat.shakespeare.lit', type:'auth'})
|
||||
.c('forbidden').attrs({xmlns:'urn:ietf:params:xml:ns:xmpp-stanzas'}).nodeTree;
|
||||
var view = this.chatboxesview.views['problematic@muc.localhost'];
|
||||
var view = this.chatboxviews.get('problematic@muc.localhost');
|
||||
spyOn(view, 'showErrorMessage').andCallThrough();
|
||||
view.onChatRoomPresence(presence, {'nick': 'dummy'});
|
||||
expect(view.$el.find('.chat-body p').text()).toBe('You have been banned from this room');
|
||||
@ -191,14 +261,14 @@
|
||||
|
||||
it("will show an error message if no nickname was specified for the user", $.proxy(function () {
|
||||
var presence = $pres().attrs({
|
||||
from:'coven@chat.shakespeare.lit/thirdwitch',
|
||||
id:'n13mt3l',
|
||||
to:'hag66@shakespeare.lit/pda',
|
||||
type:'error'})
|
||||
from:'coven@chat.shakespeare.lit/thirdwitch',
|
||||
id:'n13mt3l',
|
||||
to:'hag66@shakespeare.lit/pda',
|
||||
type:'error'})
|
||||
.c('x').attrs({xmlns:'http://jabber.org/protocol/muc'}).up()
|
||||
.c('error').attrs({by:'coven@chat.shakespeare.lit', type:'modify'})
|
||||
.c('jid-malformed').attrs({xmlns:'urn:ietf:params:xml:ns:xmpp-stanzas'}).nodeTree;
|
||||
var view = this.chatboxesview.views['problematic@muc.localhost'];
|
||||
var view = this.chatboxviews.get('problematic@muc.localhost');
|
||||
spyOn(view, 'showErrorMessage').andCallThrough();
|
||||
view.onChatRoomPresence(presence, {'nick': 'dummy'});
|
||||
expect(view.$el.find('.chat-body p').text()).toBe('No nickname was specified');
|
||||
@ -206,14 +276,14 @@
|
||||
|
||||
it("will show an error message if the user is not allowed to have created the room", $.proxy(function () {
|
||||
var presence = $pres().attrs({
|
||||
from:'coven@chat.shakespeare.lit/thirdwitch',
|
||||
id:'n13mt3l',
|
||||
to:'hag66@shakespeare.lit/pda',
|
||||
type:'error'})
|
||||
from:'coven@chat.shakespeare.lit/thirdwitch',
|
||||
id:'n13mt3l',
|
||||
to:'hag66@shakespeare.lit/pda',
|
||||
type:'error'})
|
||||
.c('x').attrs({xmlns:'http://jabber.org/protocol/muc'}).up()
|
||||
.c('error').attrs({by:'coven@chat.shakespeare.lit', type:'cancel'})
|
||||
.c('not-allowed').attrs({xmlns:'urn:ietf:params:xml:ns:xmpp-stanzas'}).nodeTree;
|
||||
var view = this.chatboxesview.views['problematic@muc.localhost'];
|
||||
var view = this.chatboxviews.get('problematic@muc.localhost');
|
||||
spyOn(view, 'showErrorMessage').andCallThrough();
|
||||
view.onChatRoomPresence(presence, {'nick': 'dummy'});
|
||||
expect(view.$el.find('.chat-body p').text()).toBe('You are not allowed to create new rooms');
|
||||
@ -221,14 +291,14 @@
|
||||
|
||||
it("will show an error message if the user's nickname doesn't conform to room policy", $.proxy(function () {
|
||||
var presence = $pres().attrs({
|
||||
from:'coven@chat.shakespeare.lit/thirdwitch',
|
||||
id:'n13mt3l',
|
||||
to:'hag66@shakespeare.lit/pda',
|
||||
type:'error'})
|
||||
from:'coven@chat.shakespeare.lit/thirdwitch',
|
||||
id:'n13mt3l',
|
||||
to:'hag66@shakespeare.lit/pda',
|
||||
type:'error'})
|
||||
.c('x').attrs({xmlns:'http://jabber.org/protocol/muc'}).up()
|
||||
.c('error').attrs({by:'coven@chat.shakespeare.lit', type:'cancel'})
|
||||
.c('not-acceptable').attrs({xmlns:'urn:ietf:params:xml:ns:xmpp-stanzas'}).nodeTree;
|
||||
var view = this.chatboxesview.views['problematic@muc.localhost'];
|
||||
var view = this.chatboxviews.get('problematic@muc.localhost');
|
||||
spyOn(view, 'showErrorMessage').andCallThrough();
|
||||
view.onChatRoomPresence(presence, {'nick': 'dummy'});
|
||||
expect(view.$el.find('.chat-body p').text()).toBe("Your nickname doesn't conform to this room's policies");
|
||||
@ -236,14 +306,14 @@
|
||||
|
||||
it("will show an error message if the user's nickname is already taken", $.proxy(function () {
|
||||
var presence = $pres().attrs({
|
||||
from:'coven@chat.shakespeare.lit/thirdwitch',
|
||||
id:'n13mt3l',
|
||||
to:'hag66@shakespeare.lit/pda',
|
||||
type:'error'})
|
||||
from:'coven@chat.shakespeare.lit/thirdwitch',
|
||||
id:'n13mt3l',
|
||||
to:'hag66@shakespeare.lit/pda',
|
||||
type:'error'})
|
||||
.c('x').attrs({xmlns:'http://jabber.org/protocol/muc'}).up()
|
||||
.c('error').attrs({by:'coven@chat.shakespeare.lit', type:'cancel'})
|
||||
.c('conflict').attrs({xmlns:'urn:ietf:params:xml:ns:xmpp-stanzas'}).nodeTree;
|
||||
var view = this.chatboxesview.views['problematic@muc.localhost'];
|
||||
var view = this.chatboxviews.get('problematic@muc.localhost');
|
||||
spyOn(view, 'showErrorMessage').andCallThrough();
|
||||
view.onChatRoomPresence(presence, {'nick': 'dummy'});
|
||||
expect(view.$el.find('.chat-body p').text()).toBe("Your nickname is already taken");
|
||||
@ -251,14 +321,14 @@
|
||||
|
||||
it("will show an error message if the room doesn't yet exist", $.proxy(function () {
|
||||
var presence = $pres().attrs({
|
||||
from:'coven@chat.shakespeare.lit/thirdwitch',
|
||||
id:'n13mt3l',
|
||||
to:'hag66@shakespeare.lit/pda',
|
||||
type:'error'})
|
||||
from:'coven@chat.shakespeare.lit/thirdwitch',
|
||||
id:'n13mt3l',
|
||||
to:'hag66@shakespeare.lit/pda',
|
||||
type:'error'})
|
||||
.c('x').attrs({xmlns:'http://jabber.org/protocol/muc'}).up()
|
||||
.c('error').attrs({by:'coven@chat.shakespeare.lit', type:'cancel'})
|
||||
.c('item-not-found').attrs({xmlns:'urn:ietf:params:xml:ns:xmpp-stanzas'}).nodeTree;
|
||||
var view = this.chatboxesview.views['problematic@muc.localhost'];
|
||||
var view = this.chatboxviews.get('problematic@muc.localhost');
|
||||
spyOn(view, 'showErrorMessage').andCallThrough();
|
||||
view.onChatRoomPresence(presence, {'nick': 'dummy'});
|
||||
expect(view.$el.find('.chat-body p').text()).toBe("This room does not (yet) exist");
|
||||
@ -266,14 +336,14 @@
|
||||
|
||||
it("will show an error message if the room has reached it's maximum number of occupants", $.proxy(function () {
|
||||
var presence = $pres().attrs({
|
||||
from:'coven@chat.shakespeare.lit/thirdwitch',
|
||||
id:'n13mt3l',
|
||||
to:'hag66@shakespeare.lit/pda',
|
||||
type:'error'})
|
||||
from:'coven@chat.shakespeare.lit/thirdwitch',
|
||||
id:'n13mt3l',
|
||||
to:'hag66@shakespeare.lit/pda',
|
||||
type:'error'})
|
||||
.c('x').attrs({xmlns:'http://jabber.org/protocol/muc'}).up()
|
||||
.c('error').attrs({by:'coven@chat.shakespeare.lit', type:'cancel'})
|
||||
.c('service-unavailable').attrs({xmlns:'urn:ietf:params:xml:ns:xmpp-stanzas'}).nodeTree;
|
||||
var view = this.chatboxesview.views['problematic@muc.localhost'];
|
||||
var view = this.chatboxviews.get('problematic@muc.localhost');
|
||||
spyOn(view, 'showErrorMessage').andCallThrough();
|
||||
view.onChatRoomPresence(presence, {'nick': 'dummy'});
|
||||
expect(view.$el.find('.chat-body p').text()).toBe("This room has reached it's maximum number of occupants");
|
||||
|
@ -8,28 +8,50 @@
|
||||
);
|
||||
} (this, function (mock, utils) {
|
||||
describe("The Control Box", $.proxy(function (mock, utils) {
|
||||
window.localStorage.clear();
|
||||
|
||||
it("is not shown by default", $.proxy(function () {
|
||||
expect(this.rosterview.$el.is(':visible')).toEqual(false);
|
||||
beforeEach(function () {
|
||||
runs(function () {
|
||||
utils.openControlBox();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {});
|
||||
});
|
||||
|
||||
it("can be opened by clicking a DOM element with class 'toggle-online-users'", $.proxy(function () {
|
||||
runs(function () {
|
||||
utils.closeControlBox();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {
|
||||
// This spec will only pass if the controlbox is not currently
|
||||
// open yet.
|
||||
expect($("div#controlbox").is(':visible')).toBe(false);
|
||||
spyOn(this.controlboxtoggle, 'onClick').andCallThrough();
|
||||
spyOn(this.controlboxtoggle, 'showControlBox').andCallThrough();
|
||||
spyOn(converse, 'emit');
|
||||
// Redelegate so that the spies are now registered as the event handlers (specifically for 'onClick')
|
||||
this.controlboxtoggle.delegateEvents();
|
||||
$('.toggle-online-users').click();
|
||||
}.bind(converse));
|
||||
waits(250);
|
||||
runs(function () {
|
||||
expect(this.controlboxtoggle.onClick).toHaveBeenCalled();
|
||||
expect(this.controlboxtoggle.showControlBox).toHaveBeenCalled();
|
||||
expect(this.emit).toHaveBeenCalledWith('onControlBoxOpened', jasmine.any(Object));
|
||||
expect($("div#controlbox").is(':visible')).toBe(true);
|
||||
}.bind(converse));
|
||||
}, converse));
|
||||
|
||||
var open_controlbox = $.proxy(function () {
|
||||
// This spec will only pass if the controlbox is not currently
|
||||
// open yet.
|
||||
expect($("div#controlbox").is(':visible')).toBe(false);
|
||||
spyOn(this.controlboxtoggle, 'onClick').andCallThrough();
|
||||
spyOn(this.controlboxtoggle, 'showControlBox').andCallThrough();
|
||||
// Redelegate so that the spies are now registered as the event handlers (specifically for 'onClick')
|
||||
this.controlboxtoggle.delegateEvents();
|
||||
$('.toggle-online-users').click();
|
||||
expect(this.controlboxtoggle.onClick).toHaveBeenCalled();
|
||||
expect(this.controlboxtoggle.showControlBox).toHaveBeenCalled();
|
||||
expect($("div#controlbox").is(':visible')).toBe(true);
|
||||
}, converse);
|
||||
it("can be opened by clicking a DOM element with class 'toggle-online-users'", open_controlbox);
|
||||
|
||||
describe("The Status Widget", $.proxy(function () {
|
||||
|
||||
beforeEach(function () {
|
||||
runs(function () {
|
||||
utils.openControlBox();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {});
|
||||
});
|
||||
|
||||
it("shows the user's chat status, which is online by default", $.proxy(function () {
|
||||
var view = this.xmppstatusview;
|
||||
expect(view.$el.find('a.choose-xmpp-status').hasClass('online')).toBe(true);
|
||||
@ -88,13 +110,23 @@
|
||||
});
|
||||
}, converse));
|
||||
}, converse));
|
||||
}, converse, utils, mock));
|
||||
}, converse, mock, utils));
|
||||
|
||||
describe("The Contacts Roster", $.proxy(function (mock, utils) {
|
||||
// FIXME: These tests are dependent on being run in order and cannot be
|
||||
// run independently
|
||||
|
||||
describe("The Contacts Roster", $.proxy(function (utils, mock) {
|
||||
describe("Pending Contacts", $.proxy(function () {
|
||||
beforeEach(function () {
|
||||
utils.openControlBox();
|
||||
utils.openContactsPanel();
|
||||
runs(function () {
|
||||
utils.openControlBox();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {
|
||||
utils.openContactsPanel();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {});
|
||||
});
|
||||
|
||||
it("do not have a heading if there aren't any", $.proxy(function () {
|
||||
@ -122,7 +154,8 @@
|
||||
}, converse));
|
||||
|
||||
it("can be removed by the user", $.proxy(function () {
|
||||
var view = _.toArray(this.rosterview.rosteritemviews).pop();
|
||||
var jid = mock.pend_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||
var view = this.rosterview.get(jid);
|
||||
spyOn(window, 'confirm').andReturn(true);
|
||||
spyOn(converse, 'emit');
|
||||
spyOn(this.connection.roster, 'remove').andCallThrough();
|
||||
@ -132,7 +165,7 @@
|
||||
runs($.proxy(function () {
|
||||
view.$el.find('.remove-xmpp-contact').click();
|
||||
}, converse));
|
||||
waits(500);
|
||||
waits(250);
|
||||
runs($.proxy(function () {
|
||||
expect(window.confirm).toHaveBeenCalled();
|
||||
expect(this.connection.roster.remove).toHaveBeenCalled();
|
||||
@ -164,7 +197,7 @@
|
||||
expect(this.rosterview.render).toHaveBeenCalled();
|
||||
expect(converse.emit).toHaveBeenCalledWith('onRosterViewUpdated');
|
||||
// Check that they are sorted alphabetically
|
||||
t = this.rosterview.$el.find('dt#pending-xmpp-contacts').siblings('dd.pending-xmpp-contact').text();
|
||||
t = this.rosterview.$el.find('dt#pending-xmpp-contacts').siblings('dd.pending-xmpp-contact').find('span').text();
|
||||
expect(t).toEqual(mock.pend_names.slice(0,i+1).sort().join(''));
|
||||
}
|
||||
}, converse));
|
||||
@ -177,8 +210,15 @@
|
||||
|
||||
describe("Existing Contacts", $.proxy(function () {
|
||||
beforeEach($.proxy(function () {
|
||||
utils.openControlBox();
|
||||
utils.openContactsPanel();
|
||||
runs(function () {
|
||||
utils.openControlBox();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {
|
||||
utils.openContactsPanel();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {});
|
||||
}, converse));
|
||||
|
||||
it("do not have a heading if there aren't any", $.proxy(function () {
|
||||
@ -215,7 +255,7 @@
|
||||
spyOn(this.rosterview, 'render').andCallThrough();
|
||||
for (i=0; i<3; i++) {
|
||||
jid = mock.cur_names[i].replace(' ','.').toLowerCase() + '@localhost';
|
||||
view = this.rosterview.rosteritemviews[jid];
|
||||
view = this.rosterview.get(jid);
|
||||
spyOn(view, 'render').andCallThrough();
|
||||
item = view.model;
|
||||
item.set('chat_status', 'online');
|
||||
@ -234,7 +274,7 @@
|
||||
spyOn(this.rosterview, 'render').andCallThrough();
|
||||
for (i=3; i<6; i++) {
|
||||
jid = mock.cur_names[i].replace(' ','.').toLowerCase() + '@localhost';
|
||||
view = this.rosterview.rosteritemviews[jid];
|
||||
view = this.rosterview.get(jid);
|
||||
spyOn(view, 'render').andCallThrough();
|
||||
item = view.model;
|
||||
item.set('chat_status', 'dnd');
|
||||
@ -253,7 +293,7 @@
|
||||
spyOn(this.rosterview, 'render').andCallThrough();
|
||||
for (i=6; i<9; i++) {
|
||||
jid = mock.cur_names[i].replace(' ','.').toLowerCase() + '@localhost';
|
||||
view = this.rosterview.rosteritemviews[jid];
|
||||
view = this.rosterview.get(jid);
|
||||
spyOn(view, 'render').andCallThrough();
|
||||
item = view.model;
|
||||
item.set('chat_status', 'away');
|
||||
@ -272,7 +312,7 @@
|
||||
spyOn(this.rosterview, 'render').andCallThrough();
|
||||
for (i=9; i<12; i++) {
|
||||
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||
view = this.rosterview.rosteritemviews[jid];
|
||||
view = this.rosterview.get(jid);
|
||||
spyOn(view, 'render').andCallThrough();
|
||||
item = view.model;
|
||||
item.set('chat_status', 'xa');
|
||||
@ -291,7 +331,7 @@
|
||||
spyOn(this.rosterview, 'render').andCallThrough();
|
||||
for (i=12; i<15; i++) {
|
||||
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||
view = this.rosterview.rosteritemviews[jid];
|
||||
view = this.rosterview.get(jid);
|
||||
spyOn(view, 'render').andCallThrough();
|
||||
item = view.model;
|
||||
item.set('chat_status', 'unavailable');
|
||||
@ -351,7 +391,7 @@
|
||||
});
|
||||
expect(this.rosterview.render).toHaveBeenCalled();
|
||||
// Check that they are sorted alphabetically
|
||||
t = this.rosterview.$el.find('dt#xmpp-contact-requests').siblings('dd.requesting-xmpp-contact').text().replace(/AcceptDecline/g, '');
|
||||
t = this.rosterview.$el.find('dt#xmpp-contact-requests').siblings('dd.requesting-xmpp-contact').children('div').text().replace(/AcceptDecline/g, '');
|
||||
expect(t).toEqual(mock.req_names.slice(0,i+1).sort().join(''));
|
||||
// When a requesting contact is added, the controlbox must
|
||||
// be opened.
|
||||
@ -369,7 +409,7 @@
|
||||
// actually not accepted/authorized because of
|
||||
// mock_connection.
|
||||
var jid = mock.req_names.sort()[0].replace(' ','.').toLowerCase() + '@localhost';
|
||||
var view = this.rosterview.rosteritemviews[jid];
|
||||
var view = this.rosterview.get(jid);
|
||||
spyOn(this.connection.roster, 'authorize');
|
||||
spyOn(view, 'acceptRequest').andCallThrough();
|
||||
view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
|
||||
@ -381,7 +421,7 @@
|
||||
|
||||
it("can have their requests denied by the user", $.proxy(function () {
|
||||
var jid = mock.req_names.sort()[1].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||
var view = this.rosterview.rosteritemviews[jid];
|
||||
var view = this.rosterview.get(jid);
|
||||
spyOn(converse, 'emit');
|
||||
spyOn(this.connection.roster, 'unauthorize');
|
||||
spyOn(this.rosterview, 'removeRosterItemView').andCallThrough();
|
||||
@ -407,7 +447,7 @@
|
||||
expect(new_roster.length).toEqual(0);
|
||||
|
||||
new_roster.localStorage = new Backbone.LocalStorage(
|
||||
hex_sha1('converse.rosteritems-dummy@localhost'));
|
||||
b64_sha1('converse.rosteritems-dummy@localhost'));
|
||||
|
||||
new_roster.fetch();
|
||||
expect(this.roster.length).toEqual(num_contacts);
|
||||
@ -432,16 +472,16 @@
|
||||
// we make some online now
|
||||
for (i=0; i<5; i++) {
|
||||
jid = mock.cur_names[i].replace(' ','.').toLowerCase() + '@localhost';
|
||||
view = this.rosterview.rosteritemviews[jid];
|
||||
view = this.rosterview.get(jid);
|
||||
view.model.set('chat_status', 'online');
|
||||
}
|
||||
}, converse));
|
||||
}, converse));
|
||||
}, converse, utils, mock));
|
||||
}, converse, mock, utils));
|
||||
|
||||
describe("The 'Add Contact' widget", $.proxy(function (utils, mock) {
|
||||
describe("The 'Add Contact' widget", $.proxy(function (mock, utils) {
|
||||
it("opens up an add form when you click on it", $.proxy(function () {
|
||||
var panel = this.chatboxesview.views.controlbox.contactspanel;
|
||||
var panel = this.chatboxviews.get('controlbox').contactspanel;
|
||||
spyOn(panel, 'toggleContactForm').andCallThrough();
|
||||
panel.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
|
||||
panel.$el.find('a.toggle-xmpp-contact-form').click();
|
||||
@ -450,16 +490,23 @@
|
||||
panel.$el.find('a.toggle-xmpp-contact-form').click();
|
||||
}, converse));
|
||||
|
||||
}, converse, utils, mock));
|
||||
}, converse, mock, utils));
|
||||
|
||||
describe("The Controlbox Tabs", $.proxy(function () {
|
||||
beforeEach($.proxy(function () {
|
||||
utils.closeAllChatBoxes();
|
||||
utils.openControlBox();
|
||||
runs(function () {
|
||||
utils.closeAllChatBoxes();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {
|
||||
utils.openControlBox();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {});
|
||||
}, converse));
|
||||
|
||||
it("contains two tabs, 'Contacts' and 'ChatRooms'", $.proxy(function () {
|
||||
var cbview = this.chatboxesview.views.controlbox;
|
||||
var cbview = this.chatboxviews.get('controlbox');
|
||||
var $panels = cbview.$el.find('.controlbox-panes');
|
||||
expect($panels.children().length).toBe(2);
|
||||
expect($panels.children().first().attr('id')).toBe('users');
|
||||
@ -468,14 +515,21 @@
|
||||
expect($panels.children().last().is(':visible')).toBe(false);
|
||||
}, converse));
|
||||
|
||||
describe("The Chatrooms Panel", $.proxy(function () {
|
||||
describe("chatrooms panel", $.proxy(function () {
|
||||
beforeEach($.proxy(function () {
|
||||
utils.closeAllChatBoxes();
|
||||
utils.openControlBox();
|
||||
runs(function () {
|
||||
utils.closeAllChatBoxes();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {
|
||||
utils.openControlBox();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {});
|
||||
}, converse));
|
||||
|
||||
it("is opened by clicking the 'Chatrooms' tab", $.proxy(function () {
|
||||
var cbview = this.chatboxesview.views.controlbox;
|
||||
var cbview = this.chatboxviews.get('controlbox');
|
||||
var $tabs = cbview.$el.find('#controlbox-tabs');
|
||||
var $panels = cbview.$el.find('.controlbox-panes');
|
||||
var $contacts = $panels.children().first();
|
||||
@ -494,7 +548,7 @@
|
||||
}, converse));
|
||||
|
||||
it("contains a form through which a new chatroom can be created", $.proxy(function () {
|
||||
var roomspanel = this.chatboxesview.views.controlbox.roomspanel;
|
||||
var roomspanel = this.chatboxviews.get('controlbox').roomspanel;
|
||||
var $input = roomspanel.$el.find('input.new-chatroom-name');
|
||||
var $nick = roomspanel.$el.find('input.new-chatroom-nick');
|
||||
var $server = roomspanel.$el.find('input.new-chatroom-server');
|
||||
|
@ -21,8 +21,8 @@
|
||||
this.prebind = false;
|
||||
this.connection.pass = 's3cr3t!';
|
||||
expect(this.otr.getSessionPassphrase()).toBe(this.connection.pass);
|
||||
expect(window.sessionStorage.length).toBe(0);
|
||||
expect(window.localStorage.length).toBe(0);
|
||||
expect(window.sessionStorage.length).toBe(0);
|
||||
expect(window.localStorage.length).toBe(0);
|
||||
|
||||
// With prebind, a random passphrase is generated and stored in
|
||||
// session storage.
|
||||
@ -30,8 +30,8 @@
|
||||
pp = this.otr.getSessionPassphrase();
|
||||
expect(pp).not.toBe(this.connection.pass);
|
||||
expect(window.sessionStorage.length).toBe(1);
|
||||
expect(window.localStorage.length).toBe(0);
|
||||
expect(pp).toBe(window.sessionStorage[hex_sha1(converse.connection.jid)]);
|
||||
expect(window.localStorage.length).toBe(0);
|
||||
expect(pp).toBe(window.sessionStorage[b64_sha1(converse.connection.jid)]);
|
||||
|
||||
// Clean up
|
||||
this.prebind = false;
|
||||
|
@ -1,13 +1,18 @@
|
||||
define("converse-dependencies", [
|
||||
"otr",
|
||||
"moment",
|
||||
"locales",
|
||||
"backbone.localStorage",
|
||||
"jquery.tinysort",
|
||||
"jquery.browser",
|
||||
"strophe",
|
||||
"strophe.muc",
|
||||
"strophe.roster",
|
||||
"strophe.vcard",
|
||||
"strophe.disco"
|
||||
], function(otr) {
|
||||
return otr;
|
||||
], function(otr, moment) {
|
||||
return {
|
||||
'otr': otr,
|
||||
'moment': moment
|
||||
};
|
||||
});
|
||||
|
@ -1,12 +1,17 @@
|
||||
define("converse-dependencies", [
|
||||
"moment",
|
||||
"locales",
|
||||
"backbone.localStorage",
|
||||
"jquery.tinysort",
|
||||
"jquery.browser",
|
||||
"strophe",
|
||||
"strophe.muc",
|
||||
"strophe.roster",
|
||||
"strophe.vcard",
|
||||
"strophe.disco"
|
||||
], function() {
|
||||
return undefined;
|
||||
], function(moment) {
|
||||
return {
|
||||
'otr': undefined,
|
||||
'moment': moment
|
||||
};
|
||||
});
|
||||
|
77
src/templates.js
Normal file
77
src/templates.js
Normal file
@ -0,0 +1,77 @@
|
||||
define("converse-templates", [
|
||||
"tpl!src/templates/action",
|
||||
"tpl!src/templates/message",
|
||||
"tpl!src/templates/new_day",
|
||||
"tpl!src/templates/info",
|
||||
"tpl!src/templates/controlbox",
|
||||
"tpl!src/templates/chatbox",
|
||||
"tpl!src/templates/toolbar",
|
||||
"tpl!src/templates/contacts_tab",
|
||||
"tpl!src/templates/contacts_panel",
|
||||
"tpl!src/templates/chatrooms_tab",
|
||||
"tpl!src/templates/login_tab",
|
||||
"tpl!src/templates/add_contact_dropdown",
|
||||
"tpl!src/templates/add_contact_form",
|
||||
"tpl!src/templates/room_item",
|
||||
"tpl!src/templates/room_description",
|
||||
"tpl!src/templates/room_panel",
|
||||
"tpl!src/templates/chatroom",
|
||||
"tpl!src/templates/chatarea",
|
||||
"tpl!src/templates/form_input",
|
||||
"tpl!src/templates/select_option",
|
||||
"tpl!src/templates/form_select",
|
||||
"tpl!src/templates/form_checkbox",
|
||||
"tpl!src/templates/field",
|
||||
"tpl!src/templates/occupant",
|
||||
"tpl!src/templates/roster_item",
|
||||
"tpl!src/templates/pending_contact",
|
||||
"tpl!src/templates/requesting_contact",
|
||||
"tpl!src/templates/requesting_contacts",
|
||||
"tpl!src/templates/pending_contacts",
|
||||
"tpl!src/templates/contacts",
|
||||
"tpl!src/templates/chat_status",
|
||||
"tpl!src/templates/change_status_message",
|
||||
"tpl!src/templates/choose_status",
|
||||
"tpl!src/templates/status_option",
|
||||
"tpl!src/templates/login_panel",
|
||||
"tpl!src/templates/controlbox_toggle"
|
||||
], function () {
|
||||
return {
|
||||
action: arguments[0],
|
||||
message: arguments[1],
|
||||
new_day: arguments[2],
|
||||
info: arguments[3],
|
||||
controlbox: arguments[4],
|
||||
chatbox: arguments[5],
|
||||
toolbar: arguments[6],
|
||||
contacts_tab: arguments[7],
|
||||
contacts_panel: arguments[8],
|
||||
chatrooms_tab: arguments[9],
|
||||
login_tab: arguments[10],
|
||||
add_contact_dropdown: arguments[11],
|
||||
add_contact_form: arguments[12],
|
||||
room_item: arguments[13],
|
||||
room_description: arguments[14],
|
||||
room_panel: arguments[15],
|
||||
chatroom: arguments[16],
|
||||
chatarea: arguments[17],
|
||||
form_input: arguments[18],
|
||||
select_option: arguments[19],
|
||||
form_select: arguments[20],
|
||||
form_checkbox: arguments[21],
|
||||
field: arguments[22],
|
||||
occupant: arguments[23],
|
||||
roster_item: arguments[24],
|
||||
pending_contact: arguments[25],
|
||||
requesting_contact: arguments[26],
|
||||
requesting_contacts: arguments[27],
|
||||
pending_contacts: arguments[28],
|
||||
contacts: arguments[29],
|
||||
chat_status: arguments[30],
|
||||
change_status_message: arguments[31],
|
||||
choose_status: arguments[32],
|
||||
status_option: arguments[33],
|
||||
login_panel: arguments[34],
|
||||
controlbox_toggle: arguments[35]
|
||||
};
|
||||
});
|
4
src/templates/action.html
Normal file
4
src/templates/action.html
Normal file
@ -0,0 +1,4 @@
|
||||
<div class="chat-message {{extra_classes}}">
|
||||
<span class="chat-message-{{sender}}">{{time}} **{{username}} </span>
|
||||
<span class="chat-message-content">{{message}}</span>
|
||||
</div>
|
8
src/templates/add_contact_dropdown.html
Normal file
8
src/templates/add_contact_dropdown.html
Normal file
@ -0,0 +1,8 @@
|
||||
<dl class="add-converse-contact dropdown">
|
||||
<dt id="xmpp-contact-search" class="fancy-dropdown">
|
||||
<a class="toggle-xmpp-contact-form" href="#"
|
||||
title="{{label_click_to_chat}}">
|
||||
<span class="icon-plus"></span>{{label_add_contact}}</a>
|
||||
</dt>
|
||||
<dd class="search-xmpp" style="display:none"><ul></ul></dd>
|
||||
</dl>
|
9
src/templates/add_contact_form.html
Normal file
9
src/templates/add_contact_form.html
Normal file
@ -0,0 +1,9 @@
|
||||
<li>
|
||||
<form class="add-xmpp-contact">
|
||||
<input type="text"
|
||||
name="identifier"
|
||||
class="username"
|
||||
placeholder="{{label_contact_username}}"/>
|
||||
<button type="submit">{{label_add}}</button>
|
||||
</form>
|
||||
<li>
|
5
src/templates/change_status_message.html
Normal file
5
src/templates/change_status_message.html
Normal file
@ -0,0 +1,5 @@
|
||||
<form id="set-custom-xmpp-status">
|
||||
<input type="text" class="custom-xmpp-status" {{status_message}}
|
||||
placeholder="{{label_custom_status}}"/>
|
||||
<button type="submit">{{label_save}}</button>
|
||||
</form>
|
11
src/templates/chat_status.html
Normal file
11
src/templates/chat_status.html
Normal file
@ -0,0 +1,11 @@
|
||||
<div class="xmpp-status">
|
||||
<a class="choose-xmpp-status {{chat_status}}"
|
||||
data-value="{{status_message}}"
|
||||
href="#" title="{{desc_change_status}}">
|
||||
|
||||
<span class="icon-{{chat_status}}"></span>{{status_message}}
|
||||
</a>
|
||||
<a class="change-xmpp-status-message icon-pencil"
|
||||
href="#"
|
||||
title="{{desc_custom_status}}"></a>
|
||||
</div>
|
13
src/templates/chatarea.html
Normal file
13
src/templates/chatarea.html
Normal file
@ -0,0 +1,13 @@
|
||||
<div class="chat-area">
|
||||
<div class="chat-content"></div>
|
||||
<form class="sendXMPPMessage" action="" method="post">
|
||||
{[ if (show_toolbar) { ]}
|
||||
<ul class="chat-toolbar no-text-select"></ul>
|
||||
{[ } ]}
|
||||
<textarea type="text" class="chat-textarea"
|
||||
placeholder="{{label_message}}"/>
|
||||
</form>
|
||||
</div>
|
||||
<div class="participants">
|
||||
<ul class="participant-list"></ul>
|
||||
</div>
|
34
src/templates/chatbox.html
Normal file
34
src/templates/chatbox.html
Normal file
@ -0,0 +1,34 @@
|
||||
<div class="box-flyout {[if (minimized) {]} minimized {[}]}"
|
||||
{[if (!minimized) {]} style="height: {{height}}px" {[}]}>
|
||||
<div class="dragresize dragresize-tm" {[ if (minimized) { ]} style="display:none" {[ } ]}></div>
|
||||
<div class="chat-head chat-head-chatbox">
|
||||
<div class="chat-head-message-count">0</div>
|
||||
<a class="close-chatbox-button icon-close"></a>
|
||||
<a class="toggle-chatbox-button
|
||||
{[ if (minimized) { ]} icon-plus {[ } ]}
|
||||
{[ if (!minimized) { ]} icon-minus {[ } ]}
|
||||
"></a>
|
||||
<div class="chat-title">
|
||||
{[ if (url) { ]}
|
||||
<a href="{{url}}" target="_blank" class="user">
|
||||
{[ } ]}
|
||||
{{ fullname }}
|
||||
{[ if (url) { ]}
|
||||
</a>
|
||||
{[ } ]}
|
||||
</div>
|
||||
<p class="user-custom-message"><p/>
|
||||
</div>
|
||||
<div class="chat-body" {[ if (minimized) { ]} style="display:none" {[ } ]}>
|
||||
<div class="chat-content"></div>
|
||||
<form class="sendXMPPMessage" action="" method="post">
|
||||
{[ if (show_toolbar) { ]}
|
||||
<ul class="chat-toolbar no-text-select"></ul>
|
||||
{[ } ]}
|
||||
<textarea
|
||||
type="text"
|
||||
class="chat-textarea"
|
||||
placeholder="{{label_personal_message}}"/>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
18
src/templates/chatroom.html
Normal file
18
src/templates/chatroom.html
Normal file
@ -0,0 +1,18 @@
|
||||
<div class="box-flyout {[if (minimized) {]} minimized {[}]}"
|
||||
{[if (!minimized) {]} style="height: {{height}}px" {[}]}>
|
||||
<div class="dragresize dragresize-tm" {[ if (minimized) { ]} style="display:none" {[ } ]}></div>
|
||||
<div class="chat-head chat-head-chatroom">
|
||||
<div class="chat-head-message-count">0</div>
|
||||
<a class="close-chatbox-button icon-close"></a>
|
||||
<a class="toggle-chatbox-button
|
||||
{[ if (minimized) { ]} icon-plus {[ } ]}
|
||||
{[ if (!minimized) { ]} icon-minus {[ } ]}
|
||||
"></a>
|
||||
<a class="configure-chatroom-button icon-wrench" style="display:none"></a>
|
||||
<div class="chat-title"> {{ name }} </div>
|
||||
<p class="chatroom-topic"><p/>
|
||||
</div>
|
||||
<div class="chat-body" {[ if (minimized) { ]} style="display:none" {[ } ]}>
|
||||
<span class="spinner centered"/>
|
||||
</div>
|
||||
</div>
|
1
src/templates/chatrooms_tab.html
Normal file
1
src/templates/chatrooms_tab.html
Normal file
@ -0,0 +1 @@
|
||||
<li><a class="s" href="#chatrooms">{{label_rooms}}</a></li>
|
4
src/templates/choose_status.html
Normal file
4
src/templates/choose_status.html
Normal file
@ -0,0 +1,4 @@
|
||||
<dl id="target" class="dropdown">
|
||||
<dt id="fancy-xmpp-status-select" class="fancy-dropdown"></dt>
|
||||
<dd><ul class="xmpp-status-menu"></ul></dd>
|
||||
</dl>
|
1
src/templates/contacts.html
Normal file
1
src/templates/contacts.html
Normal file
@ -0,0 +1 @@
|
||||
<dt id="xmpp-contacts">{{label_contacts}}</dt>
|
10
src/templates/contacts_panel.html
Normal file
10
src/templates/contacts_panel.html
Normal file
@ -0,0 +1,10 @@
|
||||
<form class="set-xmpp-status" action="" method="post">
|
||||
<span id="xmpp-status-holder">
|
||||
<select id="select-xmpp-status" style="display:none">
|
||||
<option value="online">{{label_online}}</option>
|
||||
<option value="dnd">{{label_busy}}</option>
|
||||
<option value="away">{{label_away}}</option>
|
||||
<option value="offline">{{label_offline}}</option>
|
||||
</select>
|
||||
</span>
|
||||
</form>
|
1
src/templates/contacts_tab.html
Normal file
1
src/templates/contacts_tab.html
Normal file
@ -0,0 +1 @@
|
||||
<li><a class="s current" href="#users">{{label_contacts}}</a></li>
|
8
src/templates/controlbox.html
Normal file
8
src/templates/controlbox.html
Normal file
@ -0,0 +1,8 @@
|
||||
<div class="box-flyout" style="height: {{height}}px">
|
||||
<div class="dragresize dragresize-tm"></div>
|
||||
<div class="chat-head controlbox-head">
|
||||
<ul id="controlbox-tabs"></ul>
|
||||
<a class="close-chatbox-button icon-close"></a>
|
||||
</div>
|
||||
<div class="controlbox-panes"></div>
|
||||
</div>
|
2
src/templates/controlbox_toggle.html
Normal file
2
src/templates/controlbox_toggle.html
Normal file
@ -0,0 +1,2 @@
|
||||
<span class="conn-feedback">{{label_toggle}}</span>
|
||||
<span style="display: none" id="online-count">(0)</span>
|
1
src/templates/field.html
Normal file
1
src/templates/field.html
Normal file
@ -0,0 +1 @@
|
||||
<field var="{{name}}"><value>{{value}}</value></field>
|
1
src/templates/form_checkbox.html
Normal file
1
src/templates/form_checkbox.html
Normal file
@ -0,0 +1 @@
|
||||
<label>{{label}}<input name="{{name}}" type="{{type}}" {{checked}}></label>
|
1
src/templates/form_input.html
Normal file
1
src/templates/form_input.html
Normal file
@ -0,0 +1 @@
|
||||
<label>{{label}}<input name="{{name}}" type="{{type}}" value="{{value}}"></label>
|
1
src/templates/form_select.html
Normal file
1
src/templates/form_select.html
Normal file
@ -0,0 +1 @@
|
||||
<label>{{label}}<select name="{{name}}">{{options}}</select></label>
|
1
src/templates/info.html
Normal file
1
src/templates/info.html
Normal file
@ -0,0 +1 @@
|
||||
<div class="chat-info">{{message}}</div>
|
7
src/templates/login_panel.html
Normal file
7
src/templates/login_panel.html
Normal file
@ -0,0 +1,7 @@
|
||||
<form id="converse-login">
|
||||
<label>{{label_username}}</label>
|
||||
<input type="username" name="jid">
|
||||
<label>{{label_password}}</label>
|
||||
<input type="password" name="password">
|
||||
<input class="login-submit" type="submit" value="{{label_login}}">
|
||||
</form">
|
1
src/templates/login_tab.html
Normal file
1
src/templates/login_tab.html
Normal file
@ -0,0 +1 @@
|
||||
<li><a class="current" href="#login">{{label_sign_in}}</a></li>
|
4
src/templates/message.html
Normal file
4
src/templates/message.html
Normal file
@ -0,0 +1,4 @@
|
||||
<div class="chat-message {{extra_classes}}">
|
||||
<span class="chat-message-{{sender}}">{{time}} {{username}}: </span>
|
||||
<span class="chat-message-content">{{message}}</span>
|
||||
</div>
|
1
src/templates/new_day.html
Normal file
1
src/templates/new_day.html
Normal file
@ -0,0 +1 @@
|
||||
<time class="chat-date" datetime="{{isodate}}">{{datestring}}</time>
|
11
src/templates/occupant.html
Normal file
11
src/templates/occupant.html
Normal file
@ -0,0 +1,11 @@
|
||||
<li class="{{role}}"
|
||||
{[ if (role === "moderator") { ]}
|
||||
title="{{desc_moderator}}"
|
||||
{[ } ]}
|
||||
{[ if (role === "participant") { ]}
|
||||
title="{{desc_participant}}"
|
||||
{[ } ]}
|
||||
{[ if (role === "visitor") { ]}
|
||||
title="{{desc_visitor}}"
|
||||
{[ } ]}
|
||||
>{{nick}}</li>
|
1
src/templates/pending_contact.html
Normal file
1
src/templates/pending_contact.html
Normal file
@ -0,0 +1 @@
|
||||
<span>{{fullname}}</span> <a class="remove-xmpp-contact icon-remove" title="{{desc_remove}}" href="#"></a>
|
1
src/templates/pending_contacts.html
Normal file
1
src/templates/pending_contacts.html
Normal file
@ -0,0 +1 @@
|
||||
<dt id="pending-xmpp-contacts">{{label_pending_contacts}}</dt>
|
3
src/templates/requesting_contact.html
Normal file
3
src/templates/requesting_contact.html
Normal file
@ -0,0 +1,3 @@
|
||||
<div>{{fullname}}</div>
|
||||
<button type="button" class="accept-xmpp-request">{{label_accept}}</button>
|
||||
<button type="button" class="decline-xmpp-request">{{label_decline}}</button>
|
1
src/templates/requesting_contacts.html
Normal file
1
src/templates/requesting_contacts.html
Normal file
@ -0,0 +1 @@
|
||||
<dt id="xmpp-contact-requests">{{label_contact_requests}}</dt>
|
42
src/templates/room_description.html
Normal file
42
src/templates/room_description.html
Normal file
@ -0,0 +1,42 @@
|
||||
<!-- FIXME: check markup in mockup -->
|
||||
<div class="room-info">
|
||||
<p class="room-info"><strong>{{label_desc}}</strong> {{desc}}</p>
|
||||
<p class="room-info"><strong>{{label_occ}}</strong> {{occ}}</p>
|
||||
<p class="room-info"><strong>{{label_features}}</strong>
|
||||
<ul>
|
||||
{[ if (passwordprotected) { ]}
|
||||
<li class="room-info locked">{{label_requires_auth}}</li>
|
||||
{[ } ]}
|
||||
{[ if (hidden) { ]}
|
||||
<li class="room-info">{{label_hidden}}</li>
|
||||
{[ } ]}
|
||||
{[ if (membersonly) { ]}
|
||||
<li class="room-info">{{label_requires_invite}}</li>
|
||||
{[ } ]}
|
||||
{[ if (moderated) { ]}
|
||||
<li class="room-info">{{label_moderated}}</li>
|
||||
{[ } ]}
|
||||
{[ if (nonanonymous) { ]}
|
||||
<li class="room-info">{{label_non_anon}}</li>
|
||||
{[ } ]}
|
||||
{[ if (open) { ]}
|
||||
<li class="room-info">{{label_open_room}}</li>
|
||||
{[ } ]}
|
||||
{[ if (persistent) { ]}
|
||||
<li class="room-info">{{label_permanent_room}}</li>
|
||||
{[ } ]}
|
||||
{[ if (publicroom) { ]}
|
||||
<li class="room-info">{{label_public}}</li>
|
||||
{[ } ]}
|
||||
{[ if (semianonymous) { ]}
|
||||
<li class="room-info">{{label_semi_anon}}</li>
|
||||
{[ } ]}
|
||||
{[ if (temporary) { ]}
|
||||
<li class="room-info">{{label_temp_room}}</li>
|
||||
{[ } ]}
|
||||
{[ if (unmoderated) { ]}
|
||||
<li class="room-info">{{label_unmoderated}}</li>
|
||||
{[ } ]}
|
||||
</ul>
|
||||
</p>
|
||||
</div>
|
6
src/templates/room_item.html
Normal file
6
src/templates/room_item.html
Normal file
@ -0,0 +1,6 @@
|
||||
<dd class="available-chatroom">
|
||||
<a class="open-room" data-room-jid="{{jid}}"
|
||||
title="{{open_title}}" href="#">{{name}}</a>
|
||||
<a class="room-info icon-room-info" data-room-jid="{{jid}}"
|
||||
title="{{info_title}}" href="#"> </a>
|
||||
</dd>
|
11
src/templates/room_panel.html
Normal file
11
src/templates/room_panel.html
Normal file
@ -0,0 +1,11 @@
|
||||
<form class="add-chatroom" action="" method="post">
|
||||
<input type="text" name="chatroom" class="new-chatroom-name"
|
||||
placeholder="{{label_room_name}}"/>
|
||||
<input type="text" name="nick" class="new-chatroom-nick"
|
||||
placeholder="{{label_nickname}}"/>
|
||||
<input type="{{server_input_type}}" name="server" class="new-chatroom-server"
|
||||
placeholder="{{label_server}}"/>
|
||||
<input type="submit" name="join" value="{{label_join}}"/>
|
||||
<input type="button" name="show" id="show-rooms" value="{{label_show_rooms}}"/>
|
||||
</form>
|
||||
<dl id="available-chatrooms"></dl>
|
2
src/templates/roster_item.html
Normal file
2
src/templates/roster_item.html
Normal file
@ -0,0 +1,2 @@
|
||||
<a class="open-chat" title="{{desc_chat}}" href="#"><span class="icon-{{chat_status}}" title="{{desc_status}}"></span>{{fullname}}</a>
|
||||
<a class="remove-xmpp-contact icon-remove" title="{{desc_remove}}" href="#"></a>
|
9
src/templates/search_contact.html
Normal file
9
src/templates/search_contact.html
Normal file
@ -0,0 +1,9 @@
|
||||
<li>
|
||||
<form class="search-xmpp-contact">
|
||||
<input type="text"
|
||||
name="identifier"
|
||||
class="username"
|
||||
placeholder="{{label_contact_name}}"/>
|
||||
<button type="submit">{{label_search}}</button>
|
||||
</form>
|
||||
<li>
|
1
src/templates/select_option.html
Normal file
1
src/templates/select_option.html
Normal file
@ -0,0 +1 @@
|
||||
<option value="{{value}}">{{label}}</option>
|
6
src/templates/status_option.html
Normal file
6
src/templates/status_option.html
Normal file
@ -0,0 +1,6 @@
|
||||
<li>
|
||||
<a href="#" class="{{ value }}" data-value="{{ value }}">
|
||||
<span class="icon-{{ value }}"></span>
|
||||
{{ text }}
|
||||
</a>
|
||||
</li>
|
53
src/templates/toolbar.html
Normal file
53
src/templates/toolbar.html
Normal file
@ -0,0 +1,53 @@
|
||||
{[ if (show_emoticons) { ]}
|
||||
<li class="toggle-smiley icon-happy" title="Insert a smilery">
|
||||
<ul>
|
||||
<li><a class="icon-smiley" href="#" data-emoticon=":)"></a></li>
|
||||
<li><a class="icon-wink" href="#" data-emoticon=";)"></a></li>
|
||||
<li><a class="icon-grin" href="#" data-emoticon=":D"></a></li>
|
||||
<li><a class="icon-tongue" href="#" data-emoticon=":P"></a></li>
|
||||
<li><a class="icon-cool" href="#" data-emoticon="8)"></a></li>
|
||||
<li><a class="icon-evil" href="#" data-emoticon=">:)"></a></li>
|
||||
<li><a class="icon-confused" href="#" data-emoticon=":S"></a></li>
|
||||
<li><a class="icon-wondering" href="#" data-emoticon=":\"></a></li>
|
||||
<li><a class="icon-angry" href="#" data-emoticon=">:("></a></li>
|
||||
<li><a class="icon-sad" href="#" data-emoticon=":("></a></li>
|
||||
<li><a class="icon-shocked" href="#" data-emoticon=":O"></a></li>
|
||||
<li><a class="icon-thumbs-up" href="#" data-emoticon="(^.^)b"></a></li>
|
||||
<li><a class="icon-heart" href="#" data-emoticon="<3"></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
{[ } ]}
|
||||
{[ if (show_call_button) { ]}
|
||||
<li><a class="toggle-call icon-phone" title="Start a call"></a></li>
|
||||
{[ } ]}
|
||||
{[ if (allow_otr) { ]}
|
||||
<li class="toggle-otr {{otr_status_class}}" title="{{otr_tooltip}}">
|
||||
<span class="chat-toolbar-text">{{otr_translated_status}}</span>
|
||||
{[ if (otr_status == UNENCRYPTED) { ]}
|
||||
<span class="icon-unlocked"></span>
|
||||
{[ } ]}
|
||||
{[ if (otr_status == UNVERIFIED) { ]}
|
||||
<span class="icon-lock"></span>
|
||||
{[ } ]}
|
||||
{[ if (otr_status == VERIFIED) { ]}
|
||||
<span class="icon-lock"></span>
|
||||
{[ } ]}
|
||||
{[ if (otr_status == FINISHED) { ]}
|
||||
<span class="icon-unlocked"></span>
|
||||
{[ } ]}
|
||||
<ul>
|
||||
{[ if (otr_status == UNENCRYPTED) { ]}
|
||||
<li><a class="start-otr" href="#">{{label_start_encrypted_conversation}}</a></li>
|
||||
{[ } ]}
|
||||
{[ if (otr_status != UNENCRYPTED) { ]}
|
||||
<li><a class="start-otr" href="#">{{label_refresh_encrypted_conversation}}</a></li>
|
||||
<li><a class="end-otr" href="#">{{label_end_encrypted_conversation}}</a></li>
|
||||
<li><a class="auth-otr" data-scheme="smp" href="#">{{label_verify_with_smp}}</a></li>
|
||||
{[ } ]}
|
||||
{[ if (otr_status == UNVERIFIED) { ]}
|
||||
<li><a class="auth-otr" data-scheme="fingerprint" href="#">{{label_verify_with_fingerprints}}</a></li>
|
||||
{[ } ]}
|
||||
<li><a href="http://www.cypherpunks.ca/otr/help/3.2.0/levels.php" target="_blank">{{label_whats_this}}</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
{[ } ]}
|
@ -8,6 +8,7 @@
|
||||
<link rel="stylesheet" type="text/css" href="components/jasmine/src/html/jasmine.css">
|
||||
<link rel="stylesheet" type="text/css" media="screen" href="stylesheets/stylesheet.css">
|
||||
<link rel="stylesheet" type="text/css" media="screen" href="converse.css">
|
||||
<script src="main.js"></script>
|
||||
<script data-main="tests_main" src="components/requirejs/require.js"></script>
|
||||
</head>
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
var i, chatbox;
|
||||
for (i=converse.chatboxes.models.length-1; i>-1; i--) {
|
||||
chatbox = converse.chatboxes.models[i];
|
||||
converse.chatboxesview.views[chatbox.get('id')].closeChat();
|
||||
converse.chatboxviews.get(chatbox.get('id')).closeChat();
|
||||
}
|
||||
return this;
|
||||
};
|
||||
@ -22,17 +22,17 @@
|
||||
var i, chatbox, num_chatboxes = converse.chatboxes.models.length;
|
||||
for (i=num_chatboxes-1; i>-1; i--) {
|
||||
chatbox = converse.chatboxes.models[i];
|
||||
converse.chatboxesview.views[chatbox.get('id')].closeChat();
|
||||
converse.chatboxesview.views[chatbox.get('id')].$el.remove();
|
||||
converse.chatboxviews.get(chatbox.get('id')).closeChat();
|
||||
converse.chatboxviews.get(chatbox.get('id')).$el.remove();
|
||||
}
|
||||
converse.chatboxesview.views.controlbox.closeChat();
|
||||
converse.chatboxesview.views.controlbox.$el.remove();
|
||||
converse.chatboxviews.get('controlbox').closeChat();
|
||||
converse.chatboxviews.get('controlbox').$el.remove();
|
||||
return this;
|
||||
};
|
||||
|
||||
utils.initConverse = function () {
|
||||
converse.chatboxes = new converse.ChatBoxes();
|
||||
converse.chatboxesview = new converse.ChatBoxesView({model: converse.chatboxes});
|
||||
converse.chatboxviews = new converse.ChatBoxViews({model: converse.chatboxes});
|
||||
converse.onConnected();
|
||||
};
|
||||
|
||||
@ -42,68 +42,59 @@
|
||||
};
|
||||
|
||||
utils.openControlBox = function () {
|
||||
var toggle = $(".toggle-online-users");
|
||||
if (!$("#controlbox").is(':visible')) {
|
||||
$('.toggle-online-users').click();
|
||||
if (!toggle.is(':visible')) {
|
||||
toggle.show(toggle.click);
|
||||
} else {
|
||||
toggle.click();
|
||||
}
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
utils.closeControlBox = function () {
|
||||
if ($("#controlbox").is(':visible')) {
|
||||
$('.toggle-online-users').click();
|
||||
$("#controlbox").find(".close-chatbox-button").click();
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
utils.removeControlBox = function () {
|
||||
converse.controlboxtoggle.show();
|
||||
$('#controlbox').remove();
|
||||
};
|
||||
|
||||
utils.openContactsPanel = function () {
|
||||
var cbview = converse.chatboxesview.views.controlbox;
|
||||
var cbview = converse.chatboxviews.get('controlbox');
|
||||
var $tabs = cbview.$el.find('#controlbox-tabs');
|
||||
$tabs.find('li').first().find('a').click();
|
||||
};
|
||||
|
||||
utils.openRoomsPanel = function () {
|
||||
var cbview = converse.chatboxesview.views.controlbox;
|
||||
var cbview = converse.chatboxviews.get('controlbox');
|
||||
var $tabs = cbview.$el.find('#controlbox-tabs');
|
||||
$tabs.find('li').last().find('a').click();
|
||||
};
|
||||
|
||||
utils.openChatBoxes = function (amount) {
|
||||
var i = 0, jid;
|
||||
var i = 0, jid, views = [];
|
||||
for (i; i<amount; i++) {
|
||||
jid = mock.cur_names[i].replace(' ','.').toLowerCase() + '@localhost';
|
||||
converse.rosterview.rosteritemviews[jid].openChat(mock.event);
|
||||
views[i] = converse.rosterview.get(jid).openChat(mock.event);
|
||||
}
|
||||
return views;
|
||||
};
|
||||
|
||||
utils.openChatBoxFor = function (jid) {
|
||||
return converse.rosterview.rosteritemviews[jid].openChat(mock.event);
|
||||
return converse.rosterview.get(jid).openChat(mock.event);
|
||||
};
|
||||
|
||||
utils.clearChatBoxMessages = function (jid) {
|
||||
var view = converse.chatboxesview.views[jid];
|
||||
var view = converse.chatboxviews.get(jid);
|
||||
view.$el.find('.chat-content').empty();
|
||||
view.model.messages.reset().localStorage._clear();
|
||||
};
|
||||
|
||||
utils.createNewChatRoom = function (room, nick) {
|
||||
var controlbox_was_visible = $("#controlbox").is(':visible');
|
||||
utils.openControlBox();
|
||||
utils.openRoomsPanel();
|
||||
var roomspanel = converse.chatboxesview.views.controlbox.roomspanel;
|
||||
var $input = roomspanel.$el.find('input.new-chatroom-name');
|
||||
var $nick = roomspanel.$el.find('input.new-chatroom-nick');
|
||||
var $server = roomspanel.$el.find('input.new-chatroom-server');
|
||||
$input.val('lounge');
|
||||
$nick.val('dummy');
|
||||
$server.val('muc.localhost');
|
||||
roomspanel.$el.find('form').submit();
|
||||
if (!controlbox_was_visible) {
|
||||
utils.closeControlBox();
|
||||
}
|
||||
view.model.messages.reset();
|
||||
view.model.messages.localStorage._clear();
|
||||
};
|
||||
|
||||
utils.createCurrentContacts = function () {
|
||||
|
122
tests_main.js
122
tests_main.js
@ -1,88 +1,14 @@
|
||||
require.config({
|
||||
paths: {
|
||||
"jquery": "components/jquery/jquery",
|
||||
"locales": "locale/locales",
|
||||
"jquery.tinysort": "components/tinysort/src/jquery.tinysort",
|
||||
"underscore": "components/underscore/underscore",
|
||||
"backbone": "components/backbone/backbone",
|
||||
"backbone.localStorage": "components/backbone.localStorage/backbone.localStorage",
|
||||
"strophe": "components/strophe/strophe",
|
||||
"strophe.muc": "components/strophe.muc/index",
|
||||
"strophe.roster": "components/strophe.roster/index",
|
||||
"strophe.vcard": "components/strophe.vcard/index",
|
||||
"strophe.disco": "components/strophe.disco/index",
|
||||
"salsa20": "components/otr/build/dep/salsa20",
|
||||
"bigint": "src/bigint",
|
||||
"crypto.core": "components/otr/vendor/cryptojs/core",
|
||||
"crypto.enc-base64": "components/otr/vendor/cryptojs/enc-base64",
|
||||
"crypto.md5": "components/crypto-js-evanvosberg/src/md5",
|
||||
"crypto.evpkdf": "components/crypto-js-evanvosberg/src/evpkdf",
|
||||
"crypto.cipher-core": "components/otr/vendor/cryptojs/cipher-core",
|
||||
"crypto.aes": "components/otr/vendor/cryptojs/aes",
|
||||
"crypto.sha1": "components/otr/vendor/cryptojs/sha1",
|
||||
"crypto.sha256": "components/otr/vendor/cryptojs/sha256",
|
||||
"crypto.hmac": "components/otr/vendor/cryptojs/hmac",
|
||||
"crypto.pad-nopadding": "components/otr/vendor/cryptojs/pad-nopadding",
|
||||
"crypto.mode-ctr": "components/otr/vendor/cryptojs/mode-ctr",
|
||||
"crypto": "src/crypto",
|
||||
"eventemitter": "components/otr/build/dep/eventemitter",
|
||||
"otr": "components/otr/build/otr",
|
||||
"converse-dependencies": "src/deps-full",
|
||||
// Extra test dependencies
|
||||
"mock": "tests/mock",
|
||||
"utils": "tests/utils",
|
||||
"jasmine": "components/jasmine/lib/jasmine-core/jasmine",
|
||||
"jasmine-html": "components/jasmine/lib/jasmine-core/jasmine-html",
|
||||
"jasmine-console-reporter": "node_modules/jasmine-reporters/src/jasmine.console_reporter",
|
||||
"jasmine-junit-reporter": "node_modules/jasmine-reporters/src/jasmine.junit_reporter"
|
||||
},
|
||||
|
||||
// define module dependencies for modules not using define
|
||||
shim: {
|
||||
'backbone': {
|
||||
//These script dependencies should be loaded before loading
|
||||
//backbone.js
|
||||
deps: [
|
||||
'underscore',
|
||||
'jquery'
|
||||
],
|
||||
//Once loaded, use the global 'Backbone' as the
|
||||
//module value.
|
||||
exports: 'Backbone'
|
||||
},
|
||||
'underscore': { exports: '_' },
|
||||
'crypto.aes': { deps: ['crypto.cipher-core'] },
|
||||
'crypto.cipher-core': { deps: ['crypto.enc-base64', 'crypto.evpkdf'] },
|
||||
'crypto.enc-base64': { deps: ['crypto.core'] },
|
||||
'crypto.evpkdf': { deps: ['crypto.md5'] },
|
||||
'crypto.hmac': { deps: ['crypto.core'] },
|
||||
'crypto.md5': { deps: ['crypto.core'] },
|
||||
'crypto.mode-ctr': { deps: ['crypto.cipher-core'] },
|
||||
'crypto.pad-nopadding': { deps: ['crypto.cipher-core'] },
|
||||
'crypto.sha1': { deps: ['crypto.core'] },
|
||||
'crypto.sha256': { deps: ['crypto.core'] },
|
||||
'jquery.tinysort': { deps: ['jquery'] },
|
||||
'strophe': { deps: ['jquery'] },
|
||||
'strophe.disco': { deps: ['strophe'] },
|
||||
'strophe.muc': { deps: ['strophe', 'jquery'] },
|
||||
'strophe.roster': { deps: ['strophe'] },
|
||||
'strophe.vcard': { deps: ['strophe'] },
|
||||
|
||||
// Extra test dependencies
|
||||
'jasmine-html': {
|
||||
deps: ['jasmine'],
|
||||
exports: 'jasmine'
|
||||
},
|
||||
'jasmine-console-reporter': {
|
||||
deps: ['jasmine-html'],
|
||||
exports: 'jasmine'
|
||||
},
|
||||
'jasmine-junit-reporter': {
|
||||
deps: ['jasmine-html'],
|
||||
exports: 'jasmine'
|
||||
}
|
||||
}
|
||||
});
|
||||
// Extra test dependencies
|
||||
config.paths.mock = "tests/mock";
|
||||
config.paths.utils = "tests/utils";
|
||||
config.paths.jasmine = "components/jasmine/lib/jasmine-core/jasmine";
|
||||
config.paths["jasmine-html"] = "components/jasmine/lib/jasmine-core/jasmine-html";
|
||||
config.paths["console-runner"] = "node_modules/phantom-jasmine/lib/console-runner";
|
||||
config.shim['jasmine-html'] = {
|
||||
deps: ['jasmine'],
|
||||
exports: 'jasmine'
|
||||
};
|
||||
require.config(config);
|
||||
|
||||
// Polyfill 'bind' which is not available in phantomjs < 2.0
|
||||
if (!Function.prototype.bind) {
|
||||
@ -91,8 +17,8 @@ if (!Function.prototype.bind) {
|
||||
// closest thing possible to the ECMAScript 5 internal IsCallable function
|
||||
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
|
||||
}
|
||||
var aArgs = Array.prototype.slice.call(arguments, 1),
|
||||
fToBind = this,
|
||||
var aArgs = Array.prototype.slice.call(arguments, 1),
|
||||
fToBind = this,
|
||||
fNOP = function () {},
|
||||
fBound = function () {
|
||||
return fToBind.apply(this instanceof fNOP && oThis ? this : oThis,
|
||||
@ -111,6 +37,7 @@ require([
|
||||
"jasmine-html"
|
||||
], function($, converse, mock, jasmine) {
|
||||
// Set up converse.js
|
||||
$.fx.off = true;
|
||||
window.converse_api = converse;
|
||||
window.localStorage.clear();
|
||||
converse.initialize({
|
||||
@ -128,12 +55,11 @@ require([
|
||||
var i;
|
||||
for (i=0, len=buf.length; i<len; i++) {
|
||||
buf[i] = Math.floor(Math.random()*256);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
require([
|
||||
"jasmine-console-reporter",
|
||||
"jasmine-junit-reporter",
|
||||
"console-runner",
|
||||
"spec/converse",
|
||||
"spec/otr",
|
||||
"spec/eventemitter",
|
||||
@ -146,19 +72,19 @@ require([
|
||||
|
||||
// Jasmine stuff
|
||||
var jasmineEnv = jasmine.getEnv();
|
||||
var reporter;
|
||||
if (/PhantomJS/.test(navigator.userAgent)) {
|
||||
jasmineEnv.addReporter(new jasmine.TrivialReporter());
|
||||
jasmineEnv.addReporter(new jasmine.JUnitXmlReporter('./test-reports/'));
|
||||
jasmineEnv.addReporter(new jasmine.ConsoleReporter());
|
||||
reporter = new jasmine.ConsoleReporter();
|
||||
window.console_reporter = reporter;
|
||||
jasmineEnv.addReporter(reporter);
|
||||
jasmineEnv.updateInterval = 0;
|
||||
} else {
|
||||
var htmlReporter = new jasmine.HtmlReporter();
|
||||
jasmineEnv.addReporter(htmlReporter);
|
||||
jasmineEnv.addReporter(new jasmine.ConsoleReporter());
|
||||
reporter = new jasmine.HtmlReporter();
|
||||
jasmineEnv.addReporter(reporter);
|
||||
jasmineEnv.specFilter = function(spec) {
|
||||
return htmlReporter.specFilter(spec);
|
||||
return reporter.specFilter(spec);
|
||||
};
|
||||
jasmineEnv.updateInterval = 100;
|
||||
jasmineEnv.updateInterval = 0;
|
||||
}
|
||||
jasmineEnv.execute();
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user