Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
converse.js
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
converse.js
Commits
52cabd0d
Commit
52cabd0d
authored
Oct 28, 2014
by
JC Brand
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'profiling'
parents
299fa033
25c18ee7
Changes
18
Show whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
1315 additions
and
800 deletions
+1315
-800
Gruntfile.js
Gruntfile.js
+5
-0
bower.json
bower.json
+1
-2
converse.js
converse.js
+108
-45
index.html
index.html
+7
-5
main.js
main.js
+7
-10
spec/chatbox.js
spec/chatbox.js
+32
-21
spec/controlbox.js
spec/controlbox.js
+429
-264
spec/profiling.js
spec/profiling.js
+71
-0
src/build-no-locales-no-otr.js
src/build-no-locales-no-otr.js
+2
-70
src/build-no-otr.js
src/build-no-otr.js
+2
-83
src/build-website-no-otr.js
src/build-website-no-otr.js
+2
-85
src/build-website.js
src/build-website.js
+2
-102
src/build.js
src/build.js
+2
-100
src/strophe.roster.js
src/strophe.roster.js
+447
-0
src/templates/roster.html
src/templates/roster.html
+2
-3
tests/main.js
tests/main.js
+153
-4
tests/mock.js
tests/mock.js
+32
-6
tests/utils.js
tests/utils.js
+11
-0
No files found.
Gruntfile.js
View file @
52cabd0d
...
...
@@ -99,10 +99,15 @@ module.exports = function(grunt) {
done
();
};
exec
(
'
./node_modules/requirejs/bin/r.js -o src/build.js &&
'
+
'
./node_modules/requirejs/bin/r.js -o src/build.js optimize=none out=builds/converse.js &&
'
+
'
./node_modules/requirejs/bin/r.js -o src/build-no-locales-no-otr.js &&
'
+
'
./node_modules/requirejs/bin/r.js -o src/build-no-locales-no-otr.js optimize=none out=builds/converse-no-locales-no-otr.js &&
'
+
'
./node_modules/requirejs/bin/r.js -o src/build-no-otr.js &&
'
+
'
./node_modules/requirejs/bin/r.js -o src/build-no-otr.js optimize=none out=builds/converse-no-otr.js &&
'
+
'
./node_modules/requirejs/bin/r.js -o src/build-website-no-otr.js &&
'
+
'
./node_modules/requirejs/bin/r.js -o src/build-website.js
'
,
callback
);
// XXX: It might be possible to not have separate build config files. For example:
// 'r.js -o src/build.js paths.converse-dependencies=src/deps-no-otr paths.locales=locale/nolocales out=builds/converse-no-locales-no-otr.min.js'
});
grunt
.
registerTask
(
'
minify
'
,
'
Create a new release
'
,
[
'
cssmin
'
,
'
jsmin
'
]);
...
...
bower.json
View file @
52cabd0d
...
...
@@ -16,7 +16,6 @@
"backbone.browserStorage"
:
"*"
,
"backbone.overview"
:
"*"
,
"strophe"
:
"~1.1.3"
,
"strophe.roster"
:
"https://raw.github.com/strophe/strophejs-plugins/b1f364eb6e854ffe844c57add38e885cfeb9b498/roster/strophe.roster.js"
,
"strophe.muc"
:
"https://raw.githubusercontent.com/strophe/strophejs-plugins/master/muc/strophe.muc.js"
,
"otr"
:
"0.2.12"
,
"crypto-js-evanvosberg"
:
"~3.1.2"
,
...
...
@@ -30,7 +29,7 @@
"bootstrapJS"
:
"https://raw.githubusercontent.com/jcbrand/bootstrap/7d96a5f60d26c67b5348b270a775518b96a702c8/dist/js/bootstrap.js"
,
"fontawesome"
:
"~4.1.0"
,
"typeahead.js"
:
"https://raw.githubusercontent.com/jcbrand/typeahead.js/eedfb10505dd3a20123d1fafc07c1352d83f0ab3/dist/typeahead.jquery.js"
,
"strophejs-plugins"
:
"
~0.0.4
"
"strophejs-plugins"
:
"
https://github.com/strophe/strophejs-plugins.git#a56421ff4ecf0807113ab48c46728715597df599
"
},
"exportsOverride"
:
{}
}
converse.js
View file @
52cabd0d
...
...
@@ -541,6 +541,7 @@
};
this
.
clearSession
=
function
()
{
this
.
roster
.
browserStorage
.
_clear
();
this
.
session
.
browserStorage
.
_clear
();
// XXX: this should perhaps go into the beforeunload handler
converse
.
chatboxes
.
get
(
'
controlbox
'
).
save
({
'
connected
'
:
false
});
...
...
@@ -1935,8 +1936,16 @@
b64_sha1
(
'
converse.roster.groups
'
+
converse
.
bare_jid
));
converse
.
rosterview
=
new
converse
.
RosterView
({
model
:
rostergroups
});
this
.
contactspanel
.
$el
.
append
(
converse
.
rosterview
.
$el
);
// TODO:
// See if we shouldn't also fetch the roster here... otherwise
// the roster is always populated by the rosterHandler method,
// which appears to be a less economic way.
// i.e. from what it seems, only groups are fetched from
// browserStorage, and no contacts.
// XXX: Make sure that if fetch is called, we don't sort on
// each item add...
// converse.roster.fetch()
converse
.
rosterview
.
render
().
fetch
().
update
();
converse
.
connection
.
roster
.
get
(
function
()
{});
return
this
;
},
...
...
@@ -3212,6 +3221,10 @@
'
status
'
:
''
},
attributes
);
this
.
set
(
attrs
);
},
showInRoster
:
function
()
{
return
(
!
converse
.
show_only_online_users
||
this
.
get
(
'
chat_status
'
)
===
'
online
'
);
}
});
...
...
@@ -3226,24 +3239,12 @@
},
initialize
:
function
()
{
this
.
model
.
on
(
"
change
"
,
this
.
onChange
,
this
);
this
.
model
.
on
(
"
change
"
,
this
.
render
,
this
);
this
.
model
.
on
(
"
remove
"
,
this
.
remove
,
this
);
this
.
model
.
on
(
"
destroy
"
,
this
.
remove
,
this
);
this
.
model
.
on
(
"
open
"
,
this
.
openChat
,
this
);
},
onChange
:
function
()
{
if
(
converse
.
show_only_online_users
)
{
if
(
this
.
model
.
get
(
'
chat_status
'
)
!==
'
online
'
)
{
this
.
$el
.
hide
();
}
else
{
this
.
$el
.
show
();
}
}
else
{
this
.
render
();
}
},
openChat
:
function
(
ev
)
{
if
(
ev
&&
ev
.
preventDefault
)
{
ev
.
preventDefault
();
}
// XXX: Can this.model.attributes be used here, instead of
...
...
@@ -3293,6 +3294,12 @@
},
render
:
function
()
{
if
(
!
this
.
model
.
showInRoster
())
{
this
.
$el
.
hide
();
return
this
;
}
else
if
(
this
.
$el
[
0
].
style
.
display
===
"
none
"
)
{
this
.
$el
.
show
();
}
var
item
=
this
.
model
,
ask
=
item
.
get
(
'
ask
'
),
chat_status
=
item
.
get
(
'
chat_status
'
),
...
...
@@ -3356,13 +3363,13 @@
this
.
RosterContacts
=
Backbone
.
Collection
.
extend
({
model
:
converse
.
RosterContact
,
comparator
:
function
(
contact1
,
contact2
)
{
var
name1
=
contact1
.
get
(
'
fullname
'
).
toLowerCase
()
;
var
name1
,
name2
;
var
status1
=
contact1
.
get
(
'
chat_status
'
)
||
'
offline
'
;
var
name2
=
contact2
.
get
(
'
fullname
'
).
toLowerCase
();
var
status2
=
contact2
.
get
(
'
chat_status
'
)
||
'
offline
'
;
if
(
STATUS_WEIGHTS
[
status1
]
===
STATUS_WEIGHTS
[
status2
])
{
name1
=
contact1
.
get
(
'
fullname
'
).
toLowerCase
();
name2
=
contact2
.
get
(
'
fullname
'
).
toLowerCase
();
return
name1
<
name2
?
-
1
:
(
name1
>
name2
?
1
:
0
);
}
else
{
return
STATUS_WEIGHTS
[
status1
]
<
STATUS_WEIGHTS
[
status2
]
?
-
1
:
1
;
...
...
@@ -3370,15 +3377,13 @@
},
subscribeToSuggestedItems
:
function
(
msg
)
{
$
(
msg
).
find
(
'
item
'
).
each
(
function
()
{
$
(
msg
).
find
(
'
item
'
).
each
(
function
(
i
,
items
)
{
var
$this
=
$
(
this
),
jid
=
$this
.
attr
(
'
jid
'
),
action
=
$this
.
attr
(
'
action
'
),
fullname
=
$this
.
attr
(
'
name
'
);
if
(
action
===
'
add
'
)
{
converse
.
connection
.
roster
.
add
(
jid
,
fullname
,
[],
function
(
iq
)
{
converse
.
connection
.
roster
.
subscribe
(
jid
,
null
,
converse
.
xmppstatus
.
get
(
'
fullname
'
));
});
}
});
return
true
;
...
...
@@ -3486,7 +3491,8 @@
rosterHandler
:
function
(
items
,
item
)
{
converse
.
emit
(
'
roster
'
,
items
);
this
.
clearCache
(
items
);
_
.
each
(
items
,
function
(
item
,
index
,
items
)
{
var
new_items
=
item
?
[
item
]
:
items
;
_
.
each
(
new_items
,
function
(
item
,
index
,
items
)
{
if
(
this
.
isSelf
(
item
.
jid
))
{
return
;
}
var
model
=
this
.
get
(
item
.
jid
);
if
(
!
model
)
{
...
...
@@ -3503,7 +3509,7 @@
groups
:
item
.
groups
,
jid
:
item
.
jid
,
subscription
:
item
.
subscription
});
}
,
{
sort
:
false
}
);
}
else
{
if
((
item
.
subscription
===
'
none
'
)
&&
(
item
.
ask
===
null
))
{
// This user is no longer in our roster
...
...
@@ -3686,11 +3692,13 @@
var
view
=
new
converse
.
RosterContactView
({
model
:
contact
});
this
.
add
(
contact
.
get
(
'
id
'
),
view
);
view
=
this
.
positionContact
(
contact
).
render
();
if
(
contact
.
showInRoster
())
{
if
(
this
.
model
.
get
(
'
state
'
)
===
CLOSED
)
{
view
.
$el
.
hide
();
this
.
$el
.
show
();
if
(
view
.
$el
[
0
].
style
.
display
!==
"
none
"
)
{
view
.
$el
.
hide
();
}
if
(
this
.
$el
[
0
].
style
.
display
===
"
none
"
)
{
this
.
$el
.
show
();
}
}
else
{
this
.
show
();
if
(
this
.
$el
[
0
].
style
.
display
!==
"
block
"
)
{
this
.
show
();
}
}
}
},
...
...
@@ -3712,6 +3720,9 @@
},
show
:
function
()
{
// FIXME: There's a bug here, if show_only_online_users is true
// Possible solution, get the group, call _.each and check
// showInRoster
this
.
$el
.
nextUntil
(
'
dt
'
).
addBack
().
show
();
},
...
...
@@ -3729,7 +3740,7 @@
if
(
q
.
length
===
0
)
{
if
(
this
.
model
.
get
(
'
state
'
)
===
OPENED
)
{
this
.
model
.
contacts
.
each
(
$
.
proxy
(
function
(
item
)
{
if
(
!
(
converse
.
show_only_online_users
&&
item
.
get
(
'
chat_status
'
)
===
'
online
'
))
{
if
(
item
.
showInRoster
(
))
{
this
.
get
(
item
.
get
(
'
id
'
)).
$el
.
show
();
}
},
this
));
...
...
@@ -3849,16 +3860,20 @@
converse
.
roster
.
on
(
"
remove
"
,
this
.
update
,
this
);
this
.
model
.
on
(
"
add
"
,
this
.
onGroupAdd
,
this
);
this
.
model
.
on
(
"
reset
"
,
this
.
reset
,
this
);
this
.
$roster
=
$
(
'
<dl class="roster-contacts" style="display: none;"></dl>
'
);
},
update
:
function
()
{
update
:
_
.
debounce
(
function
()
{
var
$count
=
$
(
'
#online-count
'
);
$count
.
text
(
'
(
'
+
converse
.
roster
.
getNumOnlineContacts
()
+
'
)
'
);
if
(
!
$count
.
is
(
'
:visible
'
))
{
$count
.
show
();
}
if
(
this
.
$roster
.
parent
().
length
===
0
)
{
this
.
$el
.
append
(
this
.
$roster
.
show
());
}
return
this
.
showHideFilter
();
},
},
converse
.
animate
?
100
:
0
),
render
:
function
()
{
this
.
$el
.
html
(
converse
.
templates
.
roster
({
...
...
@@ -3871,10 +3886,47 @@
fetch
:
function
()
{
this
.
model
.
fetch
({
silent
:
true
,
success
:
$
.
proxy
(
this
.
positionFetchedGroups
,
this
)
silent
:
true
,
// We use the success handler to handle groups that were added,
// we need to first have all groups before positionFetchedGroups
// will work properly.
success
:
$
.
proxy
(
function
(
collection
,
resp
,
options
)
{
if
(
collection
.
length
!==
0
)
{
this
.
positionFetchedGroups
(
collection
,
resp
,
options
);
}
converse
.
roster
.
fetch
({
add
:
true
,
success
:
function
(
collection
)
{
// XXX: Bit of a hack.
// strophe.roster expects .get to be called for
// every page load so that its "items" attr
// gets populated.
// This is very inefficient for large rosters,
// and we already have the roster cached in
// sessionStorage.
// Therefore we manually populate the "items"
// attr.
// Ideally we should eventually replace
// strophe.roster with something better.
if
(
collection
.
length
>
0
)
{
collection
.
each
(
function
(
item
)
{
converse
.
connection
.
roster
.
items
.
push
({
name
:
item
.
get
(
'
fullname
'
),
jid
:
item
.
get
(
'
jid
'
),
subscription
:
item
.
get
(
'
subscription
'
),
ask
:
item
.
get
(
'
ask
'
),
groups
:
item
.
get
(
'
groups
'
),
resources
:
item
.
get
(
'
resources
'
)
});
});
converse
.
initial_presence_sent
=
1
;
converse
.
xmppstatus
.
sendPresence
();
}
else
{
converse
.
connection
.
roster
.
get
();
}
}
});
},
this
)
});
converse
.
roster
.
fetch
({
add
:
true
});
return
this
;
},
...
...
@@ -3942,7 +3994,7 @@
// Don't hide if user is currently filtering.
return
;
}
if
(
this
.
$
(
'
.roster-contacts
'
)
.
hasScrollBar
())
{
if
(
this
.
$
roster
.
hasScrollBar
())
{
if
(
!
visible
)
{
$filter
.
show
();
$type
.
show
();
...
...
@@ -3957,6 +4009,7 @@
reset
:
function
()
{
converse
.
roster
.
reset
();
this
.
removeAll
();
this
.
$roster
=
$
(
'
<dl class="roster-contacts" style="display: none;"></dl>
'
);
this
.
render
().
update
();
return
this
;
},
...
...
@@ -3964,13 +4017,24 @@
registerRosterHandler
:
function
()
{
// Register handlers that depend on the roster
converse
.
connection
.
roster
.
registerCallback
(
$
.
proxy
(
converse
.
roster
.
rosterHandler
,
converse
.
roster
)
,
null
,
'
presence
'
,
null
);
$
.
proxy
(
converse
.
roster
.
rosterHandler
,
converse
.
roster
)
);
},
registerRosterXHandler
:
function
()
{
var
t
=
0
;
converse
.
connection
.
addHandler
(
$
.
proxy
(
converse
.
roster
.
subscribeToSuggestedItems
,
converse
.
roster
),
function
(
msg
)
{
window
.
setTimeout
(
function
()
{
converse
.
connection
.
flush
();
$
.
proxy
(
converse
.
roster
.
subscribeToSuggestedItems
,
converse
.
roster
)(
msg
);
},
t
);
t
+=
$
(
msg
).
find
(
'
item
'
).
length
*
250
;
return
true
;
},
'
http://jabber.org/protocol/rosterx
'
,
'
message
'
,
null
);
},
...
...
@@ -4047,7 +4111,7 @@
this
.
add
(
group
.
get
(
'
name
'
),
view
.
render
());
}
if
(
idx
===
0
)
{
this
.
$
(
'
.roster-contacts
'
)
.
append
(
view
.
$el
);
this
.
$
roster
.
append
(
view
.
$el
);
}
else
{
this
.
appendGroup
(
view
);
}
...
...
@@ -4058,13 +4122,14 @@
/* Place the group's DOM element in the correct alphabetical
* position amongst the other groups in the roster.
*/
var
index
=
this
.
model
.
indexOf
(
view
.
model
);
var
$groups
=
this
.
$roster
.
find
(
'
.roster-group
'
),
index
=
$groups
.
length
?
this
.
model
.
indexOf
(
view
.
model
)
:
0
;
if
(
index
===
0
)
{
this
.
$
(
'
.roster-contacts
'
)
.
prepend
(
view
.
$el
);
this
.
$
roster
.
prepend
(
view
.
$el
);
}
else
if
(
index
==
(
this
.
model
.
length
-
1
))
{
this
.
appendGroup
(
view
);
}
else
{
$
(
this
.
$
(
'
.roster-group
'
)
.
eq
(
index
)).
before
(
view
.
$el
);
$
(
$groups
.
eq
(
index
)).
before
(
view
.
$el
);
}
return
this
;
},
...
...
@@ -4072,7 +4137,7 @@
appendGroup
:
function
(
view
)
{
/* Add the group at the bottom of the roster
*/
var
$last
=
this
.
$
(
'
.roster-group
'
).
last
();
var
$last
=
this
.
$
roster
.
find
(
'
.roster-group
'
).
last
();
var
$siblings
=
$last
.
siblings
(
'
dd
'
);
if
(
$siblings
.
length
>
0
)
{
$siblings
.
last
().
after
(
view
.
$el
);
...
...
@@ -4563,8 +4628,6 @@
sid
=
this
.
session
.
get
(
'
sid
'
);
jid
=
this
.
session
.
get
(
'
jid
'
);
if
(
rid
&&
jid
&&
sid
)
{
// We have the necessary tokens for resuming a session
rid
+=
1
;
this
.
session
.
save
({
rid
:
rid
});
// The RID needs to be increased with each request.
this
.
connection
.
attach
(
jid
,
sid
,
rid
,
this
.
onConnect
);
}
else
if
(
this
.
prebind
)
{
...
...
index.html
View file @
52cabd0d
...
...
@@ -229,7 +229,6 @@
<script
type=
"text/javascript"
>
try
{
var
pageTracker
=
_gat
.
_getTracker
(
"
UA-2128260-8
"
);
pageTracker
.
_trackPageview
();
}
catch
(
err
)
{}
</script>
<script>
// Configuration loaded, so safe to make other require calls.
require
([
'
converse
'
],
function
(
converse
)
{
(
function
()
{
/* XXX: This function initializes jquery.easing for the https://conversejs.org
...
...
@@ -255,14 +254,17 @@
})();
converse
.
initialize
({
allow_otr
:
true
,
auto_list_rooms
:
false
,
auto_subscribe
:
false
,
bosh_service_url
:
'
https://bind.conversejs.org
'
,
// Please use this connection manager only for testing purposes
i18n
:
locales
.
en
,
// Refer to ./locale/locales.js to see which locales are supported
hide_muc_server
:
false
,
i18n
:
locales
[
'
en
'
],
// Refer to ./locale/locales.js to see which locales are supported
keepalive
:
true
,
play_sounds
:
true
,
prebind
:
fals
e
,
roster_groups
:
tru
e
,
show_controlbox_by_default
:
true
,
debug
:
true
,
roster_groups
:
true
xhr_user_search
:
false
});
});
</script>
...
...
main.js
View file @
52cabd0d
config
=
{
require
.
config
(
{
baseUrl
:
'
.
'
,
paths
:
{
"
backbone
"
:
"
components/backbone/backbone
"
,
...
...
@@ -17,7 +17,7 @@ config = {
"
strophe
"
:
"
components/strophe/strophe
"
,
"
strophe.disco
"
:
"
components/strophejs-plugins/disco/strophe.disco
"
,
"
strophe.muc
"
:
"
components/strophe.muc/index
"
,
"
strophe.roster
"
:
"
components/strophe.roster/index
"
,
"
strophe.roster
"
:
"
src/strophe.roster
"
,
"
strophe.vcard
"
:
"
components/strophejs-plugins/vcard/strophe.vcard
"
,
"
text
"
:
'
components/requirejs-text/text
'
,
"
tpl
"
:
'
components/requirejs-tpl-jcbrand/tpl
'
,
...
...
@@ -139,16 +139,13 @@ config = {
'
crypto.sha1
'
:
{
deps
:
[
'
crypto.core
'
]
},
'
crypto.sha256
'
:
{
deps
:
[
'
crypto.core
'
]
},
'
bigint
'
:
{
deps
:
[
'
crypto
'
]
},
'
strophe
'
:
{
exports
:
'
Strophe
'
},
'
strophe.disco
'
:
{
deps
:
[
'
strophe
'
]
},
'
strophe.muc
'
:
{
deps
:
[
'
strophe
'
]
},
'
strophe.roster
'
:
{
deps
:
[
'
strophe
'
]
},
'
strophe.vcard
'
:
{
deps
:
[
'
strophe
'
]
}
}
};
if
(
typeof
(
require
)
!==
'
undefined
'
)
{
require
.
config
(
config
);
require
([
"
jquery
"
,
"
converse
"
],
function
(
$
,
converse
)
{
});
require
([
"
converse
"
],
function
(
converse
)
{
window
.
converse
=
converse
;
});
}
});
spec/chatbox.js
View file @
52cabd0d
...
...
@@ -57,6 +57,12 @@
expect
(
$
(
"
#conversejs .chatbox
"
).
length
).
toBe
(
1
);
// Controlbox is open
// Test that they can be trimmed
runs
(
$
.
proxy
(
function
()
{
converse
.
rosterview
.
update
();
// XXX: Hack to make sure $roster element is attaced.
},
this
));
waits
(
50
);
runs
(
$
.
proxy
(
function
()
{
// Test that they can be maximized again
var
online_contacts
=
this
.
rosterview
.
$el
.
find
(
'
dt.roster-group
'
).
siblings
(
'
dd.current-xmpp-contact
'
).
find
(
'
a.open-chat
'
);
for
(
i
=
0
;
i
<
online_contacts
.
length
;
i
++
)
{
$el
=
$
(
online_contacts
[
i
]);
...
...
@@ -71,9 +77,6 @@
expect
(
chatboxview
.
hide
).
toHaveBeenCalled
();
trimmedview
=
trimmed_chatboxes
.
get
(
jid
);
}
// Test that they can be maximized again
runs
(
$
.
proxy
(
function
()
{
var
key
=
this
.
chatboxviews
.
keys
()[
1
];
trimmedview
=
trimmed_chatboxes
.
get
(
key
);
chatbox
=
trimmedview
.
model
;
...
...
@@ -99,11 +102,19 @@
chatbox
=
test_utils
.
openChatBoxFor
(
contact_jid
);
chatboxview
=
this
.
chatboxviews
.
get
(
contact_jid
);
spyOn
(
chatboxview
,
'
focus
'
);
// Test that they can be trimmed
runs
(
$
.
proxy
(
function
()
{
converse
.
rosterview
.
update
();
// XXX: Hack to make sure $roster element is attaced.
},
this
));
waits
(
50
);
runs
(
$
.
proxy
(
function
()
{
$el
=
this
.
rosterview
.
$el
.
find
(
'
a.open-chat:contains("
'
+
chatbox
.
get
(
'
fullname
'
)
+
'
")
'
);
jid
=
$el
.
text
().
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
$el
.
click
();
expect
(
this
.
chatboxes
.
length
).
toEqual
(
2
);
expect
(
chatboxview
.
focus
).
toHaveBeenCalled
();
},
this
));
},
converse
));
it
(
"
can be saved to, and retrieved from, browserStorage
"
,
$
.
proxy
(
function
()
{
...
...
spec/controlbox.js
View file @
52cabd0d
...
...
@@ -145,7 +145,7 @@
subscription
:
'
both
'
});
converse
.
rosterview
.
update
();
// XXX: Will normally called as event handler
if
(
converse
.
rosterview
.
$
(
'
.roster-contacts
'
)
.
hasScrollBar
())
{
if
(
converse
.
rosterview
.
$
roster
.
hasScrollBar
())
{
expect
(
$filter
.
is
(
'
:visible
'
)).
toBeTruthy
();
}
else
{
expect
(
$filter
.
is
(
'
:visible
'
)).
toBeFalsy
();
...
...
@@ -154,11 +154,16 @@
},
converse
));
it
(
"
can be used to filter the contacts shown
"
,
function
()
{
converse
.
roster_groups
=
true
;
var
$filter
;
var
$roster
;
runs
(
function
()
{
_clearContacts
();
converse
.
roster_groups
=
true
;
utils
.
createGroupedContacts
();
var
$filter
=
converse
.
rosterview
.
$
(
'
.roster-filter
'
);
var
$roster
=
converse
.
rosterview
.
$
(
'
.roster-contacts
'
);
$filter
=
converse
.
rosterview
.
$
(
'
.roster-filter
'
);
$roster
=
converse
.
rosterview
.
$roster
;
});
waits
(
350
);
// Needed, due to debounce
runs
(
function
()
{
expect
(
$roster
.
find
(
'
dd:visible
'
).
length
).
toBe
(
15
);
expect
(
$roster
.
find
(
'
dt:visible
'
).
length
).
toBe
(
5
);
...
...
@@ -199,13 +204,19 @@
});
it
(
"
can be used to filter the groups shown
"
,
function
()
{
var
$filter
;
var
$roster
;
var
$type
;
runs
(
function
()
{
converse
.
roster_groups
=
true
;
_clearContacts
();
utils
.
createGroupedContacts
();
var
$filter
=
converse
.
rosterview
.
$
(
'
.roster-filter
'
);
var
$roster
=
converse
.
rosterview
.
$
(
'
.roster-contacts
'
)
;
var
$type
=
converse
.
rosterview
.
$
(
'
.filter-type
'
);
$filter
=
converse
.
rosterview
.
$
(
'
.roster-filter
'
);
$roster
=
converse
.
rosterview
.
$roster
;
$type
=
converse
.
rosterview
.
$
(
'
.filter-type
'
);
$type
.
val
(
'
groups
'
);
});
waits
(
350
);
// Needed, due to debounce
runs
(
function
()
{
expect
(
$roster
.
find
(
'
dd:visible
'
).
length
).
toBe
(
15
);
expect
(
$roster
.
find
(
'
dt:visible
'
).
length
).
toBe
(
5
);
...
...
@@ -242,7 +253,7 @@
_clearContacts
();
utils
.
createGroupedContacts
();
var
$filter
=
converse
.
rosterview
.
$
(
'
.roster-filter
'
);
var
$roster
=
converse
.
rosterview
.
$
(
'
.roster-contacts
'
)
;
var
$roster
=
converse
.
rosterview
.
$
roster
;
runs
(
function
()
{
$filter
.
val
(
"
xxx
"
);
$filter
.
trigger
(
'
keydown
'
);
...
...
@@ -267,6 +278,7 @@
});
it
(
"
can be used to organize existing contacts
"
,
$
.
proxy
(
function
()
{
runs
(
$
.
proxy
(
function
()
{
_clearContacts
();
spyOn
(
converse
,
'
emit
'
);
spyOn
(
this
.
rosterview
,
'
update
'
).
andCallThrough
();
...
...
@@ -274,6 +286,9 @@
utils
.
createContacts
(
'
pending
'
);
utils
.
createContacts
(
'
requesting
'
);
utils
.
createGroupedContacts
();
},
this
));
waits
(
50
);
// Needed, due to debounce
runs
(
$
.
proxy
(
function
()
{
// Check that the groups appear alphabetically and that
// requesting and pending contacts are last.
var
group_titles
=
$
.
map
(
this
.
rosterview
.
$el
.
find
(
'
dt
'
),
function
(
o
)
{
return
$
(
o
).
text
().
trim
();
});
...
...
@@ -292,15 +307,17 @@
var
names
=
$
.
map
(
$contacts
,
function
(
o
)
{
return
$
(
o
).
text
().
trim
();
});
expect
(
names
).
toEqual
(
_
.
clone
(
names
).
sort
());
},
converse
));
},
this
));
},
converse
));
it
(
"
can share contacts with other roster groups
"
,
$
.
proxy
(
function
()
{
var
groups
=
[
'
colleagues
'
,
'
friends
'
];
runs
(
$
.
proxy
(
function
()
{
_clearContacts
();
var
i
=
0
,
j
=
0
;
spyOn
(
converse
,
'
emit
'
);
spyOn
(
this
.
rosterview
,
'
update
'
).
andCallThrough
();
converse
.
rosterview
.
render
();
var
groups
=
[
'
colleagues
'
,
'
friends
'
];
for
(
i
=
0
;
i
<
mock
.
cur_names
.
length
;
i
++
)
{
this
.
roster
.
create
({
jid
:
mock
.
cur_names
[
i
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
,
...
...
@@ -310,13 +327,17 @@
fullname
:
mock
.
cur_names
[
i
]
});
}
},
this
));
waits
(
50
);
// Needed, due to debounce
runs
(
$
.
proxy
(
function
()
{
// Check that usernames appear alphabetically per group
_
.
each
(
groups
,
$
.
proxy
(
function
(
name
)
{
var
$contacts
=
this
.
rosterview
.
$
(
'
dt.roster-group[data-group="
'
+
name
+
'
"]
'
).
nextUntil
(
'
dt
'
,
'
dd
'
);
var
names
=
$
.
map
(
$contacts
,
function
(
o
)
{
return
$
(
o
).
text
().
trim
();
});
expect
(
names
).
toEqual
(
_
.
clone
(
names
).
sort
());
expect
(
names
.
length
).
toEqual
(
mock
.
cur_names
.
length
);
},
converse
));
},
this
));
},
this
));
},
converse
));
it
(
"
remembers whether it is closed or opened
"
,
$
.
proxy
(
function
()
{
...
...
@@ -361,8 +382,13 @@
}
it
(
"
can be collapsed under their own header
"
,
$
.
proxy
(
function
()
{
runs
(
function
()
{
_addContacts
();
});
waits
(
50
);
runs
(
$
.
proxy
(
function
()
{
checkHeaderToggling
.
apply
(
this
,
[
this
.
rosterview
.
get
(
'
Pending contacts
'
).
$el
]);
},
this
));
},
converse
));
it
(
"
can be added to the roster
"
,
$
.
proxy
(
function
()
{
...
...
@@ -385,7 +411,20 @@
},
converse
));
it
(
"
can be removed by the user
"
,
$
.
proxy
(
function
()
{
runs
(
$
.
proxy
(
function
()
{
_addContacts
();
},
this
));
waits
(
50
);
runs
(
$
.
proxy
(
function
()
{
/* FIXME: Monkepatch
* After refactoring the mock connection to use a
* Strophe.Connection object, these tests fail because "remove"
* function in strophe.roster (line 292) gets called and it
* then tries to actually remove the user which is not in the roster...
*/
var
old_remove
=
this
.
connection
.
roster
.
remove
;
this
.
connection
.
roster
.
remove
=
function
(
jid
,
callback
)
{
callback
();
};
var
name
=
mock
.
pend_names
[
0
];
var
jid
=
name
.
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
spyOn
(
window
,
'
confirm
'
).
andReturn
(
true
);
...
...
@@ -402,11 +441,19 @@
expect
(
this
.
connection
.
roster
.
unauthorize
).
toHaveBeenCalled
();
expect
(
this
.
rosterview
.
model
.
remove
).
toHaveBeenCalled
();
expect
(
converse
.
rosterview
.
$el
.
find
(
"
.pending-contact-name:contains('
"
+
name
+
"
')
"
).
length
).
toEqual
(
0
);
/* XXX Restore Monkeypatch */
this
.
connection
.
roster
.
remove
=
old_remove
;
},
this
));
},
converse
));
it
(
"
do not have a header if there aren't any
"
,
$
.
proxy
(
function
()
{
var
name
=
mock
.
pend_names
[
0
];
runs
(
$
.
proxy
(
function
()
{
_clearContacts
();
},
this
));
waits
(
50
);
runs
(
$
.
proxy
(
function
()
{
spyOn
(
window
,
'
confirm
'
).
andReturn
(
true
);
this
.
roster
.
create
({
jid
:
name
.
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
,
...
...
@@ -419,6 +466,7 @@
.
siblings
(
'
.remove-xmpp-contact
'
).
click
();
expect
(
window
.
confirm
).
toHaveBeenCalled
();
expect
(
this
.
rosterview
.
get
(
'
Pending contacts
'
).
$el
.
is
(
'
:visible
'
)).
toEqual
(
false
);
},
this
));
},
converse
));
...
...
@@ -467,8 +515,13 @@
};
it
(
"
can be collapsed under their own header
"
,
$
.
proxy
(
function
()
{
runs
(
function
()
{
_addContacts
();
});
waits
(
50
);
runs
(
$
.
proxy
(
function
()
{
checkHeaderToggling
.
apply
(
this
,
[
this
.
rosterview
.
$el
.
find
(
'
dt.roster-group
'
)]);
},
this
));
},
converse
));
it
(
"
will be hidden when appearing under a collapsed group
"
,
$
.
proxy
(
function
()
{
...
...
@@ -488,7 +541,11 @@
},
converse
));
it
(
"
can be added to the roster and they will be sorted alphabetically
"
,
$
.
proxy
(
function
()
{
runs
(
function
()
{
_clearContacts
();
});
waits
(
50
);
runs
(
$
.
proxy
(
function
()
{
var
i
,
t
;
spyOn
(
converse
,
'
emit
'
);
spyOn
(
this
.
rosterview
,
'
update
'
).
andCallThrough
();
...
...
@@ -504,10 +561,24 @@
// Check that they are sorted alphabetically
t
=
this
.
rosterview
.
$el
.
find
(
'
dt.roster-group
'
).
siblings
(
'
dd.current-xmpp-contact.offline
'
).
find
(
'
a.open-chat
'
).
text
();
expect
(
t
).
toEqual
(
mock
.
cur_names
.
slice
(
0
,
i
+
1
).
sort
().
join
(
''
));
},
this
));
},
converse
));
it
(
"
can be removed by the user
"
,
$
.
proxy
(
function
()
{
runs
(
function
()
{
_addContacts
();
});
waits
(
50
);
runs
(
$
.
proxy
(
function
()
{
/* FIXME: Monkepatch
* After refactoring the mock connection to use a
* Strophe.Connection object, these tests fail because "remove"
* function in strophe.roster (line 292) gets called and it
* then tries to actually remove the user which is not in the roster...
*/
var
old_remove
=
this
.
connection
.
roster
.
remove
;
this
.
connection
.
roster
.
remove
=
function
(
jid
,
callback
)
{
callback
();
};
var
name
=
mock
.
cur_names
[
0
];
var
jid
=
name
.
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
spyOn
(
window
,
'
confirm
'
).
andReturn
(
true
);
...
...
@@ -524,12 +595,20 @@
expect
(
this
.
connection
.
roster
.
unauthorize
).
toHaveBeenCalled
();
expect
(
this
.
rosterview
.
model
.
remove
).
toHaveBeenCalled
();
expect
(
converse
.
rosterview
.
$el
.
find
(
"
.open-chat:contains('
"
+
name
+
"
')
"
).
length
).
toEqual
(
0
);
/* XXX Restore Monkeypatch */
this
.
connection
.
roster
.
remove
=
old_remove
;
},
this
));
},
converse
));
it
(
"
do not have a header if there aren't any
"
,
$
.
proxy
(
function
()
{
var
name
=
mock
.
cur_names
[
0
];
runs
(
function
()
{
_clearContacts
();
});
waits
(
50
);
runs
(
$
.
proxy
(
function
()
{
spyOn
(
window
,
'
confirm
'
).
andReturn
(
true
);
this
.
roster
.
create
({
jid
:
name
.
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
,
...
...
@@ -542,10 +621,15 @@
.
siblings
(
'
.remove-xmpp-contact
'
).
click
();
expect
(
window
.
confirm
).
toHaveBeenCalled
();
expect
(
this
.
rosterview
.
$el
.
find
(
'
dt.roster-group
'
).
css
(
'
display
'
)).
toEqual
(
'
none
'
);
},
this
));
},
converse
));
it
(
"
can change their status to online and be sorted alphabetically
"
,
$
.
proxy
(
function
()
{
runs
(
function
()
{
_addContacts
();
});
waits
(
50
);
runs
(
$
.
proxy
(
function
()
{
var
jid
,
t
;
spyOn
(
converse
,
'
emit
'
);
spyOn
(
this
.
rosterview
,
'
update
'
).
andCallThrough
();
...
...
@@ -557,10 +641,15 @@
t
=
this
.
rosterview
.
$el
.
find
(
'
dt.roster-group
'
).
siblings
(
'
dd.current-xmpp-contact.online
'
).
find
(
'
a.open-chat
'
).
text
();
expect
(
t
).
toEqual
(
mock
.
cur_names
.
slice
(
0
,
i
+
1
).
sort
().
join
(
''
));
}
},
this
));
},
converse
));
it
(
"
can change their status to busy and be sorted alphabetically
"
,
$
.
proxy
(
function
()
{
runs
(
function
()
{
_addContacts
();
});
waits
(
50
);
runs
(
$
.
proxy
(
function
()
{
var
jid
,
t
;
spyOn
(
converse
,
'
emit
'
);
spyOn
(
this
.
rosterview
,
'
update
'
).
andCallThrough
();
...
...
@@ -572,10 +661,15 @@
t
=
this
.
rosterview
.
$el
.
find
(
'
dt.roster-group
'
).
siblings
(
'
dd.current-xmpp-contact.dnd
'
).
find
(
'
a.open-chat
'
).
text
();
expect
(
t
).
toEqual
(
mock
.
cur_names
.
slice
(
0
,
i
+
1
).
sort
().
join
(
''
));
}
},
this
));
},
converse
));
it
(
"
can change their status to away and be sorted alphabetically
"
,
$
.
proxy
(
function
()
{
runs
(
function
()
{
_addContacts
();
});
waits
(
50
);
runs
(
$
.
proxy
(
function
()
{
var
jid
,
t
;
spyOn
(
converse
,
'
emit
'
);
spyOn
(
this
.
rosterview
,
'
update
'
).
andCallThrough
();
...
...
@@ -587,10 +681,15 @@
t
=
this
.
rosterview
.
$el
.
find
(
'
dt.roster-group
'
).
siblings
(
'
dd.current-xmpp-contact.away
'
).
find
(
'
a.open-chat
'
).
text
();
expect
(
t
).
toEqual
(
mock
.
cur_names
.
slice
(
0
,
i
+
1
).
sort
().
join
(
''
));
}
},
this
));
},
converse
));
it
(
"
can change their status to xa and be sorted alphabetically
"
,
$
.
proxy
(
function
()
{
runs
(
function
()
{
_addContacts
();
});
waits
(
50
);
runs
(
$
.
proxy
(
function
()
{
var
jid
,
t
;
spyOn
(
converse
,
'
emit
'
);
spyOn
(
this
.
rosterview
,
'
update
'
).
andCallThrough
();
...
...
@@ -602,10 +701,15 @@
t
=
this
.
rosterview
.
$el
.
find
(
'
dt.roster-group
'
).
siblings
(
'
dd.current-xmpp-contact.xa
'
).
find
(
'
a.open-chat
'
).
text
();
expect
(
t
).
toEqual
(
mock
.
cur_names
.
slice
(
0
,
i
+
1
).
sort
().
join
(
''
));
}
},
this
));
},
converse
));
it
(
"
can change their status to unavailable and be sorted alphabetically
"
,
$
.
proxy
(
function
()
{
runs
(
function
()
{
_addContacts
();
});
waits
(
50
);
runs
(
$
.
proxy
(
function
()
{
var
jid
,
t
;
spyOn
(
converse
,
'
emit
'
);
spyOn
(
this
.
rosterview
,
'
update
'
).
andCallThrough
();
...
...
@@ -617,10 +721,15 @@
t
=
this
.
rosterview
.
$el
.
find
(
'
dt.roster-group
'
).
siblings
(
'
dd.current-xmpp-contact.unavailable
'
).
find
(
'
a.open-chat
'
).
text
();
expect
(
t
).
toEqual
(
mock
.
cur_names
.
slice
(
0
,
i
+
1
).
sort
().
join
(
''
));
}
},
this
));
},
converse
));
it
(
"
are ordered according to status: online, busy, away, xa, unavailable, offline
"
,
$
.
proxy
(
function
()
{
runs
(
function
()
{
_addContacts
();
});
waits
(
50
);
runs
(
$
.
proxy
(
function
()
{
var
i
;
for
(
i
=
0
;
i
<
3
;
i
++
)
{
jid
=
mock
.
cur_names
[
i
].
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
...
...
@@ -662,6 +771,7 @@
for
(
i
=
15
;
i
<
mock
.
cur_names
.
length
;
i
++
)
{
expect
(
$
(
contacts
[
i
]).
attr
(
'
class
'
).
split
(
'
'
,
1
)[
0
]).
toEqual
(
'
offline
'
);
}
},
this
));
},
converse
));
},
converse
));
...
...
@@ -713,6 +823,7 @@
it
(
"
do not have a header if there aren't any
"
,
$
.
proxy
(
function
()
{
converse
.
rosterview
.
model
.
reset
();
// We want to manually create users so that we can spy
var
name
=
mock
.
req_names
[
0
];
runs
(
$
.
proxy
(
function
()
{
spyOn
(
window
,
'
confirm
'
).
andReturn
(
true
);
this
.
roster
.
create
({
jid
:
name
.
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
,
...
...
@@ -721,12 +832,16 @@
requesting
:
true
,
fullname
:
name
});
},
this
));
waits
(
50
);
runs
(
$
.
proxy
(
function
()
{
expect
(
this
.
rosterview
.
get
(
'
Contact requests
'
).
$el
.
is
(
'
:visible
'
)).
toEqual
(
true
);
converse
.
rosterview
.
$el
.
find
(
"
.req-contact-name:contains('
"
+
name
+
"
')
"
)
.
siblings
(
'
.request-actions
'
)
.
find
(
'
.decline-xmpp-request
'
).
click
();
expect
(
window
.
confirm
).
toHaveBeenCalled
();
expect
(
this
.
rosterview
.
get
(
'
Contact requests
'
).
$el
.
is
(
'
:visible
'
)).
toEqual
(
false
);
},
this
));
},
converse
));
it
(
"
can be collapsed under their own header
"
,
$
.
proxy
(
function
()
{
...
...
@@ -750,20 +865,70 @@
it
(
"
can have their requests denied by the user
"
,
$
.
proxy
(
function
()
{
this
.
rosterview
.
model
.
reset
();
runs
(
$
.
proxy
(
function
()
{
spyOn
(
converse
,
'
emit
'
);
spyOn
(
this
.
connection
.
roster
,
'
unauthorize
'
);
spyOn
(
window
,
'
confirm
'
).
andReturn
(
true
);
utils
.
createContacts
(
'
requesting
'
).
openControlBox
();
converse
.
rosterview
.
update
();
// XXX: Hack to make sure $roster element is attaced.
},
this
));
waits
(
50
);
runs
(
$
.
proxy
(
function
()
{
var
name
=
mock
.
req_names
.
sort
()[
1
];
var
jid
=
name
.
replace
(
/ /g
,
'
.
'
).
toLowerCase
()
+
'
@localhost
'
;
converse
.
rosterview
.
$el
.
find
(
"
.req-contact-name:contains('
"
+
name
+
"
')
"
)
.
siblings
(
'
.request-actions
'
)
.
find
(
'
.decline-xmpp-request
'
).
click
();
},
this
));
waits
(
50
);
runs
(
$
.
proxy
(
function
()
{
expect
(
window
.
confirm
).
toHaveBeenCalled
();
expect
(
this
.
connection
.
roster
.
unauthorize
).
toHaveBeenCalled
();
// There should now be one less contact
expect
(
this
.
roster
.
length
).
toEqual
(
mock
.
req_names
.
length
-
1
);
},
this
));
},
converse
));
it
(
"
are persisted even if other contacts' change their presence
"
,
$
.
proxy
(
function
()
{
/* This is a regression test.
* https://github.com/jcbrand/converse.js/issues/262
*/
this
.
rosterview
.
model
.
reset
();
spyOn
(
this
.
roster
,
'
clearCache
'
).
andCallThrough
();
expect
(
this
.
roster
.
pluck
(
'
jid
'
).
length
).
toBe
(
0
);
var
stanza
=
$pres
({
from
:
'
data@enterprise/resource
'
,
type
:
'
subscribe
'
});
this
.
connection
.
_dataRecv
(
test_utils
.
createRequest
(
stanza
));
expect
(
this
.
roster
.
pluck
(
'
jid
'
).
length
).
toBe
(
1
);
expect
(
_
.
contains
(
this
.
roster
.
pluck
(
'
jid
'
),
'
data@enterprise
'
)).
toBeTruthy
();
// Taken from the spec
// http://xmpp.org/rfcs/rfc3921.html#rfc.section.7.3
stanza
=
$iq
({
to
:
this
.
connection
.
jid
,
type
:
'
result
'
,
id
:
'
roster_1
'
}).
c
(
'
query
'
,
{
xmlns
:
'
jabber:iq:roster
'
,
}).
c
(
'
item
'
,
{
jid
:
'
romeo@example.net
'
,
name
:
'
Romeo
'
,
subscription
:
'
both
'
}).
c
(
'
group
'
).
t
(
'
Friends
'
).
up
().
up
()
.
c
(
'
item
'
,
{
jid
:
'
mercutio@example.org
'
,
name
:
'
Mercutio
'
,
subscription
:
'
from
'
}).
c
(
'
group
'
).
t
(
'
Friends
'
).
up
().
up
()
.
c
(
'
item
'
,
{
jid
:
'
benvolio@example.org
'
,
name
:
'
Benvolio
'
,
subscription
:
'
both
'
}).
c
(
'
group
'
).
t
(
'
Friends
'
);
this
.
connection
.
roster
.
_onReceiveRosterSuccess
(
null
,
stanza
.
tree
());
expect
(
this
.
roster
.
clearCache
).
toHaveBeenCalled
();
expect
(
_
.
contains
(
this
.
roster
.
pluck
(
'
jid
'
),
'
data@enterprise
'
)).
toBeTruthy
();
},
converse
));
},
converse
));
describe
(
"
All Contacts
"
,
$
.
proxy
(
function
()
{
...
...
@@ -775,7 +940,7 @@
},
converse
));
it
(
"
are saved to, and can be retrieved from, browserStorage
"
,
$
.
proxy
(
function
()
{
var
new_attrs
,
old_attrs
,
attrs
,
old_roster
;
var
new_attrs
,
old_attrs
,
attrs
;
var
num_contacts
=
this
.
roster
.
length
;
new_roster
=
new
this
.
RosterContacts
();
// Roster items are yet to be fetched from browserStorage
...
...
spec/profiling.js
0 → 100644
View file @
52cabd0d
(
function
(
root
,
factory
)
{
define
([
"
jquery
"
,
"
mock
"
,
"
test_utils
"
],
function
(
$
,
mock
,
test_utils
)
{
return
factory
(
$
,
mock
,
test_utils
);
}
);
}
(
this
,
function
(
$
,
mock
,
test_utils
)
{
describe
(
"
Profiling
"
,
function
()
{
beforeEach
(
function
()
{
converse
.
connection
.
roster
.
items
=
[];
converse
.
connection
.
_changeConnectStatus
(
Strophe
.
Status
.
CONNECTED
);
});
xit
(
"
adds hundreds of contacts to the roster
"
,
$
.
proxy
(
function
()
{
converse
.
roster_groups
=
false
;
spyOn
(
this
.
roster
,
'
clearCache
'
).
andCallThrough
();
expect
(
this
.
roster
.
pluck
(
'
jid
'
).
length
).
toBe
(
0
);
var
stanza
=
$iq
({
to
:
this
.
connection
.
jid
,
type
:
'
result
'
,
id
:
'
roster_1
'
}).
c
(
'
query
'
,
{
xmlns
:
'
jabber:iq:roster
'
});
_
.
each
([
'
Friends
'
,
'
Colleagues
'
,
'
Family
'
,
'
Acquaintances
'
],
function
(
group
)
{
var
i
;
for
(
i
=
0
;
i
<
100
;
i
++
)
{
stanza
=
stanza
.
c
(
'
item
'
,
{
jid
:
Math
.
random
().
toString
().
replace
(
'
0.
'
,
''
)
+
'
@example.net
'
,
subscription
:
'
both
'
}).
c
(
'
group
'
).
t
(
group
).
up
().
up
();
}
});
this
.
connection
.
roster
.
_onReceiveRosterSuccess
(
null
,
stanza
.
tree
());
expect
(
this
.
roster
.
clearCache
).
toHaveBeenCalled
();
expect
(
this
.
roster
.
pluck
(
'
jid
'
).
length
).
toBe
(
400
);
},
converse
));
xit
(
"
adds hundreds of contacts to the roster, with roster groups
"
,
$
.
proxy
(
function
()
{
// converse.show_only_online_users = true;
converse
.
roster_groups
=
true
;
spyOn
(
this
.
roster
,
'
clearCache
'
).
andCallThrough
();
expect
(
this
.
roster
.
pluck
(
'
jid
'
).
length
).
toBe
(
0
);
var
stanza
=
$iq
({
to
:
this
.
connection
.
jid
,
type
:
'
result
'
,
id
:
'
roster_1
'
}).
c
(
'
query
'
,
{
xmlns
:
'
jabber:iq:roster
'
});
_
.
each
([
'
Friends
'
,
'
Colleagues
'
,
'
Family
'
,
'
Acquaintances
'
],
function
(
group
)
{
var
i
;
for
(
i
=
0
;
i
<
100
;
i
++
)
{
stanza
=
stanza
.
c
(
'
item
'
,
{
jid
:
Math
.
random
().
toString
().
replace
(
'
0.
'
,
''
)
+
'
@example.net
'
,
subscription
:
'
both
'
}).
c
(
'
group
'
).
t
(
group
).
up
().
up
();
}
});
this
.
connection
.
roster
.
_onReceiveRosterSuccess
(
null
,
stanza
.
tree
());
expect
(
this
.
roster
.
clearCache
).
toHaveBeenCalled
();
//expect(this.roster.pluck('jid').length).toBe(400);
},
converse
));
it
(
"
contacts in a very large roster change their statuses
"
,
$
.
proxy
(
function
()
{
},
converse
));
});
}));
src/build-no-locales-no-otr.js
View file @
52cabd0d
...
...
@@ -19,77 +19,9 @@
// be an unresolvable cyclic dependency.
'
jquery-private
'
:
{
'
jquery
'
:
'
jquery
'
}
},
mainConfigFile
:
'
../main.js
'
,
paths
:
{
"
backbone
"
:
"
components/backbone/backbone
"
,
"
backbone.browserStorage
"
:
"
components/backbone.browserStorage/backbone.browserStorage
"
,
"
backbone.overview
"
:
"
components/backbone.overview/backbone.overview
"
,
"
bootstrap
"
:
"
components/bootstrap/dist/js/bootstrap
"
,
// XXX: Only required for https://conversejs.org website
"
converse-dependencies
"
:
"
src/deps-no-otr
"
,
"
converse-templates
"
:
"
src/templates
"
,
"
eventemitter
"
:
"
components/otr/build/dep/eventemitter
"
,
"
jquery
"
:
"
components/jquery/dist/jquery
"
,
"
jquery-private
"
:
"
src/jquery-private
"
,
"
jquery.browser
"
:
"
components/jquery.browser/index
"
,
"
jquery.easing
"
:
"
components/jquery-easing-original/index
"
,
// XXX: Only required for https://conversejs.org website
"
moment
"
:
"
components/momentjs/moment
"
,
"
strophe
"
:
"
components/strophe/strophe
"
,
"
strophe.disco
"
:
"
components/strophe.disco/index
"
,
"
strophe.muc
"
:
"
components/strophe.muc/index
"
,
"
strophe.roster
"
:
"
components/strophe.roster/index
"
,
"
strophe.vcard
"
:
"
components/strophe.vcard/index
"
,
"
text
"
:
'
components/requirejs-text/text
'
,
"
tpl
"
:
'
components/requirejs-tpl-jcbrand/tpl
'
,
"
typeahead
"
:
"
components/typeahead.js/index
"
,
"
underscore
"
:
"
components/underscore/underscore
"
,
"
utils
"
:
"
src/utils
"
,
// Locales paths
"
locales
"
:
"
locale/nolocales
"
,
"
jed
"
:
"
components/jed/jed
"
,
// Templates
"
action
"
:
"
src/templates/action
"
,
"
add_contact_dropdown
"
:
"
src/templates/add_contact_dropdown
"
,
"
add_contact_form
"
:
"
src/templates/add_contact_form
"
,
"
change_status_message
"
:
"
src/templates/change_status_message
"
,
"
chat_status
"
:
"
src/templates/chat_status
"
,
"
chatarea
"
:
"
src/templates/chatarea
"
,
"
chatbox
"
:
"
src/templates/chatbox
"
,
"
chatroom
"
:
"
src/templates/chatroom
"
,
"
chatroom_password_form
"
:
"
src/templates/chatroom_password_form
"
,
"
chatroom_sidebar
"
:
"
src/templates/chatroom_sidebar
"
,
"
chatrooms_tab
"
:
"
src/templates/chatrooms_tab
"
,
"
chats_panel
"
:
"
src/templates/chats_panel
"
,
"
choose_status
"
:
"
src/templates/choose_status
"
,
"
contacts_panel
"
:
"
src/templates/contacts_panel
"
,
"
contacts_tab
"
:
"
src/templates/contacts_tab
"
,
"
controlbox
"
:
"
src/templates/controlbox
"
,
"
controlbox_toggle
"
:
"
src/templates/controlbox_toggle
"
,
"
field
"
:
"
src/templates/field
"
,
"
form_checkbox
"
:
"
src/templates/form_checkbox
"
,
"
form_input
"
:
"
src/templates/form_input
"
,
"
form_select
"
:
"
src/templates/form_select
"
,
"
group_header
"
:
"
src/templates/group_header
"
,
"
info
"
:
"
src/templates/info
"
,
"
login_panel
"
:
"
src/templates/login_panel
"
,
"
login_tab
"
:
"
src/templates/login_tab
"
,
"
message
"
:
"
src/templates/message
"
,
"
new_day
"
:
"
src/templates/new_day
"
,
"
occupant
"
:
"
src/templates/occupant
"
,
"
pending_contact
"
:
"
src/templates/pending_contact
"
,
"
pending_contacts
"
:
"
src/templates/pending_contacts
"
,
"
requesting_contact
"
:
"
src/templates/requesting_contact
"
,
"
requesting_contacts
"
:
"
src/templates/requesting_contacts
"
,
"
room_description
"
:
"
src/templates/room_description
"
,
"
room_item
"
:
"
src/templates/room_item
"
,
"
room_panel
"
:
"
src/templates/room_panel
"
,
"
roster
"
:
"
src/templates/roster
"
,
"
roster_item
"
:
"
src/templates/roster_item
"
,
"
search_contact
"
:
"
src/templates/search_contact
"
,
"
select_option
"
:
"
src/templates/select_option
"
,
"
status_option
"
:
"
src/templates/status_option
"
,
"
toggle_chats
"
:
"
src/templates/toggle_chats
"
,
"
toolbar
"
:
"
src/templates/toolbar
"
,
"
trimmed_chat
"
:
"
src/templates/trimmed_chat
"
"
locales
"
:
"
locale/nolocales
"
}
})
src/build-no-otr.js
View file @
52cabd0d
...
...
@@ -19,89 +19,8 @@
// be an unresolvable cyclic dependency.
'
jquery-private
'
:
{
'
jquery
'
:
'
jquery
'
}
},
mainConfigFile
:
'
../main.js
'
,
paths
:
{
"
backbone
"
:
"
components/backbone/backbone
"
,
"
backbone.browserStorage
"
:
"
components/backbone.browserStorage/backbone.browserStorage
"
,
"
backbone.overview
"
:
"
components/backbone.overview/backbone.overview
"
,
"
converse-dependencies
"
:
"
src/deps-no-otr
"
,
"
converse-templates
"
:
"
src/templates
"
,
"
eventemitter
"
:
"
components/otr/build/dep/eventemitter
"
,
"
jquery
"
:
"
components/jquery/dist/jquery
"
,
"
jquery-private
"
:
"
src/jquery-private
"
,
"
jquery.browser
"
:
"
components/jquery.browser/index
"
,
"
moment
"
:
"
components/momentjs/moment
"
,
"
strophe
"
:
"
components/strophe/strophe
"
,
"
strophe.disco
"
:
"
components/strophe.disco/index
"
,
"
strophe.muc
"
:
"
components/strophe.muc/index
"
,
"
strophe.roster
"
:
"
components/strophe.roster/index
"
,
"
strophe.vcard
"
:
"
components/strophe.vcard/index
"
,
"
text
"
:
'
components/requirejs-text/text
'
,
"
tpl
"
:
'
components/requirejs-tpl-jcbrand/tpl
'
,
"
typeahead
"
:
"
components/typeahead.js/index
"
,
"
underscore
"
:
"
components/underscore/underscore
"
,
"
utils
"
:
"
src/utils
"
,
// Locales paths
"
locales
"
:
"
locale/locales
"
,
"
jed
"
:
"
components/jed/jed
"
,
"
af
"
:
"
locale/af/LC_MESSAGES/af
"
,
"
de
"
:
"
locale/de/LC_MESSAGES/de
"
,
"
en
"
:
"
locale/en/LC_MESSAGES/en
"
,
"
es
"
:
"
locale/es/LC_MESSAGES/es
"
,
"
fr
"
:
"
locale/fr/LC_MESSAGES/fr
"
,
"
he
"
:
"
locale/he/LC_MESSAGES/he
"
,
"
hu
"
:
"
locale/hu/LC_MESSAGES/hu
"
,
"
id
"
:
"
locale/id/LC_MESSAGES/id
"
,
"
it
"
:
"
locale/it/LC_MESSAGES/it
"
,
"
ja
"
:
"
locale/ja/LC_MESSAGES/ja
"
,
"
nl
"
:
"
locale/nl/LC_MESSAGES/nl
"
,
"
pt_BR
"
:
"
locale/pt_BR/LC_MESSAGES/pt_BR
"
,
"
ru
"
:
"
locale/ru/LC_MESSAGES/ru
"
,
"
zh
"
:
"
locale/zh/LC_MESSAGES/zh
"
,
// Templates
"
action
"
:
"
src/templates/action
"
,
"
add_contact_dropdown
"
:
"
src/templates/add_contact_dropdown
"
,
"
add_contact_form
"
:
"
src/templates/add_contact_form
"
,
"
change_status_message
"
:
"
src/templates/change_status_message
"
,
"
chat_status
"
:
"
src/templates/chat_status
"
,
"
chatarea
"
:
"
src/templates/chatarea
"
,
"
chatbox
"
:
"
src/templates/chatbox
"
,
"
chatroom
"
:
"
src/templates/chatroom
"
,
"
chatroom_password_form
"
:
"
src/templates/chatroom_password_form
"
,
"
chatroom_sidebar
"
:
"
src/templates/chatroom_sidebar
"
,
"
chatrooms_tab
"
:
"
src/templates/chatrooms_tab
"
,
"
chats_panel
"
:
"
src/templates/chats_panel
"
,
"
choose_status
"
:
"
src/templates/choose_status
"
,
"
contacts_panel
"
:
"
src/templates/contacts_panel
"
,
"
contacts_tab
"
:
"
src/templates/contacts_tab
"
,
"
controlbox
"
:
"
src/templates/controlbox
"
,
"
controlbox_toggle
"
:
"
src/templates/controlbox_toggle
"
,
"
field
"
:
"
src/templates/field
"
,
"
form_checkbox
"
:
"
src/templates/form_checkbox
"
,
"
form_input
"
:
"
src/templates/form_input
"
,
"
form_select
"
:
"
src/templates/form_select
"
,
"
group_header
"
:
"
src/templates/group_header
"
,
"
info
"
:
"
src/templates/info
"
,
"
login_panel
"
:
"
src/templates/login_panel
"
,
"
login_tab
"
:
"
src/templates/login_tab
"
,
"
message
"
:
"
src/templates/message
"
,
"
new_day
"
:
"
src/templates/new_day
"
,
"
occupant
"
:
"
src/templates/occupant
"
,
"
pending_contact
"
:
"
src/templates/pending_contact
"
,
"
pending_contacts
"
:
"
src/templates/pending_contacts
"
,
"
requesting_contact
"
:
"
src/templates/requesting_contact
"
,
"
requesting_contacts
"
:
"
src/templates/requesting_contacts
"
,
"
room_description
"
:
"
src/templates/room_description
"
,
"
room_item
"
:
"
src/templates/room_item
"
,
"
room_panel
"
:
"
src/templates/room_panel
"
,
"
roster
"
:
"
src/templates/roster
"
,
"
roster_item
"
:
"
src/templates/roster_item
"
,
"
search_contact
"
:
"
src/templates/search_contact
"
,
"
select_option
"
:
"
src/templates/select_option
"
,
"
status_option
"
:
"
src/templates/status_option
"
,
"
toggle_chats
"
:
"
src/templates/toggle_chats
"
,
"
toolbar
"
:
"
src/templates/toolbar
"
,
"
trimmed_chat
"
:
"
src/templates/trimmed_chat
"
"
converse-dependencies
"
:
"
src/deps-no-otr
"
}
})
src/build-website-no-otr.js
View file @
52cabd0d
...
...
@@ -19,91 +19,8 @@
// be an unresolvable cyclic dependency.
'
jquery-private
'
:
{
'
jquery
'
:
'
jquery
'
}
},
mainConfigFile
:
'
../main.js
'
,
paths
:
{
"
backbone
"
:
"
components/backbone/backbone
"
,
"
backbone.browserStorage
"
:
"
components/backbone.browserStorage/backbone.browserStorage
"
,
"
backbone.overview
"
:
"
components/backbone.overview/backbone.overview
"
,
"
bootstrapJS
"
:
"
components/bootstrapJS/index
"
,
// XXX: Only required for https://conversejs.org website
"
converse-dependencies
"
:
"
src/deps-website-no-otr
"
,
"
converse-templates
"
:
"
src/templates
"
,
"
eventemitter
"
:
"
components/otr/build/dep/eventemitter
"
,
"
jquery
"
:
"
components/jquery/dist/jquery
"
,
"
jquery-private
"
:
"
src/jquery-private
"
,
"
jquery.browser
"
:
"
components/jquery.browser/index
"
,
"
jquery.easing
"
:
"
components/jquery-easing-original/index
"
,
// XXX: Only required for https://conversejs.org website
"
moment
"
:
"
components/momentjs/moment
"
,
"
strophe
"
:
"
components/strophe/strophe
"
,
"
strophe.disco
"
:
"
components/strophe.disco/index
"
,
"
strophe.muc
"
:
"
components/strophe.muc/index
"
,
"
strophe.roster
"
:
"
components/strophe.roster/index
"
,
"
strophe.vcard
"
:
"
components/strophe.vcard/index
"
,
"
text
"
:
'
components/requirejs-text/text
'
,
"
tpl
"
:
'
components/requirejs-tpl-jcbrand/tpl
'
,
"
typeahead
"
:
"
components/typeahead.js/index
"
,
"
underscore
"
:
"
components/underscore/underscore
"
,
"
utils
"
:
"
src/utils
"
,
// Locales paths
"
locales
"
:
"
locale/locales
"
,
"
jed
"
:
"
components/jed/jed
"
,
"
af
"
:
"
locale/af/LC_MESSAGES/af
"
,
"
de
"
:
"
locale/de/LC_MESSAGES/de
"
,
"
en
"
:
"
locale/en/LC_MESSAGES/en
"
,
"
es
"
:
"
locale/es/LC_MESSAGES/es
"
,
"
fr
"
:
"
locale/fr/LC_MESSAGES/fr
"
,
"
he
"
:
"
locale/he/LC_MESSAGES/he
"
,
"
hu
"
:
"
locale/hu/LC_MESSAGES/hu
"
,
"
id
"
:
"
locale/id/LC_MESSAGES/id
"
,
"
it
"
:
"
locale/it/LC_MESSAGES/it
"
,
"
ja
"
:
"
locale/ja/LC_MESSAGES/ja
"
,
"
nl
"
:
"
locale/nl/LC_MESSAGES/nl
"
,
"
pt_BR
"
:
"
locale/pt_BR/LC_MESSAGES/pt_BR
"
,
"
ru
"
:
"
locale/ru/LC_MESSAGES/ru
"
,
"
zh
"
:
"
locale/zh/LC_MESSAGES/zh
"
,
// Templates
"
action
"
:
"
src/templates/action
"
,
"
add_contact_dropdown
"
:
"
src/templates/add_contact_dropdown
"
,
"
add_contact_form
"
:
"
src/templates/add_contact_form
"
,
"
change_status_message
"
:
"
src/templates/change_status_message
"
,
"
chat_status
"
:
"
src/templates/chat_status
"
,
"
chatarea
"
:
"
src/templates/chatarea
"
,
"
chatbox
"
:
"
src/templates/chatbox
"
,
"
chatroom
"
:
"
src/templates/chatroom
"
,
"
chatroom_password_form
"
:
"
src/templates/chatroom_password_form
"
,
"
chatroom_sidebar
"
:
"
src/templates/chatroom_sidebar
"
,
"
chatrooms_tab
"
:
"
src/templates/chatrooms_tab
"
,
"
chats_panel
"
:
"
src/templates/chats_panel
"
,
"
choose_status
"
:
"
src/templates/choose_status
"
,
"
contacts_panel
"
:
"
src/templates/contacts_panel
"
,
"
contacts_tab
"
:
"
src/templates/contacts_tab
"
,
"
controlbox
"
:
"
src/templates/controlbox
"
,
"
controlbox_toggle
"
:
"
src/templates/controlbox_toggle
"
,
"
field
"
:
"
src/templates/field
"
,
"
form_checkbox
"
:
"
src/templates/form_checkbox
"
,
"
form_input
"
:
"
src/templates/form_input
"
,
"
form_select
"
:
"
src/templates/form_select
"
,
"
group_header
"
:
"
src/templates/group_header
"
,
"
info
"
:
"
src/templates/info
"
,
"
login_panel
"
:
"
src/templates/login_panel
"
,
"
login_tab
"
:
"
src/templates/login_tab
"
,
"
message
"
:
"
src/templates/message
"
,
"
new_day
"
:
"
src/templates/new_day
"
,
"
occupant
"
:
"
src/templates/occupant
"
,
"
pending_contact
"
:
"
src/templates/pending_contact
"
,
"
pending_contacts
"
:
"
src/templates/pending_contacts
"
,
"
requesting_contact
"
:
"
src/templates/requesting_contact
"
,
"
requesting_contacts
"
:
"
src/templates/requesting_contacts
"
,
"
room_description
"
:
"
src/templates/room_description
"
,
"
room_item
"
:
"
src/templates/room_item
"
,
"
room_panel
"
:
"
src/templates/room_panel
"
,
"
roster
"
:
"
src/templates/roster
"
,
"
roster_item
"
:
"
src/templates/roster_item
"
,
"
search_contact
"
:
"
src/templates/search_contact
"
,
"
select_option
"
:
"
src/templates/select_option
"
,
"
status_option
"
:
"
src/templates/status_option
"
,
"
toggle_chats
"
:
"
src/templates/toggle_chats
"
,
"
toolbar
"
:
"
src/templates/toolbar
"
,
"
trimmed_chat
"
:
"
src/templates/trimmed_chat
"
"
converse-dependencies
"
:
"
src/deps-website-no-otr
"
}
})
src/build-website.js
View file @
52cabd0d
...
...
@@ -19,108 +19,8 @@
// be an unresolvable cyclic dependency.
'
jquery-private
'
:
{
'
jquery
'
:
'
jquery
'
}
},
mainConfigFile
:
'
../main.js
'
,
paths
:
{
"
backbone
"
:
"
components/backbone/backbone
"
,
"
backbone.browserStorage
"
:
"
components/backbone.browserStorage/backbone.browserStorage
"
,
"
backbone.overview
"
:
"
components/backbone.overview/backbone.overview
"
,
"
bootstrapJS
"
:
"
components/bootstrapJS/index
"
,
// XXX: Only required for https://conversejs.org website
"
converse-dependencies
"
:
"
src/deps-website
"
,
"
converse-templates
"
:
"
src/templates
"
,
"
eventemitter
"
:
"
components/otr/build/dep/eventemitter
"
,
"
jquery
"
:
"
components/jquery/dist/jquery
"
,
"
jquery-private
"
:
"
src/jquery-private
"
,
"
jquery.browser
"
:
"
components/jquery.browser/index
"
,
"
jquery.easing
"
:
"
components/jquery-easing-original/index
"
,
// XXX: Only required for https://conversejs.org website
"
moment
"
:
"
components/momentjs/moment
"
,
"
strophe
"
:
"
components/strophe/strophe
"
,
"
strophe.disco
"
:
"
components/strophe.disco/index
"
,
"
strophe.muc
"
:
"
components/strophe.muc/index
"
,
"
strophe.roster
"
:
"
components/strophe.roster/index
"
,
"
strophe.vcard
"
:
"
components/strophe.vcard/index
"
,
"
text
"
:
'
components/requirejs-text/text
'
,
"
tpl
"
:
'
components/requirejs-tpl-jcbrand/tpl
'
,
"
typeahead
"
:
"
components/typeahead.js/index
"
,
"
underscore
"
:
"
components/underscore/underscore
"
,
"
utils
"
:
"
src/utils
"
,
// Off-the-record-encryption
"
bigint
"
:
"
src/bigint
"
,
"
crypto
"
:
"
src/crypto
"
,
"
crypto.aes
"
:
"
components/otr/vendor/cryptojs/aes
"
,
"
crypto.cipher-core
"
:
"
components/otr/vendor/cryptojs/cipher-core
"
,
"
crypto.core
"
:
"
components/otr/vendor/cryptojs/core
"
,
"
crypto.enc-base64
"
:
"
components/otr/vendor/cryptojs/enc-base64
"
,
"
crypto.evpkdf
"
:
"
components/crypto-js-evanvosberg/src/evpkdf
"
,
"
crypto.hmac
"
:
"
components/otr/vendor/cryptojs/hmac
"
,
"
crypto.md5
"
:
"
components/crypto-js-evanvosberg/src/md5
"
,
"
crypto.mode-ctr
"
:
"
components/otr/vendor/cryptojs/mode-ctr
"
,
"
crypto.pad-nopadding
"
:
"
components/otr/vendor/cryptojs/pad-nopadding
"
,
"
crypto.sha1
"
:
"
components/otr/vendor/cryptojs/sha1
"
,
"
crypto.sha256
"
:
"
components/otr/vendor/cryptojs/sha256
"
,
"
salsa20
"
:
"
components/otr/build/dep/salsa20
"
,
"
otr
"
:
"
src/otr
"
,
// Locales paths
"
locales
"
:
"
locale/locales
"
,
"
jed
"
:
"
components/jed/jed
"
,
"
af
"
:
"
locale/af/LC_MESSAGES/af
"
,
"
de
"
:
"
locale/de/LC_MESSAGES/de
"
,
"
en
"
:
"
locale/en/LC_MESSAGES/en
"
,
"
es
"
:
"
locale/es/LC_MESSAGES/es
"
,
"
fr
"
:
"
locale/fr/LC_MESSAGES/fr
"
,
"
he
"
:
"
locale/he/LC_MESSAGES/he
"
,
"
hu
"
:
"
locale/hu/LC_MESSAGES/hu
"
,
"
id
"
:
"
locale/id/LC_MESSAGES/id
"
,
"
it
"
:
"
locale/it/LC_MESSAGES/it
"
,
"
ja
"
:
"
locale/ja/LC_MESSAGES/ja
"
,
"
nl
"
:
"
locale/nl/LC_MESSAGES/nl
"
,
"
pt_BR
"
:
"
locale/pt_BR/LC_MESSAGES/pt_BR
"
,
"
ru
"
:
"
locale/ru/LC_MESSAGES/ru
"
,
"
zh
"
:
"
locale/zh/LC_MESSAGES/zh
"
,
// Templates
"
action
"
:
"
src/templates/action
"
,
"
add_contact_dropdown
"
:
"
src/templates/add_contact_dropdown
"
,
"
add_contact_form
"
:
"
src/templates/add_contact_form
"
,
"
change_status_message
"
:
"
src/templates/change_status_message
"
,
"
chat_status
"
:
"
src/templates/chat_status
"
,
"
chatarea
"
:
"
src/templates/chatarea
"
,
"
chatbox
"
:
"
src/templates/chatbox
"
,
"
chatroom
"
:
"
src/templates/chatroom
"
,
"
chatroom_password_form
"
:
"
src/templates/chatroom_password_form
"
,
"
chatroom_sidebar
"
:
"
src/templates/chatroom_sidebar
"
,
"
chatrooms_tab
"
:
"
src/templates/chatrooms_tab
"
,
"
chats_panel
"
:
"
src/templates/chats_panel
"
,
"
choose_status
"
:
"
src/templates/choose_status
"
,
"
contacts_panel
"
:
"
src/templates/contacts_panel
"
,
"
contacts_tab
"
:
"
src/templates/contacts_tab
"
,
"
controlbox
"
:
"
src/templates/controlbox
"
,
"
controlbox_toggle
"
:
"
src/templates/controlbox_toggle
"
,
"
field
"
:
"
src/templates/field
"
,
"
form_checkbox
"
:
"
src/templates/form_checkbox
"
,
"
form_input
"
:
"
src/templates/form_input
"
,
"
form_select
"
:
"
src/templates/form_select
"
,
"
group_header
"
:
"
src/templates/group_header
"
,
"
info
"
:
"
src/templates/info
"
,
"
login_panel
"
:
"
src/templates/login_panel
"
,
"
login_tab
"
:
"
src/templates/login_tab
"
,
"
message
"
:
"
src/templates/message
"
,
"
new_day
"
:
"
src/templates/new_day
"
,
"
occupant
"
:
"
src/templates/occupant
"
,
"
pending_contact
"
:
"
src/templates/pending_contact
"
,
"
pending_contacts
"
:
"
src/templates/pending_contacts
"
,
"
requesting_contact
"
:
"
src/templates/requesting_contact
"
,
"
requesting_contacts
"
:
"
src/templates/requesting_contacts
"
,
"
room_description
"
:
"
src/templates/room_description
"
,
"
room_item
"
:
"
src/templates/room_item
"
,
"
room_panel
"
:
"
src/templates/room_panel
"
,
"
roster
"
:
"
src/templates/roster
"
,
"
roster_item
"
:
"
src/templates/roster_item
"
,
"
search_contact
"
:
"
src/templates/search_contact
"
,
"
select_option
"
:
"
src/templates/select_option
"
,
"
status_option
"
:
"
src/templates/status_option
"
,
"
toggle_chats
"
:
"
src/templates/toggle_chats
"
,
"
toolbar
"
:
"
src/templates/toolbar
"
,
"
trimmed_chat
"
:
"
src/templates/trimmed_chat
"
"
converse-dependencies
"
:
"
src/deps-website
"
}
})
src/build.js
View file @
52cabd0d
...
...
@@ -19,106 +19,8 @@
// be an unresolvable cyclic dependency.
'
jquery-private
'
:
{
'
jquery
'
:
'
jquery
'
}
},
mainConfigFile
:
'
../main.js
'
,
paths
:
{
"
backbone
"
:
"
components/backbone/backbone
"
,
"
backbone.browserStorage
"
:
"
components/backbone.browserStorage/backbone.browserStorage
"
,
"
backbone.overview
"
:
"
components/backbone.overview/backbone.overview
"
,
"
converse-dependencies
"
:
"
src/deps-full
"
,
"
converse-templates
"
:
"
src/templates
"
,
"
eventemitter
"
:
"
components/otr/build/dep/eventemitter
"
,
"
jquery
"
:
"
components/jquery/dist/jquery
"
,
"
jquery-private
"
:
"
src/jquery-private
"
,
"
jquery.browser
"
:
"
components/jquery.browser/index
"
,
"
moment
"
:
"
components/momentjs/moment
"
,
"
strophe
"
:
"
components/strophe/strophe
"
,
"
strophe.disco
"
:
"
components/strophe.disco/index
"
,
"
strophe.muc
"
:
"
components/strophe.muc/index
"
,
"
strophe.roster
"
:
"
components/strophe.roster/index
"
,
"
strophe.vcard
"
:
"
components/strophe.vcard/index
"
,
"
text
"
:
'
components/requirejs-text/text
'
,
"
tpl
"
:
'
components/requirejs-tpl-jcbrand/tpl
'
,
"
typeahead
"
:
"
components/typeahead.js/index
"
,
"
underscore
"
:
"
components/underscore/underscore
"
,
"
utils
"
:
"
src/utils
"
,
// Off-the-record-encryption
"
bigint
"
:
"
src/bigint
"
,
"
crypto
"
:
"
src/crypto
"
,
"
crypto.aes
"
:
"
components/otr/vendor/cryptojs/aes
"
,
"
crypto.cipher-core
"
:
"
components/otr/vendor/cryptojs/cipher-core
"
,
"
crypto.core
"
:
"
components/otr/vendor/cryptojs/core
"
,
"
crypto.enc-base64
"
:
"
components/otr/vendor/cryptojs/enc-base64
"
,
"
crypto.evpkdf
"
:
"
components/crypto-js-evanvosberg/src/evpkdf
"
,
"
crypto.hmac
"
:
"
components/otr/vendor/cryptojs/hmac
"
,
"
crypto.md5
"
:
"
components/crypto-js-evanvosberg/src/md5
"
,
"
crypto.mode-ctr
"
:
"
components/otr/vendor/cryptojs/mode-ctr
"
,
"
crypto.pad-nopadding
"
:
"
components/otr/vendor/cryptojs/pad-nopadding
"
,
"
crypto.sha1
"
:
"
components/otr/vendor/cryptojs/sha1
"
,
"
crypto.sha256
"
:
"
components/otr/vendor/cryptojs/sha256
"
,
"
salsa20
"
:
"
components/otr/build/dep/salsa20
"
,
"
otr
"
:
"
src/otr
"
,
// Locales paths
"
locales
"
:
"
locale/locales
"
,
"
jed
"
:
"
components/jed/jed
"
,
"
af
"
:
"
locale/af/LC_MESSAGES/af
"
,
"
de
"
:
"
locale/de/LC_MESSAGES/de
"
,
"
en
"
:
"
locale/en/LC_MESSAGES/en
"
,
"
es
"
:
"
locale/es/LC_MESSAGES/es
"
,
"
fr
"
:
"
locale/fr/LC_MESSAGES/fr
"
,
"
he
"
:
"
locale/he/LC_MESSAGES/he
"
,
"
hu
"
:
"
locale/hu/LC_MESSAGES/hu
"
,
"
id
"
:
"
locale/id/LC_MESSAGES/id
"
,
"
it
"
:
"
locale/it/LC_MESSAGES/it
"
,
"
ja
"
:
"
locale/ja/LC_MESSAGES/ja
"
,
"
nl
"
:
"
locale/nl/LC_MESSAGES/nl
"
,
"
pt_BR
"
:
"
locale/pt_BR/LC_MESSAGES/pt_BR
"
,
"
ru
"
:
"
locale/ru/LC_MESSAGES/ru
"
,
"
zh
"
:
"
locale/zh/LC_MESSAGES/zh
"
,
// Templates
"
action
"
:
"
src/templates/action
"
,
"
add_contact_dropdown
"
:
"
src/templates/add_contact_dropdown
"
,
"
add_contact_form
"
:
"
src/templates/add_contact_form
"
,
"
change_status_message
"
:
"
src/templates/change_status_message
"
,
"
chat_status
"
:
"
src/templates/chat_status
"
,
"
chatarea
"
:
"
src/templates/chatarea
"
,
"
chatbox
"
:
"
src/templates/chatbox
"
,
"
chatroom
"
:
"
src/templates/chatroom
"
,
"
chatroom_password_form
"
:
"
src/templates/chatroom_password_form
"
,
"
chatroom_sidebar
"
:
"
src/templates/chatroom_sidebar
"
,
"
chatrooms_tab
"
:
"
src/templates/chatrooms_tab
"
,
"
chats_panel
"
:
"
src/templates/chats_panel
"
,
"
choose_status
"
:
"
src/templates/choose_status
"
,
"
contacts_panel
"
:
"
src/templates/contacts_panel
"
,
"
contacts_tab
"
:
"
src/templates/contacts_tab
"
,
"
controlbox
"
:
"
src/templates/controlbox
"
,
"
controlbox_toggle
"
:
"
src/templates/controlbox_toggle
"
,
"
field
"
:
"
src/templates/field
"
,
"
form_checkbox
"
:
"
src/templates/form_checkbox
"
,
"
form_input
"
:
"
src/templates/form_input
"
,
"
form_select
"
:
"
src/templates/form_select
"
,
"
group_header
"
:
"
src/templates/group_header
"
,
"
info
"
:
"
src/templates/info
"
,
"
login_panel
"
:
"
src/templates/login_panel
"
,
"
login_tab
"
:
"
src/templates/login_tab
"
,
"
message
"
:
"
src/templates/message
"
,
"
new_day
"
:
"
src/templates/new_day
"
,
"
occupant
"
:
"
src/templates/occupant
"
,
"
pending_contact
"
:
"
src/templates/pending_contact
"
,
"
pending_contacts
"
:
"
src/templates/pending_contacts
"
,
"
requesting_contact
"
:
"
src/templates/requesting_contact
"
,
"
requesting_contacts
"
:
"
src/templates/requesting_contacts
"
,
"
room_description
"
:
"
src/templates/room_description
"
,
"
room_item
"
:
"
src/templates/room_item
"
,
"
room_panel
"
:
"
src/templates/room_panel
"
,
"
roster
"
:
"
src/templates/roster
"
,
"
roster_item
"
:
"
src/templates/roster_item
"
,
"
search_contact
"
:
"
src/templates/search_contact
"
,
"
select_option
"
:
"
src/templates/select_option
"
,
"
status_option
"
:
"
src/templates/status_option
"
,
"
toggle_chats
"
:
"
src/templates/toggle_chats
"
,
"
toolbar
"
:
"
src/templates/toolbar
"
,
"
trimmed_chat
"
:
"
src/templates/trimmed_chat
"
"
converse-dependencies
"
:
"
src/deps-full
"
}
})
src/strophe.roster.js
0 → 100644
View file @
52cabd0d
/*
Copyright 2010, François de Metz <francois@2metz.fr>
*/
/**
* Roster Plugin
* Allow easily roster management
*
* Features
* * Get roster from server
* * handle presence
* * handle roster iq
* * subscribe/unsubscribe
* * authorize/unauthorize
* * roster versioning (xep 237)
*/
Strophe
.
addConnectionPlugin
(
'
roster
'
,
{
/** Function: init
* Plugin init
*
* Parameters:
* (Strophe.Connection) conn - Strophe connection
*/
init
:
function
(
conn
)
{
this
.
_connection
=
conn
;
this
.
_callbacks
=
[];
/** Property: items
* Roster items
* [
* {
* name : "",
* jid : "",
* subscription : "",
* ask : "",
* groups : ["", ""],
* resources : {
* myresource : {
* show : "",
* status : "",
* priority : ""
* }
* }
* }
* ]
*/
this
.
items
=
[];
/** Property: ver
* current roster revision
* always null if server doesn't support xep 237
*/
this
.
ver
=
null
;
// Override the connect and attach methods to always add presence and roster handlers.
// They are removed when the connection disconnects, so must be added on connection.
var
oldCallback
,
roster
=
this
,
_connect
=
conn
.
connect
,
_attach
=
conn
.
attach
;
var
newCallback
=
function
(
status
)
{
if
(
status
==
Strophe
.
Status
.
ATTACHED
||
status
==
Strophe
.
Status
.
CONNECTED
)
{
try
{
// Presence subscription
conn
.
addHandler
(
roster
.
_onReceivePresence
.
bind
(
roster
),
null
,
'
presence
'
,
null
,
null
,
null
);
conn
.
addHandler
(
roster
.
_onReceiveIQ
.
bind
(
roster
),
Strophe
.
NS
.
ROSTER
,
'
iq
'
,
"
set
"
,
null
,
null
);
}
catch
(
e
)
{
Strophe
.
error
(
e
);
}
}
if
(
typeof
oldCallback
===
"
function
"
)
{
oldCallback
.
apply
(
this
,
arguments
);
}
};
conn
.
connect
=
function
(
jid
,
pass
,
callback
,
wait
,
hold
)
{
oldCallback
=
callback
;
if
(
typeof
jid
==
"
undefined
"
)
jid
=
null
;
if
(
typeof
pass
==
"
undefined
"
)
pass
=
null
;
callback
=
newCallback
;
_connect
.
apply
(
conn
,
[
jid
,
pass
,
callback
,
wait
,
hold
]);
};
conn
.
attach
=
function
(
jid
,
sid
,
rid
,
callback
,
wait
,
hold
,
wind
)
{
oldCallback
=
callback
;
if
(
typeof
jid
==
"
undefined
"
)
jid
=
null
;
if
(
typeof
sid
==
"
undefined
"
)
sid
=
null
;
if
(
typeof
rid
==
"
undefined
"
)
rid
=
null
;
callback
=
newCallback
;
_attach
.
apply
(
conn
,
[
jid
,
sid
,
rid
,
callback
,
wait
,
hold
,
wind
]);
};
Strophe
.
addNamespace
(
'
ROSTER_VER
'
,
'
urn:xmpp:features:rosterver
'
);
Strophe
.
addNamespace
(
'
NICK
'
,
'
http://jabber.org/protocol/nick
'
);
},
/** Function: supportVersioning
* return true if roster versioning is enabled on server
*/
supportVersioning
:
function
()
{
return
(
this
.
_connection
.
features
&&
this
.
_connection
.
features
.
getElementsByTagName
(
'
ver
'
).
length
>
0
);
},
/** Function: get
* Get Roster on server
*
* Parameters:
* (Function) userCallback - callback on roster result
* (String) ver - current rev of roster
* (only used if roster versioning is enabled)
* (Array) items - initial items of ver
* (only used if roster versioning is enabled)
* In browser context you can use sessionStorage
* to store your roster in json (JSON.stringify())
*/
get
:
function
(
userCallback
,
ver
,
items
)
{
var
attrs
=
{
xmlns
:
Strophe
.
NS
.
ROSTER
};
if
(
this
.
supportVersioning
())
{
// empty rev because i want an rev attribute in the result
attrs
.
ver
=
ver
||
''
;
this
.
items
=
items
||
[];
}
var
iq
=
$iq
({
type
:
'
get
'
,
'
id
'
:
this
.
_connection
.
getUniqueId
(
'
roster
'
)}).
c
(
'
query
'
,
attrs
);
return
this
.
_connection
.
sendIQ
(
iq
,
this
.
_onReceiveRosterSuccess
.
bind
(
this
,
userCallback
),
this
.
_onReceiveRosterError
.
bind
(
this
,
userCallback
));
},
/** Function: registerCallback
* register callback on roster (presence and iq)
*
* Parameters:
* (Function) call_back
*/
registerCallback
:
function
(
call_back
)
{
this
.
_callbacks
.
push
(
call_back
);
},
/** Function: findItem
* Find item by JID
*
* Parameters:
* (String) jid
*/
findItem
:
function
(
jid
)
{
try
{
for
(
var
i
=
0
;
i
<
this
.
items
.
length
;
i
++
)
{
if
(
this
.
items
[
i
]
&&
this
.
items
[
i
].
jid
==
jid
)
{
return
this
.
items
[
i
];
}
}
}
catch
(
e
)
{
Strophe
.
error
(
e
);
}
return
false
;
},
/** Function: removeItem
* Remove item by JID
*
* Parameters:
* (String) jid
*/
removeItem
:
function
(
jid
)
{
for
(
var
i
=
0
;
i
<
this
.
items
.
length
;
i
++
)
{
if
(
this
.
items
[
i
]
&&
this
.
items
[
i
].
jid
==
jid
)
{
this
.
items
.
splice
(
i
,
1
);
return
true
;
}
}
return
false
;
},
/** Function: subscribe
* Subscribe presence
*
* Parameters:
* (String) jid
* (String) message (optional)
* (String) nick (optional)
*/
subscribe
:
function
(
jid
,
message
,
nick
)
{
var
pres
=
$pres
({
to
:
jid
,
type
:
"
subscribe
"
});
if
(
message
&&
message
!==
""
)
{
pres
.
c
(
"
status
"
).
t
(
message
).
up
();
}
if
(
nick
&&
nick
!==
""
)
{
pres
.
c
(
'
nick
'
,
{
'
xmlns
'
:
Strophe
.
NS
.
NICK
}).
t
(
nick
).
up
();
}
this
.
_connection
.
send
(
pres
);
},
/** Function: unsubscribe
* Unsubscribe presence
*
* Parameters:
* (String) jid
* (String) message
*/
unsubscribe
:
function
(
jid
,
message
)
{
var
pres
=
$pres
({
to
:
jid
,
type
:
"
unsubscribe
"
});
if
(
message
&&
message
!==
""
)
pres
.
c
(
"
status
"
).
t
(
message
);
this
.
_connection
.
send
(
pres
);
},
/** Function: authorize
* Authorize presence subscription
*
* Parameters:
* (String) jid
* (String) message
*/
authorize
:
function
(
jid
,
message
)
{
var
pres
=
$pres
({
to
:
jid
,
type
:
"
subscribed
"
});
if
(
message
&&
message
!==
""
)
pres
.
c
(
"
status
"
).
t
(
message
);
this
.
_connection
.
send
(
pres
);
},
/** Function: unauthorize
* Unauthorize presence subscription
*
* Parameters:
* (String) jid
* (String) message
*/
unauthorize
:
function
(
jid
,
message
)
{
var
pres
=
$pres
({
to
:
jid
,
type
:
"
unsubscribed
"
});
if
(
message
&&
message
!==
""
)
pres
.
c
(
"
status
"
).
t
(
message
);
this
.
_connection
.
send
(
pres
);
},
/** Function: add
* Add roster item
*
* Parameters:
* (String) jid - item jid
* (String) name - name
* (Array) groups
* (Function) call_back
*/
add
:
function
(
jid
,
name
,
groups
,
call_back
)
{
var
iq
=
$iq
({
type
:
'
set
'
}).
c
(
'
query
'
,
{
xmlns
:
Strophe
.
NS
.
ROSTER
}).
c
(
'
item
'
,
{
jid
:
jid
,
name
:
name
});
for
(
var
i
=
0
;
i
<
groups
.
length
;
i
++
)
{
iq
.
c
(
'
group
'
).
t
(
groups
[
i
]).
up
();
}
this
.
_connection
.
sendIQ
(
iq
,
call_back
,
call_back
);
},
/** Function: update
* Update roster item
*
* Parameters:
* (String) jid - item jid
* (String) name - name
* (Array) groups
* (Function) call_back
*/
update
:
function
(
jid
,
name
,
groups
,
call_back
)
{
var
item
=
this
.
findItem
(
jid
);
if
(
!
item
)
{
throw
"
item not found
"
;
}
var
newName
=
name
||
item
.
name
;
var
newGroups
=
groups
||
item
.
groups
;
var
iq
=
$iq
({
type
:
'
set
'
}).
c
(
'
query
'
,
{
xmlns
:
Strophe
.
NS
.
ROSTER
}).
c
(
'
item
'
,
{
jid
:
item
.
jid
,
name
:
newName
});
for
(
var
i
=
0
;
i
<
newGroups
.
length
;
i
++
)
{
iq
.
c
(
'
group
'
).
t
(
newGroups
[
i
]).
up
();
}
return
this
.
_connection
.
sendIQ
(
iq
,
call_back
,
call_back
);
},
/** Function: remove
* Remove roster item
*
* Parameters:
* (String) jid - item jid
* (Function) call_back
*/
remove
:
function
(
jid
,
call_back
)
{
var
item
=
this
.
findItem
(
jid
);
if
(
!
item
)
{
throw
"
item not found
"
;
}
var
iq
=
$iq
({
type
:
'
set
'
}).
c
(
'
query
'
,
{
xmlns
:
Strophe
.
NS
.
ROSTER
}).
c
(
'
item
'
,
{
jid
:
item
.
jid
,
subscription
:
"
remove
"
});
this
.
_connection
.
sendIQ
(
iq
,
call_back
,
call_back
);
},
/** PrivateFunction: _onReceiveRosterSuccess
*
*/
_onReceiveRosterSuccess
:
function
(
userCallback
,
stanza
)
{
this
.
_updateItems
(
stanza
);
if
(
typeof
userCallback
===
"
function
"
)
{
userCallback
(
this
.
items
);
}
},
/** PrivateFunction: _onReceiveRosterError
*
*/
_onReceiveRosterError
:
function
(
userCallback
,
stanza
)
{
userCallback
(
this
.
items
);
},
/** PrivateFunction: _onReceivePresence
* Handle presence
*/
_onReceivePresence
:
function
(
presence
)
{
// TODO: from is optional
var
jid
=
presence
.
getAttribute
(
'
from
'
);
var
from
=
Strophe
.
getBareJidFromJid
(
jid
);
var
item
=
this
.
findItem
(
from
);
// not in roster
if
(
!
item
)
{
return
true
;
}
var
type
=
presence
.
getAttribute
(
'
type
'
);
if
(
type
==
'
unavailable
'
)
{
delete
item
.
resources
[
Strophe
.
getResourceFromJid
(
jid
)];
}
else
if
(
!
type
)
{
// TODO: add timestamp
item
.
resources
[
Strophe
.
getResourceFromJid
(
jid
)]
=
{
show
:
(
presence
.
getElementsByTagName
(
'
show
'
).
length
!==
0
)
?
Strophe
.
getText
(
presence
.
getElementsByTagName
(
'
show
'
)[
0
])
:
""
,
status
:
(
presence
.
getElementsByTagName
(
'
status
'
).
length
!==
0
)
?
Strophe
.
getText
(
presence
.
getElementsByTagName
(
'
status
'
)[
0
])
:
""
,
priority
:
(
presence
.
getElementsByTagName
(
'
priority
'
).
length
!==
0
)
?
Strophe
.
getText
(
presence
.
getElementsByTagName
(
'
priority
'
)[
0
])
:
""
};
}
else
{
// Stanza is not a presence notification. (It's probably a subscription type stanza.)
return
true
;
}
this
.
_call_backs
(
this
.
items
,
item
);
return
true
;
},
/** PrivateFunction: _call_backs
*
*/
_call_backs
:
function
(
items
,
item
)
{
for
(
var
i
=
0
;
i
<
this
.
_callbacks
.
length
;
i
++
)
// [].forEach my love ...
{
this
.
_callbacks
[
i
](
items
,
item
);
}
},
/** PrivateFunction: _onReceiveIQ
* Handle roster push.
*/
_onReceiveIQ
:
function
(
iq
)
{
var
id
=
iq
.
getAttribute
(
'
id
'
);
var
from
=
iq
.
getAttribute
(
'
from
'
);
// Receiving client MUST ignore stanza unless it has no from or from = user's JID.
if
(
from
&&
from
!==
""
&&
from
!=
this
.
_connection
.
jid
&&
from
!=
Strophe
.
getBareJidFromJid
(
this
.
_connection
.
jid
))
return
true
;
var
iqresult
=
$iq
({
type
:
'
result
'
,
id
:
id
,
from
:
this
.
_connection
.
jid
});
this
.
_connection
.
send
(
iqresult
);
this
.
_updateItems
(
iq
);
return
true
;
},
/** PrivateFunction: _updateItems
* Update items from iq
*/
_updateItems
:
function
(
iq
)
{
var
query
=
iq
.
getElementsByTagName
(
'
query
'
);
if
(
query
.
length
!==
0
)
{
this
.
ver
=
query
.
item
(
0
).
getAttribute
(
'
ver
'
);
var
self
=
this
;
Strophe
.
forEachChild
(
query
.
item
(
0
),
'
item
'
,
function
(
item
)
{
self
.
_updateItem
(
item
);
}
);
}
this
.
_call_backs
(
this
.
items
);
},
/** PrivateFunction: _updateItem
* Update internal representation of roster item
*/
_updateItem
:
function
(
item
)
{
var
jid
=
item
.
getAttribute
(
"
jid
"
);
var
name
=
item
.
getAttribute
(
"
name
"
);
var
subscription
=
item
.
getAttribute
(
"
subscription
"
);
var
ask
=
item
.
getAttribute
(
"
ask
"
);
var
groups
=
[];
Strophe
.
forEachChild
(
item
,
'
group
'
,
function
(
group
)
{
groups
.
push
(
Strophe
.
getText
(
group
));
}
);
if
(
subscription
==
"
remove
"
)
{
this
.
removeItem
(
jid
);
return
;
}
item
=
this
.
findItem
(
jid
);
if
(
!
item
)
{
this
.
items
.
push
({
name
:
name
,
jid
:
jid
,
subscription
:
subscription
,
ask
:
ask
,
groups
:
groups
,
resources
:
{}
});
}
else
{
item
.
name
=
name
;
item
.
subscription
=
subscription
;
item
.
ask
=
ask
;
item
.
groups
=
groups
;
}
}
});
src/templates/roster.html
View file @
52cabd0d
<input
class=
"roster-filter"
placeholder=
"{{placeholder}}"
>
<select
class=
"filter-type"
>
<input
style=
"display: none;"
class=
"roster-filter"
placeholder=
"{{placeholder}}"
>
<select
style=
"display: none;"
class=
"filter-type"
>
<option
value=
"contacts"
>
{{label_contacts}}
</option>
<option
value=
"groups"
>
{{label_groups}}
</option>
</select>
<dl
class=
"roster-contacts"
></dl>
tests/main.js
View file @
52cabd0d
config
=
{
baseUrl
:
'
.
'
,
paths
:
{
"
backbone
"
:
"
components/backbone/backbone
"
,
"
backbone.browserStorage
"
:
"
components/backbone.browserStorage/backbone.browserStorage
"
,
"
backbone.overview
"
:
"
components/backbone.overview/backbone.overview
"
,
"
bootstrap
"
:
"
components/bootstrap/dist/js/bootstrap
"
,
// XXX: Only required for https://conversejs.org website
"
bootstrapJS
"
:
"
components/bootstrapJS/index
"
,
// XXX: Only required for https://conversejs.org website
"
converse-dependencies
"
:
"
src/deps-website
"
,
"
converse-templates
"
:
"
src/templates
"
,
"
eventemitter
"
:
"
components/otr/build/dep/eventemitter
"
,
"
jquery
"
:
"
components/jquery/dist/jquery
"
,
"
jquery-private
"
:
"
src/jquery-private
"
,
"
jquery.browser
"
:
"
components/jquery.browser/index
"
,
"
jquery.easing
"
:
"
components/jquery-easing-original/index
"
,
// XXX: Only required for https://conversejs.org website
"
moment
"
:
"
components/momentjs/moment
"
,
"
strophe
"
:
"
components/strophe/strophe
"
,
"
strophe.disco
"
:
"
components/strophejs-plugins/disco/strophe.disco
"
,
"
strophe.muc
"
:
"
components/strophe.muc/index
"
,
"
strophe.roster
"
:
"
src/strophe.roster
"
,
"
strophe.vcard
"
:
"
components/strophejs-plugins/vcard/strophe.vcard
"
,
"
text
"
:
'
components/requirejs-text/text
'
,
"
tpl
"
:
'
components/requirejs-tpl-jcbrand/tpl
'
,
"
typeahead
"
:
"
components/typeahead.js/index
"
,
"
underscore
"
:
"
components/underscore/underscore
"
,
"
utils
"
:
"
src/utils
"
,
// Off-the-record-encryption
"
bigint
"
:
"
src/bigint
"
,
"
crypto
"
:
"
src/crypto
"
,
"
crypto.aes
"
:
"
components/otr/vendor/cryptojs/aes
"
,
"
crypto.cipher-core
"
:
"
components/otr/vendor/cryptojs/cipher-core
"
,
"
crypto.core
"
:
"
components/otr/vendor/cryptojs/core
"
,
"
crypto.enc-base64
"
:
"
components/otr/vendor/cryptojs/enc-base64
"
,
"
crypto.evpkdf
"
:
"
components/crypto-js-evanvosberg/src/evpkdf
"
,
"
crypto.hmac
"
:
"
components/otr/vendor/cryptojs/hmac
"
,
"
crypto.md5
"
:
"
components/crypto-js-evanvosberg/src/md5
"
,
"
crypto.mode-ctr
"
:
"
components/otr/vendor/cryptojs/mode-ctr
"
,
"
crypto.pad-nopadding
"
:
"
components/otr/vendor/cryptojs/pad-nopadding
"
,
"
crypto.sha1
"
:
"
components/otr/vendor/cryptojs/sha1
"
,
"
crypto.sha256
"
:
"
components/otr/vendor/cryptojs/sha256
"
,
"
salsa20
"
:
"
components/otr/build/dep/salsa20
"
,
"
otr
"
:
"
src/otr
"
,
// Locales paths
"
locales
"
:
"
locale/locales
"
,
"
jed
"
:
"
components/jed/jed
"
,
"
af
"
:
"
locale/af/LC_MESSAGES/af
"
,
"
de
"
:
"
locale/de/LC_MESSAGES/de
"
,
"
en
"
:
"
locale/en/LC_MESSAGES/en
"
,
"
es
"
:
"
locale/es/LC_MESSAGES/es
"
,
"
fr
"
:
"
locale/fr/LC_MESSAGES/fr
"
,
"
he
"
:
"
locale/he/LC_MESSAGES/he
"
,
"
hu
"
:
"
locale/hu/LC_MESSAGES/hu
"
,
"
id
"
:
"
locale/id/LC_MESSAGES/id
"
,
"
it
"
:
"
locale/it/LC_MESSAGES/it
"
,
"
ja
"
:
"
locale/ja/LC_MESSAGES/ja
"
,
"
nl
"
:
"
locale/nl/LC_MESSAGES/nl
"
,
"
pt_BR
"
:
"
locale/pt_BR/LC_MESSAGES/pt_BR
"
,
"
ru
"
:
"
locale/ru/LC_MESSAGES/ru
"
,
"
zh
"
:
"
locale/zh/LC_MESSAGES/zh
"
,
// Templates
"
action
"
:
"
src/templates/action
"
,
"
add_contact_dropdown
"
:
"
src/templates/add_contact_dropdown
"
,
"
add_contact_form
"
:
"
src/templates/add_contact_form
"
,
"
change_status_message
"
:
"
src/templates/change_status_message
"
,
"
chat_status
"
:
"
src/templates/chat_status
"
,
"
chatarea
"
:
"
src/templates/chatarea
"
,
"
chatbox
"
:
"
src/templates/chatbox
"
,
"
chatroom
"
:
"
src/templates/chatroom
"
,
"
chatroom_password_form
"
:
"
src/templates/chatroom_password_form
"
,
"
chatroom_sidebar
"
:
"
src/templates/chatroom_sidebar
"
,
"
chatrooms_tab
"
:
"
src/templates/chatrooms_tab
"
,
"
chats_panel
"
:
"
src/templates/chats_panel
"
,
"
choose_status
"
:
"
src/templates/choose_status
"
,
"
contacts_panel
"
:
"
src/templates/contacts_panel
"
,
"
contacts_tab
"
:
"
src/templates/contacts_tab
"
,
"
controlbox
"
:
"
src/templates/controlbox
"
,
"
controlbox_toggle
"
:
"
src/templates/controlbox_toggle
"
,
"
field
"
:
"
src/templates/field
"
,
"
form_checkbox
"
:
"
src/templates/form_checkbox
"
,
"
form_input
"
:
"
src/templates/form_input
"
,
"
form_select
"
:
"
src/templates/form_select
"
,
"
group_header
"
:
"
src/templates/group_header
"
,
"
info
"
:
"
src/templates/info
"
,
"
login_panel
"
:
"
src/templates/login_panel
"
,
"
login_tab
"
:
"
src/templates/login_tab
"
,
"
message
"
:
"
src/templates/message
"
,
"
new_day
"
:
"
src/templates/new_day
"
,
"
occupant
"
:
"
src/templates/occupant
"
,
"
pending_contact
"
:
"
src/templates/pending_contact
"
,
"
pending_contacts
"
:
"
src/templates/pending_contacts
"
,
"
requesting_contact
"
:
"
src/templates/requesting_contact
"
,
"
requesting_contacts
"
:
"
src/templates/requesting_contacts
"
,
"
room_description
"
:
"
src/templates/room_description
"
,
"
room_item
"
:
"
src/templates/room_item
"
,
"
room_panel
"
:
"
src/templates/room_panel
"
,
"
roster
"
:
"
src/templates/roster
"
,
"
roster_item
"
:
"
src/templates/roster_item
"
,
"
search_contact
"
:
"
src/templates/search_contact
"
,
"
select_option
"
:
"
src/templates/select_option
"
,
"
status_option
"
:
"
src/templates/status_option
"
,
"
toggle_chats
"
:
"
src/templates/toggle_chats
"
,
"
toolbar
"
:
"
src/templates/toolbar
"
,
"
trimmed_chat
"
:
"
src/templates/trimmed_chat
"
},
map
:
{
// '*' means all modules will get 'jquery-private'
// for their 'jquery' dependency.
'
*
'
:
{
'
jquery
'
:
'
jquery-private
'
},
// 'jquery-private' wants the real jQuery module
// though. If this line was not here, there would
// be an unresolvable cyclic dependency.
'
jquery-private
'
:
{
'
jquery
'
:
'
jquery
'
}
},
tpl
:
{
// Configuration for requirejs-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
:
{
'
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
'
]
},
'
bigint
'
:
{
deps
:
[
'
crypto
'
]
},
'
strophe
'
:
{
exports
:
'
Strophe
'
},
'
strophe.disco
'
:
{
deps
:
[
'
strophe
'
]
},
'
strophe.muc
'
:
{
deps
:
[
'
strophe
'
]
},
'
strophe.roster
'
:
{
deps
:
[
'
strophe
'
]
},
'
strophe.vcard
'
:
{
deps
:
[
'
strophe
'
]
}
}
};
// Extra test dependencies
config
.
paths
.
mock
=
"
tests/mock
"
;
config
.
paths
.
test_utils
=
"
tests/utils
"
;
...
...
@@ -40,8 +189,6 @@ require([
window
.
converse_api
=
converse
;
window
.
localStorage
.
clear
();
window
.
sessionStorage
.
clear
();
// XXX: call this to initialize Strophe plugins
new
Strophe
.
Connection
(
'
localhost
'
);
converse
.
initialize
({
prebind
:
false
,
...
...
@@ -49,7 +196,8 @@ require([
auto_subscribe
:
false
,
animate
:
false
,
connection
:
mock
.
mock_connection
,
no_trimming
:
true
no_trimming
:
true
,
debug
:
true
},
function
(
converse
)
{
window
.
converse
=
converse
;
window
.
crypto
=
{
...
...
@@ -68,7 +216,8 @@ require([
"
spec/controlbox
"
,
"
spec/chatbox
"
,
"
spec/chatroom
"
,
"
spec/minchats
"
"
spec/minchats
"
,
"
spec/profiling
"
],
function
()
{
// Make sure this callback is only called once.
delete
converse
.
callback
;
...
...
tests/mock.js
View file @
52cabd0d
...
...
@@ -36,11 +36,37 @@
'
preventDefault
'
:
function
()
{}
};
mock
.
mock_connection
=
{
'
_proto
'
:
{},
'
connected
'
:
true
,
'
authenticated
'
:
true
,
'
mock
'
:
true
,
mock
.
mock_connection
=
function
()
{
Strophe
.
Bosh
.
prototype
.
_processRequest
=
function
()
{};
// Don't attempt to send out stanzas
var
c
=
new
Strophe
.
Connection
(
'
jasmine tests
'
);
c
.
authenticated
=
true
;
c
.
connected
=
true
;
c
.
mock
=
true
;
c
.
jid
=
'
dummy@localhost/resource
'
;
c
.
vcard
=
{
'
get
'
:
function
(
callback
,
jid
)
{
var
fullname
;
if
(
!
jid
)
{
jid
=
'
dummy@localhost
'
;
fullname
=
'
Max Mustermann
'
;
}
else
{
var
name
=
jid
.
split
(
'
@
'
)[
0
].
replace
(
/
\.
/g
,
'
'
).
split
(
'
'
);
var
last
=
name
.
length
-
1
;
name
[
0
]
=
name
[
0
].
charAt
(
0
).
toUpperCase
()
+
name
[
0
].
slice
(
1
);
name
[
last
]
=
name
[
last
].
charAt
(
0
).
toUpperCase
()
+
name
[
last
].
slice
(
1
);
fullname
=
name
.
join
(
'
'
);
}
var
vcard
=
$iq
().
c
(
'
vCard
'
).
c
(
'
FN
'
).
t
(
fullname
);
callback
(
vcard
.
tree
());
}
};
c
.
_changeConnectStatus
(
Strophe
.
Status
.
CONNECTED
);
c
.
attach
(
c
.
jid
);
return
c
;
}();
/*
{
'muc': {
'listRooms': function () {},
'join': function () {},
...
...
@@ -49,7 +75,6 @@
'groupchat': function () {return String((new Date()).getTime()); }
},
'service': 'jasmine tests',
'
jid
'
:
'
dummy@localhost
'
,
'addHandler': function (handler, ns, name, type, id, from, options) {
return function () {};
},
...
...
@@ -87,5 +112,6 @@
'items': function () {}
}
};
*/
return
mock
;
}));
tests/utils.js
View file @
52cabd0d
...
...
@@ -9,6 +9,17 @@
}(
this
,
function
(
$
,
mock
)
{
var
utils
=
{};
utils
.
createRequest
=
function
(
iq
)
{
iq
=
typeof
iq
.
tree
==
"
function
"
?
iq
.
tree
()
:
iq
;
var
req
=
new
Strophe
.
Request
(
iq
,
function
()
{});
req
.
getResponse
=
function
()
{
var
env
=
new
Strophe
.
Builder
(
'
env
'
,
{
type
:
'
mock
'
}).
tree
();
env
.
appendChild
(
iq
);
return
env
;
};
return
req
;
};
utils
.
closeAllChatBoxes
=
function
()
{
var
i
,
chatbox
;
for
(
i
=
converse
.
chatboxes
.
models
.
length
-
1
;
i
>-
1
;
i
--
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment