Merge branch 'live-filter'
Conflicts: builds/converse-no-locales-no-otr.min.js builds/converse-no-otr.min.js builds/converse.min.js builds/converse.website-no-otr.min.js builds/converse.website.min.js
This commit is contained in:
commit
bf837a921e
2
builds/converse-no-locales-no-otr.min.js
vendored
2
builds/converse-no-locales-no-otr.min.js
vendored
File diff suppressed because one or more lines are too long
2
builds/converse-no-otr.min.js
vendored
2
builds/converse-no-otr.min.js
vendored
File diff suppressed because one or more lines are too long
2
builds/converse.min.js
vendored
2
builds/converse.min.js
vendored
File diff suppressed because one or more lines are too long
2
builds/converse.website-no-otr.min.js
vendored
2
builds/converse.website-no-otr.min.js
vendored
File diff suppressed because one or more lines are too long
2
builds/converse.website.min.js
vendored
2
builds/converse.website.min.js
vendored
File diff suppressed because one or more lines are too long
158
converse.js
158
converse.js
@ -292,6 +292,9 @@
|
||||
var HEADER_REQUESTING_CONTACTS = __('Contact requests');
|
||||
var HEADER_UNGROUPED = __('Ungrouped');
|
||||
|
||||
var LABEL_CONTACTS = __('Contacts');
|
||||
var LABEL_GROUPS = __('Groups');
|
||||
|
||||
var HEADER_WEIGHTS = {};
|
||||
HEADER_WEIGHTS[HEADER_CURRENT_CONTACTS] = 0;
|
||||
HEADER_WEIGHTS[HEADER_UNGROUPED] = 1;
|
||||
@ -307,8 +310,7 @@
|
||||
// Module-level functions
|
||||
// ----------------------
|
||||
this.giveFeedback = function (message, klass) {
|
||||
$('.conn-feedback').text(message);
|
||||
$('.conn-feedback').attr('class', 'conn-feedback');
|
||||
$('.conn-feedback').attr('class', 'conn-feedback').text(message);
|
||||
if (klass) {
|
||||
$('.conn-feedback').addClass(klass);
|
||||
}
|
||||
@ -1497,7 +1499,7 @@
|
||||
label_away: __('Away'),
|
||||
label_offline: __('Offline')
|
||||
});
|
||||
this.$tabs.append(converse.templates.contacts_tab({label_contacts: __('Contacts')}));
|
||||
this.$tabs.append(converse.templates.contacts_tab({label_contacts: LABEL_CONTACTS}));
|
||||
if (converse.xhr_user_search) {
|
||||
markup = converse.templates.search_contact({
|
||||
label_contact_name: __('Contact name'),
|
||||
@ -1517,9 +1519,9 @@
|
||||
});
|
||||
}
|
||||
this.$el.html(widgets);
|
||||
|
||||
this.$el.find('.search-xmpp ul').append(markup);
|
||||
this.$el.append(converse.rosterview.$el);
|
||||
converse.rosterview.update(); // Will render live filter if needed.
|
||||
return this;
|
||||
},
|
||||
|
||||
@ -3245,7 +3247,8 @@
|
||||
initialize: function () {
|
||||
this.model.contacts.on("add", this.addContact, this);
|
||||
this.model.contacts.on("change:chat_status", function (contact) {
|
||||
// This might be optimized by instead of first sorting, finding the correct position in positionContact
|
||||
// This might be optimized by instead of first sorting,
|
||||
// finding the correct position in positionContact
|
||||
this.model.contacts.sort();
|
||||
this.positionContact(contact).render();
|
||||
}, this);
|
||||
@ -3282,23 +3285,73 @@
|
||||
return view;
|
||||
},
|
||||
|
||||
hide: function () {
|
||||
this.$el.nextUntil('dt').addBack().hide();
|
||||
},
|
||||
|
||||
filter: function (q) {
|
||||
/* Filter the group's contacts based on the query "q".
|
||||
* The query is matched against the contact's full name.
|
||||
* If all contacts are filtered out (i.e. hidden), then the
|
||||
* group must be filtered out as well.
|
||||
*/
|
||||
var matches, rejects;
|
||||
var predicate = function (item) {
|
||||
return item.get('fullname').toLowerCase().indexOf(q) === -1;
|
||||
};
|
||||
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')) {
|
||||
this.get(item.get('id')).$el.show();
|
||||
}
|
||||
}, this));
|
||||
}
|
||||
this.showIfInvisible();
|
||||
} else {
|
||||
q = q.toLowerCase();
|
||||
matches = this.model.contacts.filter(predicate);
|
||||
if (matches.length === this.model.contacts.length) { // hide the whole group
|
||||
this.hide();
|
||||
} else {
|
||||
_.each(matches, $.proxy(function (item) {
|
||||
this.get(item.get('id')).$el.hide();
|
||||
}, this));
|
||||
_.each(this.model.contacts.reject(predicate), $.proxy(function (item) {
|
||||
this.get(item.get('id')).$el.show();
|
||||
}, this));
|
||||
this.showIfInvisible();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
showIfInvisible: function () {
|
||||
if (!this.$el.is(':visible')) {
|
||||
this.$el.show();
|
||||
}
|
||||
},
|
||||
|
||||
toggle: function (ev) {
|
||||
if (ev && ev.preventDefault) { ev.preventDefault(); }
|
||||
var $el = $(ev.target);
|
||||
this.$el.nextUntil('dt').slideToggle();
|
||||
if ($el.hasClass("icon-opened")) {
|
||||
this.$el.nextUntil('dt').slideUp();
|
||||
this.model.save({state: CLOSED});
|
||||
$el.removeClass("icon-opened").addClass("icon-closed");
|
||||
} else {
|
||||
$el.removeClass("icon-closed").addClass("icon-opened");
|
||||
this.model.save({state: OPENED});
|
||||
this.filter(
|
||||
converse.rosterview.$('.roster-filter').val(),
|
||||
converse.rosterview.$('.filter-type').val()
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
addContact: function (contact) {
|
||||
var view = new converse.RosterContactView({model: contact});
|
||||
this.add(contact.get('id'), view);
|
||||
var view = this.positionContact(contact).render();
|
||||
view = this.positionContact(contact).render();
|
||||
if (this.model.get('state') === CLOSED) {
|
||||
view.$el.hide();
|
||||
}
|
||||
@ -3347,8 +3400,14 @@
|
||||
});
|
||||
|
||||
this.RosterView = Backbone.Overview.extend({
|
||||
tagName: 'dl',
|
||||
tagName: 'div',
|
||||
id: 'converse-roster',
|
||||
events: {
|
||||
"keydown .roster-filter": "liveFilter",
|
||||
"click .onX": "clearFilter",
|
||||
"mousemove .x": "togglePointer",
|
||||
"change .filter-type": "changeFilterType"
|
||||
},
|
||||
|
||||
initialize: function () {
|
||||
this.registerRosterHandler();
|
||||
@ -3369,7 +3428,80 @@
|
||||
},
|
||||
|
||||
render: function () {
|
||||
this.$el.empty();
|
||||
this.$el.html(converse.templates.roster({
|
||||
placeholder: __('Type to filter'),
|
||||
label_contacts: LABEL_CONTACTS,
|
||||
label_groups: LABEL_GROUPS
|
||||
}));
|
||||
return this;
|
||||
},
|
||||
|
||||
changeFilterType: function (ev) {
|
||||
if (ev && ev.preventDefault) { ev.preventDefault(); }
|
||||
this.clearFilter();
|
||||
this.filter(
|
||||
this.$('.roster-filter').val(),
|
||||
ev.target.value
|
||||
);
|
||||
},
|
||||
|
||||
tog: function (v) {
|
||||
return v?'addClass':'removeClass';
|
||||
},
|
||||
|
||||
togglePointer: function (ev) {
|
||||
if (ev && ev.preventDefault) { ev.preventDefault(); }
|
||||
var el = ev.target;
|
||||
$(el)[this.tog(el.offsetWidth-18 < ev.clientX-el.getBoundingClientRect().left)]('onX');
|
||||
},
|
||||
|
||||
filter: function (query, type) {
|
||||
var matches;
|
||||
query = query.toLowerCase();
|
||||
if (type === 'groups') {
|
||||
matches = _.filter(this.getAll(), function (view) {
|
||||
return view.model.get('name').toLowerCase().indexOf(query) === -1;
|
||||
});
|
||||
_.each(matches, function (view) {
|
||||
view.hide();
|
||||
});
|
||||
} else {
|
||||
_.each(this.getAll(), function (view) {
|
||||
view.filter(query, type);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
liveFilter: _.debounce(function (ev) {
|
||||
if (ev && ev.preventDefault) { ev.preventDefault(); }
|
||||
var q = ev.target.value;
|
||||
var t = this.$('.filter-type').val();
|
||||
$(ev.target)[this.tog(q)]('x');
|
||||
this.filter(q, t);
|
||||
}, 500),
|
||||
|
||||
clearFilter: function (ev) {
|
||||
if (ev && ev.preventDefault) {
|
||||
ev.preventDefault();
|
||||
$(ev.target).removeClass('x onX').val('');
|
||||
}
|
||||
this.filter('');
|
||||
},
|
||||
|
||||
showHideFilter: function () {
|
||||
var $filter = this.$('.roster-filter');
|
||||
var visible = $filter.is(':visible');
|
||||
if (visible && $filter.val().length > 0) {
|
||||
// Don't hide if user is currently filtering.
|
||||
return;
|
||||
}
|
||||
if (this.$('.roster-contacts').hasScrollBar()) {
|
||||
if (!visible) {
|
||||
$filter.show();
|
||||
}
|
||||
} else {
|
||||
$filter.hide();
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
@ -3380,7 +3512,7 @@
|
||||
if (!$count.is(':visible')) {
|
||||
$count.show();
|
||||
}
|
||||
return this;
|
||||
return this.showHideFilter();
|
||||
},
|
||||
|
||||
reset: function () {
|
||||
@ -3457,13 +3589,13 @@
|
||||
*/
|
||||
model.sort();
|
||||
model.each($.proxy(function (group, idx) {
|
||||
var view = this.get(group.get('name'))
|
||||
var view = this.get(group.get('name'));
|
||||
if (!view) {
|
||||
view = new converse.RosterGroupView({model: group});
|
||||
this.add(group.get('name'), view.render());
|
||||
}
|
||||
if (idx === 0) {
|
||||
this.$el.append(view.$el);
|
||||
this.$('.roster-contacts').append(view.$el);
|
||||
} else {
|
||||
this.appendGroup(view);
|
||||
}
|
||||
@ -3476,7 +3608,7 @@
|
||||
*/
|
||||
var index = this.model.indexOf(view.model);
|
||||
if (index === 0) {
|
||||
this.$el.prepend(view.$el);
|
||||
this.$('.roster-contacts').prepend(view.$el);
|
||||
} else if (index == (this.model.length-1)) {
|
||||
this.appendGroup(view);
|
||||
} else {
|
||||
|
@ -754,7 +754,7 @@ dl.add-converse-contact {
|
||||
clear: right;
|
||||
height: 22px;
|
||||
width: 12px;
|
||||
padding: 0px 5px 0 0;
|
||||
padding: 0px 15px 0 0;
|
||||
color: #4f4f4f;
|
||||
}
|
||||
#conversejs ul#found-users {
|
||||
@ -817,7 +817,7 @@ dl.add-converse-contact {
|
||||
top: 1px;
|
||||
}
|
||||
#conversejs .controlbox-pane dt {
|
||||
padding: 3px;
|
||||
padding-bottom: 3px;
|
||||
}
|
||||
#conversejs .chatroom-form-container {
|
||||
height: 100%;
|
||||
@ -872,24 +872,52 @@ dl.add-converse-contact {
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
#conversejs #converse-roster span.req-contact-name {
|
||||
#converse-roster span.req-contact-name {
|
||||
width: 65%;
|
||||
}
|
||||
#conversejs #converse-roster span.pending-contact-name,
|
||||
#conversejs #converse-roster a.open-chat {
|
||||
#converse-roster span.pending-contact-name,
|
||||
#converse-roster a.open-chat {
|
||||
width: 80%;
|
||||
}
|
||||
#converse-roster dd span {
|
||||
padding: 0 5px 0 0;
|
||||
}
|
||||
#converse-roster {
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
margin: 0.5em 0 0 0;
|
||||
height: 254px;
|
||||
height: calc(100% - 70px);
|
||||
height: 194px;
|
||||
height: calc(100% - 25px);
|
||||
overflow-x: hidden;
|
||||
}
|
||||
#converse-roster .roster-filter {
|
||||
padding: 0;
|
||||
margin: 0 0 5px 0.5em;
|
||||
width: 111px;
|
||||
height: 20px;
|
||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAABNSURBVHjaXI7BDcAwCAMvyQjMyQ6dAbZiKfqoUK34g2zJh1dENIC7M8pMAPYdzAVY3d0ajNz9aypS/b5R6o+ZPdqoKgCq6h80KH3xDgBqNR97p8oAGQAAAABJRU5ErkJggg== ) no-repeat right -20px center;
|
||||
border: 1px solid #999;
|
||||
display: inline-block;
|
||||
}
|
||||
#converse-roster .filter-type {
|
||||
height: 20px;
|
||||
padding: 0;
|
||||
margin: 0 0 0 -5px;
|
||||
}
|
||||
/* (jQ addClass:) if input has value: */
|
||||
#converse-roster .roster-filter.x {
|
||||
background-position: right 3px center;
|
||||
}
|
||||
/* (jQ addClass:) if mouse is over the 'x' input area*/
|
||||
#converse-roster .roster-filter.onX {
|
||||
cursor: pointer;
|
||||
}
|
||||
#converse-roster .roster-contacts {
|
||||
margin: 0;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
max-height: 195px;
|
||||
max-height: calc(100% - 67px);
|
||||
}
|
||||
#converse-roster .group-toggle {
|
||||
color: #666;
|
||||
@ -961,7 +989,7 @@ dl.add-converse-contact {
|
||||
text-shadow: 0 1px 0 #fafafa;
|
||||
clear: both;
|
||||
}
|
||||
#conversejs #converse-roster dd {
|
||||
#converse-roster dd {
|
||||
line-height: 16px;
|
||||
}
|
||||
#conversejs .group-toggle {
|
||||
@ -970,20 +998,20 @@ dl.add-converse-contact {
|
||||
}
|
||||
#conversejs .roster-group:hover,
|
||||
#conversejs dd.available-chatroom:hover,
|
||||
#conversejs #converse-roster dd:hover {
|
||||
#converse-roster dd:hover {
|
||||
background-color: #eee;
|
||||
}
|
||||
#conversejs #converse-roster dd a.decline-xmpp-request {
|
||||
#converse-roster dd a.decline-xmpp-request {
|
||||
margin-left: 5px;
|
||||
}
|
||||
#conversejs #converse-roster dd a.remove-xmpp-contact {
|
||||
#converse-roster dd a.remove-xmpp-contact {
|
||||
float: right;
|
||||
width: 22px;
|
||||
margin: 0;
|
||||
display: none;
|
||||
color: #4f4f4f;
|
||||
}
|
||||
#conversejs #converse-roster dd:hover a.remove-xmpp-contact {
|
||||
#converse-roster dd:hover a.remove-xmpp-contact {
|
||||
display: inline-block;
|
||||
}
|
||||
#conversejs .chatbox,
|
||||
|
2
css/converse.min.css
vendored
2
css/converse.min.css
vendored
File diff suppressed because one or more lines are too long
@ -1,8 +1,14 @@
|
||||
Changelog
|
||||
=========
|
||||
|
||||
0.8 (2014-08-04)
|
||||
----------------
|
||||
0.8.1 (Unreleased)
|
||||
------------------
|
||||
|
||||
* #212 Provide a live filter of the roster contacts. [jcbrand]
|
||||
|
||||
|
||||
0.8.0 (2014-08-04)
|
||||
------------------
|
||||
|
||||
.. note::
|
||||
1. Converse.js is now relicensed under the `Mozilla Public License <http://www.mozilla.org/MPL/2.0/>`_.
|
||||
|
10
index.html
10
index.html
@ -11,14 +11,8 @@
|
||||
<link type="text/css" rel="stylesheet" media="screen" href="components/bootstrap/dist/css/bootstrap.min.css" />
|
||||
<link type="text/css" rel="stylesheet" media="screen" href="components/fontawesome/css/font-awesome.min.css" />
|
||||
<link type="text/css" rel="stylesheet" media="screen" href="css/theme.css" />
|
||||
<link type="text/css" rel="stylesheet" media="screen" href="css/converse.min.css" />
|
||||
<!-- Only for development: <script data-main="main" src="components/requirejs/require.js"></script> -->
|
||||
<![if gte IE 9]>
|
||||
<script src="builds/converse.website.min.js"></script>
|
||||
<![endif]>
|
||||
<!--[if lt IE 9]>
|
||||
<script src="builds/converse.website-no-otr.min.js"></script>
|
||||
<![endif]-->
|
||||
<link type="text/css" rel="stylesheet" media="screen" href="css/converse.css" />
|
||||
<script data-main="main" src="components/requirejs/require.js"></script>
|
||||
</head>
|
||||
|
||||
<body id="page-top" data-spy="scroll" data-target=".navbar-custom">
|
||||
|
@ -831,7 +831,7 @@ dl.add-converse-contact {
|
||||
clear: right;
|
||||
height: 22px;
|
||||
width: 12px;
|
||||
padding: 0px 5px 0 0;
|
||||
padding: 0px 15px 0 0;
|
||||
color: rgb(79, 79, 79);
|
||||
}
|
||||
|
||||
@ -902,7 +902,7 @@ dl.add-converse-contact {
|
||||
}
|
||||
|
||||
#conversejs .controlbox-pane dt {
|
||||
padding: 3px;
|
||||
padding-bottom: 3px;
|
||||
}
|
||||
|
||||
#conversejs .chatroom-form-container {
|
||||
@ -967,12 +967,12 @@ dl.add-converse-contact {
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
#conversejs #converse-roster span.req-contact-name {
|
||||
#converse-roster span.req-contact-name {
|
||||
width: 65%;
|
||||
}
|
||||
|
||||
#conversejs #converse-roster span.pending-contact-name,
|
||||
#conversejs #converse-roster a.open-chat {
|
||||
#converse-roster span.pending-contact-name,
|
||||
#converse-roster a.open-chat {
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
@ -981,13 +981,46 @@ dl.add-converse-contact {
|
||||
}
|
||||
|
||||
#converse-roster {
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
margin: 0.5em 0 0 0;
|
||||
height: 254px;
|
||||
height: ~"calc(100% - 70px)";
|
||||
height: 194px;
|
||||
height: ~"calc(100% - 25px)";
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
#converse-roster .roster-filter {
|
||||
padding: 0;
|
||||
margin: 0 0 5px 0.5em;
|
||||
width: 111px;
|
||||
height: 20px;
|
||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAABNSURBVHjaXI7BDcAwCAMvyQjMyQ6dAbZiKfqoUK34g2zJh1dENIC7M8pMAPYdzAVY3d0ajNz9aypS/b5R6o+ZPdqoKgCq6h80KH3xDgBqNR97p8oAGQAAAABJRU5ErkJggg== ) no-repeat right -20px center;
|
||||
border: 1px solid #999;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#converse-roster .filter-type {
|
||||
height: 20px;
|
||||
padding: 0;
|
||||
margin: 0 0 0 -5px;
|
||||
}
|
||||
|
||||
/* (jQ addClass:) if input has value: */
|
||||
#converse-roster .roster-filter.x {
|
||||
background-position: right 3px center;
|
||||
}
|
||||
|
||||
/* (jQ addClass:) if mouse is over the 'x' input area*/
|
||||
#converse-roster .roster-filter.onX{
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
#converse-roster .roster-contacts {
|
||||
margin: 0;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
max-height: 195px;
|
||||
max-height: ~"calc(100% - 67px)";
|
||||
}
|
||||
|
||||
#converse-roster .group-toggle {
|
||||
@ -1073,7 +1106,7 @@ dl.add-converse-contact {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
#conversejs #converse-roster dd {
|
||||
#converse-roster dd {
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
@ -1084,15 +1117,15 @@ dl.add-converse-contact {
|
||||
|
||||
#conversejs .roster-group:hover,
|
||||
#conversejs dd.available-chatroom:hover,
|
||||
#conversejs #converse-roster dd:hover {
|
||||
#converse-roster dd:hover {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
#conversejs #converse-roster dd a.decline-xmpp-request {
|
||||
#converse-roster dd a.decline-xmpp-request {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
#conversejs #converse-roster dd a.remove-xmpp-contact {
|
||||
#converse-roster dd a.remove-xmpp-contact {
|
||||
float: right;
|
||||
width: 22px;
|
||||
margin: 0;
|
||||
@ -1100,7 +1133,7 @@ dl.add-converse-contact {
|
||||
color: rgb(79, 79, 79);
|
||||
}
|
||||
|
||||
#conversejs #converse-roster dd:hover a.remove-xmpp-contact {
|
||||
#converse-roster dd:hover a.remove-xmpp-contact {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
|
2
main.js
2
main.js
@ -4,6 +4,7 @@ config = {
|
||||
"jquery": "components/jquery/dist/jquery",
|
||||
"jquery.browser": "components/jquery.browser/dist/jquery.browser",
|
||||
"jquery.easing": "components/jquery-easing-original/jquery.easing.1.3", // XXX: Only required for https://conversejs.org website
|
||||
"utils": "src/utils",
|
||||
"bootstrap": "components/bootstrap/dist/js/bootstrap", // XXX: Only required for https://conversejs.org website
|
||||
"locales": "locale/locales",
|
||||
"underscore": "components/underscore/underscore",
|
||||
@ -74,6 +75,7 @@ config = {
|
||||
'bigint': { deps: ['crypto'] },
|
||||
'jquery.browser': { deps: ['jquery'] },
|
||||
'jquery.easing': { deps: ['jquery'] },
|
||||
'utils': { deps: ['jquery'] },
|
||||
'strophe': { deps: ['jquery'] },
|
||||
'strophe.disco': { deps: ['strophe'] },
|
||||
'strophe.muc': { deps: ['strophe', 'jquery'] },
|
||||
|
@ -114,139 +114,146 @@
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl id="converse-roster" style="display: block;">
|
||||
<dt class="roster-group" style="display: block;">
|
||||
<a href="#" data-group="Colleagues" class="group-toggle icon-opened" title="Click to hide these contacts">Colleagues</a>
|
||||
</dt>
|
||||
<dd class="online current-xmpp-contact">
|
||||
<a class="open-chat" title="Click to chat with this contact" href="#">
|
||||
<span class="icon-online" title="This contact is online"></span>
|
||||
Victor Matfield
|
||||
</a>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
<dd class="away current-xmpp-contact">
|
||||
<a class="open-chat" title="Click to chat with this contact" href="#">
|
||||
<span class="icon-away" title="this contact is away"></span>
|
||||
William Winterbottom
|
||||
</a>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
<dd class="dnd current-xmpp-contact">
|
||||
<a class="open-chat" title="Click to chat with this contact" href="#">
|
||||
<span class="icon-dnd" title="This contact is busy"></span>
|
||||
Gary Teichmann
|
||||
</a>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
<div id="converse-roster">
|
||||
<input class="roster-filter" placeholder="Type to filter">
|
||||
<select class="filter-type">
|
||||
<option value="contacts">Contacts</option>
|
||||
<option value="groups">Groups</option>
|
||||
</select>
|
||||
<dl class="roster-contacts" style="display: block;">
|
||||
<dt class="roster-group" style="display: block;">
|
||||
<a href="#" data-group="Colleagues" class="group-toggle icon-opened" title="Click to hide these contacts">Colleagues</a>
|
||||
</dt>
|
||||
<dd class="online current-xmpp-contact">
|
||||
<a class="open-chat" title="Click to chat with this contact" href="#">
|
||||
<span class="icon-online" title="This contact is online"></span>
|
||||
Victor Matfield
|
||||
</a>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
<dd class="away current-xmpp-contact">
|
||||
<a class="open-chat" title="Click to chat with this contact" href="#">
|
||||
<span class="icon-away" title="this contact is away"></span>
|
||||
William Winterbottom
|
||||
</a>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
<dd class="dnd current-xmpp-contact">
|
||||
<a class="open-chat" title="Click to chat with this contact" href="#">
|
||||
<span class="icon-dnd" title="This contact is busy"></span>
|
||||
Gary Teichmann
|
||||
</a>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
|
||||
<dt class="roster-group" style="display: block;">
|
||||
<a href="#" data-group="Family" class="group-toggle icon-opened" title="Click to hide these contacts">Family</a>
|
||||
</dt>
|
||||
<dd class="away current-xmpp-contact">
|
||||
<a class="open-chat" title="Click to chat with this contact" href="#">
|
||||
<span class="icon-away" title="this contact is away"></span>
|
||||
Allan Donald
|
||||
</a>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
<dd class="offline current-xmpp-contact">
|
||||
<a class="open-chat" title="Click to chat with this contact" href="#">
|
||||
<span class="icon-offline" title="This contact is offline"></span>
|
||||
Corné Krige
|
||||
</a>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
<dt class="roster-group" style="display: block;">
|
||||
<a href="#" data-group="Family" class="group-toggle icon-opened" title="Click to hide these contacts">Family</a>
|
||||
</dt>
|
||||
<dd class="away current-xmpp-contact">
|
||||
<a class="open-chat" title="Click to chat with this contact" href="#">
|
||||
<span class="icon-away" title="this contact is away"></span>
|
||||
Allan Donald
|
||||
</a>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
<dd class="offline current-xmpp-contact">
|
||||
<a class="open-chat" title="Click to chat with this contact" href="#">
|
||||
<span class="icon-offline" title="This contact is offline"></span>
|
||||
Corné Krige
|
||||
</a>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
|
||||
<dt class="roster-group" style="display: block;">
|
||||
<a href="#" data-group="Friends" class="group-toggle icon-opened" title="Click to hide these contacts">Friends</a>
|
||||
</dt>
|
||||
<dd class="online current-xmpp-contact">
|
||||
<a class="open-chat" title="Click to chat with this contact" href="#">
|
||||
<span class="icon-online" title="This contact is online"></span>
|
||||
John Smit
|
||||
</a>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
<dd class="online current-xmpp-contact">
|
||||
<a class="open-chat" title="Click to chat with this contact" href="#">
|
||||
<span class="icon-online" title="This contact is online"></span>
|
||||
Bakkies Botha
|
||||
</a>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
<dt class="roster-group" style="display: block;">
|
||||
<a href="#" data-group="Friends" class="group-toggle icon-opened" title="Click to hide these contacts">Friends</a>
|
||||
</dt>
|
||||
<dd class="online current-xmpp-contact">
|
||||
<a class="open-chat" title="Click to chat with this contact" href="#">
|
||||
<span class="icon-online" title="This contact is online"></span>
|
||||
John Smit
|
||||
</a>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
<dd class="online current-xmpp-contact">
|
||||
<a class="open-chat" title="Click to chat with this contact" href="#">
|
||||
<span class="icon-online" title="This contact is online"></span>
|
||||
Bakkies Botha
|
||||
</a>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
|
||||
<dt class="roster-group" style="display: block;">
|
||||
<a href="#" class="group-toggle icon-opened" title="Click to hide these contacts">Ungrouped</a>
|
||||
</dt>
|
||||
<dd class="online current-xmpp-contact">
|
||||
<a class="open-chat" title="Click to chat with this contact" href="#">
|
||||
<span class="icon-online" title="This contact is online"></span>
|
||||
James Small
|
||||
</a>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
<dt class="roster-group" style="display: block;">
|
||||
<a href="#" class="group-toggle icon-opened" title="Click to hide these contacts">Ungrouped</a>
|
||||
</dt>
|
||||
<dd class="online current-xmpp-contact">
|
||||
<a class="open-chat" title="Click to chat with this contact" href="#">
|
||||
<span class="icon-online" title="This contact is online"></span>
|
||||
James Small
|
||||
</a>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
|
||||
<dt id="xmpp-contact-requests" style="display: block;">
|
||||
<a href="#" class="group-toggle icon-opened" title="Click to hide these contacts">Contact Requests</a>
|
||||
</dt>
|
||||
<dd class="offline requesting-xmpp-contact">
|
||||
<span class="req-contact-name">Bob Skinstad</span>
|
||||
<span class="request-actions">
|
||||
<a class="accept-xmpp-request icon-checkmark" title="Click here to accept this contact's request" href="#"></a>
|
||||
<a class="decline-xmpp-request icon-close" title="Click here to decline this contact's request" href="#"></a>
|
||||
</span>
|
||||
</dd>
|
||||
<dd class="offline requesting-xmpp-contact">
|
||||
<span class="req-contact-name">André Vos</span>
|
||||
<span class="request-actions">
|
||||
<a class="accept-xmpp-request icon-checkmark" title="Click here to accept this contact's request" href="#"></a>
|
||||
<a class="decline-xmpp-request icon-close" title="Click here to decline this contact's request" href="#"></a>
|
||||
</span>
|
||||
</dd>
|
||||
<dt id="xmpp-contact-requests" style="display: block;">
|
||||
<a href="#" class="group-toggle icon-opened" title="Click to hide these contacts">Contact Requests</a>
|
||||
</dt>
|
||||
<dd class="offline requesting-xmpp-contact">
|
||||
<span class="req-contact-name">Bob Skinstad</span>
|
||||
<span class="request-actions">
|
||||
<a class="accept-xmpp-request icon-checkmark" title="Click here to accept this contact's request" href="#"></a>
|
||||
<a class="decline-xmpp-request icon-close" title="Click here to decline this contact's request" href="#"></a>
|
||||
</span>
|
||||
</dd>
|
||||
<dd class="offline requesting-xmpp-contact">
|
||||
<span class="req-contact-name">André Vos</span>
|
||||
<span class="request-actions">
|
||||
<a class="accept-xmpp-request icon-checkmark" title="Click here to accept this contact's request" href="#"></a>
|
||||
<a class="decline-xmpp-request icon-close" title="Click here to decline this contact's request" href="#"></a>
|
||||
</span>
|
||||
</dd>
|
||||
|
||||
<dt id="pending-xmpp-contacts" style="display: block;">
|
||||
<a href="#" class="group-toggle icon-opened" title="Click to hide these contacts">Pending Contacts</a>
|
||||
</dt>
|
||||
<dd class="offline pending-xmpp-contact"><span class="pending-contact-name">Rassie Erasmus</span>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
<dd class="offline pending-xmpp-contact"><span class="pending-contact-name">Victor Matfield</span>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
</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>
|
||||
<dt id="pending-xmpp-contacts" style="display: block;">
|
||||
<a href="#" class="group-toggle icon-opened" title="Click to hide these contacts">Pending Contacts</a>
|
||||
</dt>
|
||||
<dd class="offline pending-xmpp-contact"><span class="pending-contact-name">Rassie Erasmus</span>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
<dd class="offline pending-xmpp-contact"><span class="pending-contact-name">Victor Matfield</span>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -114,89 +114,146 @@
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl id="converse-roster" style="display: block;">
|
||||
<dt id="xmpp-contacts" style="display: block;">My contacts</dt>
|
||||
<dd class="online current-xmpp-contact">
|
||||
<a class="open-chat" title="Click to chat with this contact" href="#">
|
||||
<span class="icon-online" title="This contact is online"></span>
|
||||
John Smit</a>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
<dd class="away current-xmpp-contact">
|
||||
<a class="open-chat" title="Click to chat with this contact" href="#">
|
||||
<span class="icon-away" title="this contact is away"></span>
|
||||
Francois Pienaar</a>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
<dd class="dnd current-xmpp-contact">
|
||||
<a class="open-chat" title="Click to chat with this contact" href="#">
|
||||
<span class="icon-dnd" title="This contact is busy"></span>
|
||||
Gary Teichmann</a>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
<dd class="offline current-xmpp-contact">
|
||||
<a class="open-chat" title="Click to chat with this contact" href="#">
|
||||
<span class="icon-offline" title="This contact is offline"></span>
|
||||
Corné Krige</a>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
<div id="converse-roster">
|
||||
<input class="roster-filter" placeholder="Type to filter">
|
||||
<select class="filter-type">
|
||||
<option value="contacts">Contacts</option>
|
||||
<option value="groups">Groups</option>
|
||||
</select>
|
||||
<dl class="roster-contacts" style="display: block;">
|
||||
<dt class="roster-group" style="display: block;">
|
||||
<a href="#" data-group="Colleagues" class="group-toggle icon-opened" title="Click to hide these contacts">Colleagues</a>
|
||||
</dt>
|
||||
<dd class="online current-xmpp-contact">
|
||||
<a class="open-chat" title="Click to chat with this contact" href="#">
|
||||
<span class="icon-online" title="This contact is online"></span>
|
||||
Victor Matfield
|
||||
</a>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
<dd class="away current-xmpp-contact">
|
||||
<a class="open-chat" title="Click to chat with this contact" href="#">
|
||||
<span class="icon-away" title="this contact is away"></span>
|
||||
William Winterbottom
|
||||
</a>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
<dd class="dnd current-xmpp-contact">
|
||||
<a class="open-chat" title="Click to chat with this contact" href="#">
|
||||
<span class="icon-dnd" title="This contact is busy"></span>
|
||||
Gary Teichmann
|
||||
</a>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
|
||||
<dt id="xmpp-contact-requests" style="display: block;">Contact requests</dt>
|
||||
<dd class="offline requesting-xmpp-contact">
|
||||
<span>Bob Skinstad</span>
|
||||
<span class="request-actions">
|
||||
<a class="accept-xmpp-request icon-checkmark" title="Click here to accept this contact's request" href="#"></a>
|
||||
<a class="decline-xmpp-request icon-close" title="Click here to decline this contact's request" href="#"></a>
|
||||
</span>
|
||||
</dd>
|
||||
<dd class="offline requesting-xmpp-contact">
|
||||
<span>André Vos</span>
|
||||
<span class="request-actions">
|
||||
<a class="accept-xmpp-request icon-checkmark" title="Click here to accept this contact's request" href="#"></a>
|
||||
<a class="decline-xmpp-request icon-close" title="Click here to decline this contact's request" href="#"></a>
|
||||
</span>
|
||||
</dd>
|
||||
<dt class="roster-group" style="display: block;">
|
||||
<a href="#" data-group="Family" class="group-toggle icon-opened" title="Click to hide these contacts">Family</a>
|
||||
</dt>
|
||||
<dd class="away current-xmpp-contact">
|
||||
<a class="open-chat" title="Click to chat with this contact" href="#">
|
||||
<span class="icon-away" title="this contact is away"></span>
|
||||
Allan Donald
|
||||
</a>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
<dd class="offline current-xmpp-contact">
|
||||
<a class="open-chat" title="Click to chat with this contact" href="#">
|
||||
<span class="icon-offline" title="This contact is offline"></span>
|
||||
Corné Krige
|
||||
</a>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
|
||||
<dt id="pending-xmpp-contacts" style="display: block;">Pending contacts</dt>
|
||||
<dd class="offline pending-xmpp-contact"><span>Rassie Erasmus</span>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
<dd class="offline pending-xmpp-contact"><span>Victor Matfield</span>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
</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>
|
||||
<dt class="roster-group" style="display: block;">
|
||||
<a href="#" data-group="Friends" class="group-toggle icon-opened" title="Click to hide these contacts">Friends</a>
|
||||
</dt>
|
||||
<dd class="online current-xmpp-contact">
|
||||
<a class="open-chat" title="Click to chat with this contact" href="#">
|
||||
<span class="icon-online" title="This contact is online"></span>
|
||||
John Smit
|
||||
</a>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
<dd class="online current-xmpp-contact">
|
||||
<a class="open-chat" title="Click to chat with this contact" href="#">
|
||||
<span class="icon-online" title="This contact is online"></span>
|
||||
Bakkies Botha
|
||||
</a>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
|
||||
<dt class="roster-group" style="display: block;">
|
||||
<a href="#" class="group-toggle icon-opened" title="Click to hide these contacts">Ungrouped</a>
|
||||
</dt>
|
||||
<dd class="online current-xmpp-contact">
|
||||
<a class="open-chat" title="Click to chat with this contact" href="#">
|
||||
<span class="icon-online" title="This contact is online"></span>
|
||||
James Small
|
||||
</a>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
|
||||
<dt id="xmpp-contact-requests" style="display: block;">
|
||||
<a href="#" class="group-toggle icon-opened" title="Click to hide these contacts">Contact Requests</a>
|
||||
</dt>
|
||||
<dd class="offline requesting-xmpp-contact">
|
||||
<span class="req-contact-name">Bob Skinstad</span>
|
||||
<span class="request-actions">
|
||||
<a class="accept-xmpp-request icon-checkmark" title="Click here to accept this contact's request" href="#"></a>
|
||||
<a class="decline-xmpp-request icon-close" title="Click here to decline this contact's request" href="#"></a>
|
||||
</span>
|
||||
</dd>
|
||||
<dd class="offline requesting-xmpp-contact">
|
||||
<span class="req-contact-name">André Vos</span>
|
||||
<span class="request-actions">
|
||||
<a class="accept-xmpp-request icon-checkmark" title="Click here to accept this contact's request" href="#"></a>
|
||||
<a class="decline-xmpp-request icon-close" title="Click here to decline this contact's request" href="#"></a>
|
||||
</span>
|
||||
</dd>
|
||||
|
||||
<dt id="pending-xmpp-contacts" style="display: block;">
|
||||
<a href="#" class="group-toggle icon-opened" title="Click to hide these contacts">Pending Contacts</a>
|
||||
</dt>
|
||||
<dd class="offline pending-xmpp-contact"><span class="pending-contact-name">Rassie Erasmus</span>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
<dd class="offline pending-xmpp-contact"><span class="pending-contact-name">Victor Matfield</span>
|
||||
<a class="remove-xmpp-contact icon-remove" title="Click to remove this contact" href="#"></a>
|
||||
</dd>
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
108
spec/chatbox.js
108
spec/chatbox.js
@ -1,23 +1,23 @@
|
||||
(function (root, factory) {
|
||||
define([
|
||||
"mock",
|
||||
"utils"
|
||||
], function (mock, utils) {
|
||||
return factory(mock, utils);
|
||||
"test_utils"
|
||||
], function (mock, test_utils) {
|
||||
return factory(mock, test_utils);
|
||||
}
|
||||
);
|
||||
} (this, function (mock, utils) {
|
||||
return describe("Chatboxes", $.proxy(function(mock, utils) {
|
||||
} (this, function (mock, test_utils) {
|
||||
return describe("Chatboxes", $.proxy(function(mock, test_utils) {
|
||||
describe("A Chatbox", $.proxy(function () {
|
||||
beforeEach(function () {
|
||||
runs(function () {
|
||||
utils.closeAllChatBoxes();
|
||||
utils.removeControlBox();
|
||||
utils.clearBrowserStorage();
|
||||
utils.initConverse();
|
||||
utils.createContacts();
|
||||
utils.openControlBox();
|
||||
utils.openContactsPanel();
|
||||
test_utils.closeAllChatBoxes();
|
||||
test_utils.removeControlBox();
|
||||
test_utils.clearBrowserStorage();
|
||||
test_utils.initConverse();
|
||||
test_utils.createContacts();
|
||||
test_utils.openControlBox();
|
||||
test_utils.openContactsPanel();
|
||||
});
|
||||
});
|
||||
|
||||
@ -95,7 +95,7 @@
|
||||
// openControlBox was called earlier, so the controlbox is
|
||||
// visible, but no other chat boxes have been created.
|
||||
expect(this.chatboxes.length).toEqual(1);
|
||||
chatbox = utils.openChatBoxFor(contact_jid);
|
||||
chatbox = test_utils.openChatBoxFor(contact_jid);
|
||||
chatboxview = this.chatboxviews.get(contact_jid);
|
||||
spyOn(chatboxview, 'focus');
|
||||
$el = this.rosterview.$el.find('a.open-chat:contains("'+chatbox.get('fullname')+'")');
|
||||
@ -109,11 +109,11 @@
|
||||
spyOn(converse, 'emit');
|
||||
spyOn(this.chatboxviews, 'trimChats');
|
||||
runs(function () {
|
||||
utils.openControlBox();
|
||||
test_utils.openControlBox();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {
|
||||
utils.openChatBoxes(6);
|
||||
test_utils.openChatBoxes(6);
|
||||
expect(this.chatboxviews.trimChats).toHaveBeenCalled();
|
||||
// We instantiate a new ChatBoxes collection, which by default
|
||||
// will be empty.
|
||||
@ -136,7 +136,7 @@
|
||||
}, converse));
|
||||
|
||||
it("can be closed by clicking a DOM element with class 'close-chatbox-button'", $.proxy(function () {
|
||||
var chatbox = utils.openChatBoxes(1)[0],
|
||||
var chatbox = test_utils.openChatBoxes(1)[0],
|
||||
controlview = this.chatboxviews.get('controlbox'), // The controlbox is currently open
|
||||
chatview = this.chatboxviews.get(chatbox.get('jid'));
|
||||
spyOn(chatview, 'close').andCallThrough();
|
||||
@ -166,7 +166,7 @@
|
||||
}, converse));
|
||||
|
||||
it("can be minimized by clicking a DOM element with class 'toggle-chatbox-button'", function () {
|
||||
var chatbox = utils.openChatBoxes(1)[0],
|
||||
var chatbox = test_utils.openChatBoxes(1)[0],
|
||||
chatview = this.chatboxviews.get(chatbox.get('jid')),
|
||||
trimmed_chatboxes = this.minimized_chats,
|
||||
trimmedview;
|
||||
@ -207,17 +207,17 @@
|
||||
spyOn(converse.chatboxviews, 'trimChats');
|
||||
this.chatboxes.browserStorage._clear();
|
||||
runs(function () {
|
||||
utils.closeControlBox();
|
||||
test_utils.closeControlBox();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {
|
||||
expect(converse.emit).toHaveBeenCalledWith('chatBoxClosed', jasmine.any(Object));
|
||||
expect(converse.chatboxes.length).toEqual(0);
|
||||
utils.openChatBoxes(6);
|
||||
test_utils.openChatBoxes(6);
|
||||
expect(converse.chatboxviews.trimChats).toHaveBeenCalled();
|
||||
expect(converse.chatboxes.length).toEqual(6);
|
||||
expect(converse.emit).toHaveBeenCalledWith('chatBoxOpened', jasmine.any(Object));
|
||||
utils.closeAllChatBoxes();
|
||||
test_utils.closeAllChatBoxes();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {
|
||||
@ -237,7 +237,7 @@
|
||||
describe("A chat toolbar", $.proxy(function () {
|
||||
it("can be found on each chat box", $.proxy(function () {
|
||||
var contact_jid = mock.cur_names[2].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||
utils.openChatBoxFor(contact_jid);
|
||||
test_utils.openChatBoxFor(contact_jid);
|
||||
var chatbox = this.chatboxes.get(contact_jid);
|
||||
var view = this.chatboxviews.get(contact_jid);
|
||||
expect(chatbox).toBeDefined();
|
||||
@ -249,7 +249,7 @@
|
||||
|
||||
it("contains a button for inserting emoticons", $.proxy(function () {
|
||||
var contact_jid = mock.cur_names[2].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||
utils.openChatBoxFor(contact_jid);
|
||||
test_utils.openChatBoxFor(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');
|
||||
@ -308,7 +308,7 @@
|
||||
it("contains a button for starting an encrypted chat session", $.proxy(function () {
|
||||
// TODO: More tests can be added here...
|
||||
var contact_jid = mock.cur_names[2].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||
utils.openChatBoxFor(contact_jid);
|
||||
test_utils.openChatBoxFor(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);
|
||||
@ -336,7 +336,7 @@
|
||||
// First check that the button doesn't show if it's not enabled
|
||||
// via "visible_toolbar_buttons"
|
||||
converse.visible_toolbar_buttons.call = false;
|
||||
utils.openChatBoxFor(contact_jid);
|
||||
test_utils.openChatBoxFor(contact_jid);
|
||||
view = this.chatboxviews.get(contact_jid);
|
||||
$toolbar = view.$el.find('ul.chat-toolbar');
|
||||
callButton = $toolbar.find('.toggle-call');
|
||||
@ -345,7 +345,7 @@
|
||||
// Now check that it's shown if enabled and that it emits
|
||||
// callButtonClicked
|
||||
converse.visible_toolbar_buttons.call = true; // enable the button
|
||||
utils.openChatBoxFor(contact_jid);
|
||||
test_utils.openChatBoxFor(contact_jid);
|
||||
view = this.chatboxviews.get(contact_jid);
|
||||
$toolbar = view.$el.find('ul.chat-toolbar');
|
||||
callButton = $toolbar.find('.toggle-call');
|
||||
@ -360,7 +360,7 @@
|
||||
// First check that the button doesn't show if it's not enabled
|
||||
// via "visible_toolbar_buttons"
|
||||
converse.visible_toolbar_buttons.clear = false;
|
||||
utils.openChatBoxFor(contact_jid);
|
||||
test_utils.openChatBoxFor(contact_jid);
|
||||
view = this.chatboxviews.get(contact_jid);
|
||||
view = this.chatboxviews.get(contact_jid);
|
||||
$toolbar = view.$el.find('ul.chat-toolbar');
|
||||
@ -370,7 +370,7 @@
|
||||
// Now check that it's shown if enabled and that it calls
|
||||
// clearMessages
|
||||
converse.visible_toolbar_buttons.clear = true; // enable the button
|
||||
utils.openChatBoxFor(contact_jid);
|
||||
test_utils.openChatBoxFor(contact_jid);
|
||||
view = this.chatboxviews.get(contact_jid);
|
||||
$toolbar = view.$el.find('ul.chat-toolbar');
|
||||
clearButton = $toolbar.find('.toggle-clear');
|
||||
@ -387,7 +387,7 @@
|
||||
|
||||
beforeEach(function () {
|
||||
runs(function () {
|
||||
utils.closeAllChatBoxes();
|
||||
test_utils.closeAllChatBoxes();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {});
|
||||
@ -445,7 +445,7 @@
|
||||
var contact_jid = contact_name.replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||
spyOn(this, 'emit');
|
||||
runs(function () {
|
||||
utils.openChatBoxFor(contact_jid);
|
||||
test_utils.openChatBoxFor(contact_jid);
|
||||
var chatview = converse.chatboxviews.get(contact_jid);
|
||||
expect(chatview.model.get('minimized')).toBeFalsy();
|
||||
chatview.$el.find('.toggle-chatbox-button').click();
|
||||
@ -505,8 +505,8 @@
|
||||
spyOn(converse, 'emit');
|
||||
var contact_name = mock.cur_names[1];
|
||||
var contact_jid = contact_name.replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||
utils.openChatBoxFor(contact_jid);
|
||||
utils.clearChatBoxMessages(contact_jid);
|
||||
test_utils.openChatBoxFor(contact_jid);
|
||||
test_utils.clearChatBoxMessages(contact_jid);
|
||||
var one_day_ago = moment();
|
||||
one_day_ago.subtract('days', 1);
|
||||
var message = 'This is a day old message';
|
||||
@ -574,7 +574,7 @@
|
||||
spyOn(converse, 'emit');
|
||||
var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||
runs(function () {
|
||||
utils.openChatBoxFor(contact_jid);
|
||||
test_utils.openChatBoxFor(contact_jid);
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {
|
||||
@ -582,7 +582,7 @@
|
||||
var view = this.chatboxviews.get(contact_jid);
|
||||
var message = 'This message is sent from this chatbox';
|
||||
spyOn(view, 'sendMessage').andCallThrough();
|
||||
utils.sendMessage(view, message);
|
||||
test_utils.sendMessage(view, message);
|
||||
expect(view.sendMessage).toHaveBeenCalled();
|
||||
expect(view.model.messages.length, 2);
|
||||
expect(converse.emit.mostRecentCall.args, ['messageSend', message]);
|
||||
@ -592,11 +592,11 @@
|
||||
|
||||
it("is sanitized to prevent Javascript injection attacks", $.proxy(function () {
|
||||
var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||
utils.openChatBoxFor(contact_jid);
|
||||
test_utils.openChatBoxFor(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);
|
||||
test_utils.sendMessage(view, message);
|
||||
expect(view.sendMessage).toHaveBeenCalled();
|
||||
var msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-message-content');
|
||||
expect(msg.text()).toEqual(message);
|
||||
@ -605,11 +605,11 @@
|
||||
|
||||
it("can contain hyperlinks, which will be clickable", $.proxy(function () {
|
||||
var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||
utils.openChatBoxFor(contact_jid);
|
||||
test_utils.openChatBoxFor(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);
|
||||
test_utils.sendMessage(view, message);
|
||||
expect(view.sendMessage).toHaveBeenCalled();
|
||||
var msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-message-content');
|
||||
expect(msg.text()).toEqual(message);
|
||||
@ -618,7 +618,7 @@
|
||||
|
||||
it("should display emoticons correctly", $.proxy(function () {
|
||||
var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||
utils.openChatBoxFor(contact_jid);
|
||||
test_utils.openChatBoxFor(contact_jid);
|
||||
var view = this.chatboxviews.get(contact_jid);
|
||||
var messages = [':)', ';)', ':D', ':P', '8)', '>:)', ':S', ':\\', '>:(', ':(', ':O', '(^.^)b', '<3'];
|
||||
var emoticons = [
|
||||
@ -633,7 +633,7 @@
|
||||
spyOn(view, 'sendMessage').andCallThrough();
|
||||
for (var i = 0; i < messages.length; i++) {
|
||||
var message = messages[i];
|
||||
utils.sendMessage(view, message);
|
||||
test_utils.sendMessage(view, message);
|
||||
expect(view.sendMessage).toHaveBeenCalled();
|
||||
var msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-message-content');
|
||||
expect(msg.html()).toEqual(emoticons[i]);
|
||||
@ -642,33 +642,33 @@
|
||||
|
||||
it("will have properly escaped URLs", $.proxy(function () {
|
||||
var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||
utils.openChatBoxFor(contact_jid);
|
||||
test_utils.openChatBoxFor(contact_jid);
|
||||
var view = this.chatboxviews.get(contact_jid);
|
||||
spyOn(view, 'sendMessage').andCallThrough();
|
||||
|
||||
var message = "http://www.opkode.com/'onmouseover='alert(1)'whatever";
|
||||
utils.sendMessage(view, message);
|
||||
test_utils.sendMessage(view, message);
|
||||
expect(view.sendMessage).toHaveBeenCalled();
|
||||
var msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-message-content');
|
||||
expect(msg.text()).toEqual(message);
|
||||
expect(msg.html()).toEqual('<a target="_blank" href="http://www.opkode.com/%27onmouseover=%27alert%281%29%27whatever">http://www.opkode.com/\'onmouseover=\'alert(1)\'whatever</a>');
|
||||
|
||||
message = 'http://www.opkode.com/"onmouseover="alert(1)"whatever';
|
||||
utils.sendMessage(view, message);
|
||||
test_utils.sendMessage(view, message);
|
||||
expect(view.sendMessage).toHaveBeenCalled();
|
||||
msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-message-content');
|
||||
expect(msg.text()).toEqual(message);
|
||||
expect(msg.html()).toEqual('<a target="_blank" href="http://www.opkode.com/%22onmouseover=%22alert%281%29%22whatever">http://www.opkode.com/"onmouseover="alert(1)"whatever</a>');
|
||||
|
||||
message = "https://en.wikipedia.org/wiki/Ender's_Game";
|
||||
utils.sendMessage(view, message);
|
||||
test_utils.sendMessage(view, message);
|
||||
expect(view.sendMessage).toHaveBeenCalled();
|
||||
msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-message-content');
|
||||
expect(msg.text()).toEqual(message);
|
||||
expect(msg.html()).toEqual('<a target="_blank" href="https://en.wikipedia.org/wiki/Ender%27s_Game">https://en.wikipedia.org/wiki/Ender\'s_Game</a>');
|
||||
|
||||
message = "https://en.wikipedia.org/wiki/Ender%27s_Game";
|
||||
utils.sendMessage(view, message);
|
||||
test_utils.sendMessage(view, message);
|
||||
expect(view.sendMessage).toHaveBeenCalled();
|
||||
msg = view.$el.find('.chat-content').find('.chat-message').last().find('.chat-message-content');
|
||||
expect(msg.text()).toEqual(message);
|
||||
@ -680,24 +680,24 @@
|
||||
|
||||
describe("Special Messages", $.proxy(function () {
|
||||
beforeEach(function () {
|
||||
utils.closeAllChatBoxes();
|
||||
utils.removeControlBox();
|
||||
test_utils.closeAllChatBoxes();
|
||||
test_utils.removeControlBox();
|
||||
converse.roster.browserStorage._clear();
|
||||
utils.initConverse();
|
||||
utils.createContacts();
|
||||
utils.openControlBox();
|
||||
utils.openContactsPanel();
|
||||
test_utils.initConverse();
|
||||
test_utils.createContacts();
|
||||
test_utils.openControlBox();
|
||||
test_utils.openContactsPanel();
|
||||
});
|
||||
|
||||
it("'/clear' can be used to clear messages in a conversation", $.proxy(function () {
|
||||
spyOn(converse, 'emit');
|
||||
var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||
utils.openChatBoxFor(contact_jid);
|
||||
test_utils.openChatBoxFor(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).
|
||||
utils.sendMessage(view, message);
|
||||
test_utils.sendMessage(view, message);
|
||||
expect(view.model.messages.length > 0).toBeTruthy();
|
||||
expect(view.model.messages.browserStorage.records.length > 0).toBeTruthy();
|
||||
expect(converse.emit).toHaveBeenCalledWith('messageSend', message);
|
||||
@ -709,7 +709,7 @@
|
||||
spyOn(window, 'confirm').andCallFake(function () {
|
||||
return true;
|
||||
});
|
||||
utils.sendMessage(view, message);
|
||||
test_utils.sendMessage(view, message);
|
||||
expect(view.sendMessage).toHaveBeenCalled();
|
||||
expect(view.clearMessages).toHaveBeenCalled();
|
||||
expect(window.confirm).toHaveBeenCalled();
|
||||
@ -775,5 +775,5 @@
|
||||
expect(this.msg_counter).toBe(0);
|
||||
}, converse));
|
||||
}, converse));
|
||||
}, converse, mock, utils));
|
||||
}, converse, mock, test_utils));
|
||||
}));
|
||||
|
@ -1,25 +1,25 @@
|
||||
(function (root, factory) {
|
||||
define([
|
||||
"mock",
|
||||
"utils"
|
||||
], function (mock, utils) {
|
||||
return factory(mock, utils);
|
||||
"test_utils"
|
||||
], function (mock, test_utils) {
|
||||
return factory(mock, test_utils);
|
||||
}
|
||||
);
|
||||
} (this, function (mock, utils) {
|
||||
return describe("ChatRooms", $.proxy(function (mock, utils) {
|
||||
} (this, function (mock, test_utils) {
|
||||
return describe("ChatRooms", $.proxy(function (mock, test_utils) {
|
||||
describe("A Chat Room", $.proxy(function () {
|
||||
beforeEach(function () {
|
||||
runs(function () {
|
||||
utils.closeAllChatBoxes();
|
||||
test_utils.closeAllChatBoxes();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {
|
||||
utils.openControlBox();
|
||||
test_utils.openControlBox();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {
|
||||
utils.openRoomsPanel();
|
||||
test_utils.openRoomsPanel();
|
||||
});
|
||||
waits(501);
|
||||
runs(function () {
|
||||
@ -35,7 +35,7 @@
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {
|
||||
utils.closeControlBox();
|
||||
test_utils.closeControlBox();
|
||||
});
|
||||
waits(250);
|
||||
runs(function () {});
|
||||
@ -116,7 +116,7 @@
|
||||
// We instantiate a new ChatBoxes collection, which by default
|
||||
// will be empty.
|
||||
spyOn(this.chatboxviews, 'trimChats');
|
||||
utils.openControlBox();
|
||||
test_utils.openControlBox();
|
||||
var newchatboxes = new this.ChatBoxes();
|
||||
expect(newchatboxes.length).toEqual(0);
|
||||
// The chatboxes will then be fetched from browserStorage inside the
|
||||
@ -350,5 +350,5 @@
|
||||
expect(view.$el.find('.chat-body p').text()).toBe("This room has reached it's maximum number of occupants");
|
||||
}, converse));
|
||||
}, converse));
|
||||
}, converse, mock, utils));
|
||||
}, converse, mock, test_utils));
|
||||
}));
|
||||
|
@ -1,12 +1,12 @@
|
||||
(function (root, factory) {
|
||||
define([
|
||||
"mock",
|
||||
"utils"
|
||||
], function (mock, utils) {
|
||||
return factory(mock, utils);
|
||||
"test_utils"
|
||||
], function (mock, test_utils) {
|
||||
return factory(mock, test_utils);
|
||||
}
|
||||
);
|
||||
} (this, function (mock, utils) {
|
||||
} (this, function (mock, test_utils) {
|
||||
|
||||
var checkHeaderToggling = function ($header) {
|
||||
var $toggle = $header.find('a.group-toggle');
|
||||
@ -24,16 +24,16 @@
|
||||
expect($header.nextUntil('dt', 'dd').length === $header.nextUntil('dt', 'dd:visible').length).toBeTruthy();
|
||||
};
|
||||
|
||||
describe("The Control Box", $.proxy(function (mock, utils) {
|
||||
describe("The Control Box", $.proxy(function (mock, test_utils) {
|
||||
beforeEach(function () {
|
||||
runs(function () {
|
||||
utils.openControlBox();
|
||||
test_utils.openControlBox();
|
||||
});
|
||||
});
|
||||
|
||||
it("can be opened by clicking a DOM element with class 'toggle-controlbox'", $.proxy(function () {
|
||||
runs(function () {
|
||||
utils.closeControlBox();
|
||||
test_utils.closeControlBox();
|
||||
});
|
||||
waits(50);
|
||||
runs(function () {
|
||||
@ -59,7 +59,7 @@
|
||||
describe("The Status Widget", $.proxy(function () {
|
||||
|
||||
beforeEach(function () {
|
||||
utils.openControlBox();
|
||||
test_utils.openControlBox();
|
||||
});
|
||||
|
||||
it("shows the user's chat status, which is online by default", $.proxy(function () {
|
||||
@ -120,9 +120,9 @@
|
||||
});
|
||||
}, converse));
|
||||
}, converse));
|
||||
}, converse, mock, utils));
|
||||
}, converse, mock, test_utils));
|
||||
|
||||
describe("The Contacts Roster", $.proxy(function (mock, utils) {
|
||||
describe("The Contacts Roster", $.proxy(function (mock, test_utils) {
|
||||
|
||||
describe("A Roster Group", $.proxy(function () {
|
||||
|
||||
@ -135,7 +135,7 @@
|
||||
});
|
||||
|
||||
function _clearContacts () {
|
||||
utils.clearBrowserStorage();
|
||||
test_utils.clearBrowserStorage();
|
||||
converse.rosterview.model.reset();
|
||||
}
|
||||
|
||||
@ -146,8 +146,8 @@
|
||||
spyOn(this.rosterview, 'update').andCallThrough();
|
||||
converse.rosterview.render();
|
||||
|
||||
utils.createContacts('pending');
|
||||
utils.createContacts('requesting');
|
||||
test_utils.createContacts('pending');
|
||||
test_utils.createContacts('requesting');
|
||||
var groups = {
|
||||
'colleagues': 3,
|
||||
'friends & acquaintences': 3,
|
||||
@ -243,14 +243,14 @@
|
||||
|
||||
describe("Pending Contacts", $.proxy(function () {
|
||||
function _clearContacts () {
|
||||
utils.clearBrowserStorage();
|
||||
test_utils.clearBrowserStorage();
|
||||
converse.rosterview.model.reset();
|
||||
}
|
||||
|
||||
function _addContacts () {
|
||||
_clearContacts();
|
||||
// Must be initialized, so that render is called and documentFragment set up.
|
||||
utils.createContacts('pending').openControlBox().openContactsPanel();
|
||||
test_utils.createContacts('pending').openControlBox().openContactsPanel();
|
||||
}
|
||||
|
||||
it("can be collapsed under their own header", $.proxy(function () {
|
||||
@ -350,13 +350,13 @@
|
||||
|
||||
describe("Existing Contacts", $.proxy(function () {
|
||||
function _clearContacts () {
|
||||
utils.clearBrowserStorage();
|
||||
test_utils.clearBrowserStorage();
|
||||
converse.rosterview.model.reset();
|
||||
}
|
||||
|
||||
var _addContacts = function () {
|
||||
_clearContacts();
|
||||
utils.createContacts().openControlBox().openContactsPanel();
|
||||
test_utils.createContacts().openControlBox().openContactsPanel();
|
||||
};
|
||||
|
||||
it("can be collapsed under their own header", $.proxy(function () {
|
||||
@ -561,13 +561,13 @@
|
||||
describe("Requesting Contacts", $.proxy(function () {
|
||||
beforeEach($.proxy(function () {
|
||||
runs(function () {
|
||||
utils.clearBrowserStorage();
|
||||
test_utils.clearBrowserStorage();
|
||||
converse.rosterview.model.reset();
|
||||
utils.createContacts('requesting').openControlBox();
|
||||
test_utils.createContacts('requesting').openControlBox();
|
||||
});
|
||||
waits(50);
|
||||
runs(function () {
|
||||
utils.openContactsPanel();
|
||||
test_utils.openContactsPanel();
|
||||
});
|
||||
}, converse));
|
||||
|
||||
@ -646,7 +646,7 @@
|
||||
spyOn(converse, 'emit');
|
||||
spyOn(this.connection.roster, 'unauthorize');
|
||||
spyOn(window, 'confirm').andReturn(true);
|
||||
utils.createContacts('requesting').openControlBox();
|
||||
test_utils.createContacts('requesting').openControlBox();
|
||||
var name = mock.req_names.sort()[1];
|
||||
var jid = name.replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||
converse.rosterview.$el.find(".req-contact-name:contains('"+name+"')")
|
||||
@ -661,10 +661,10 @@
|
||||
|
||||
describe("All Contacts", $.proxy(function () {
|
||||
beforeEach($.proxy(function () {
|
||||
utils.clearBrowserStorage();
|
||||
test_utils.clearBrowserStorage();
|
||||
converse.rosterview.model.reset();
|
||||
utils.createContacts('all').openControlBox();
|
||||
utils.openContactsPanel();
|
||||
test_utils.createContacts('all').openControlBox();
|
||||
test_utils.openContactsPanel();
|
||||
}, converse));
|
||||
|
||||
it("are saved to, and can be retrieved from, browserStorage", $.proxy(function () {
|
||||
@ -700,9 +700,9 @@
|
||||
}
|
||||
}, converse));
|
||||
}, converse));
|
||||
}, converse, mock, utils));
|
||||
}, converse, mock, test_utils));
|
||||
|
||||
describe("The 'Add Contact' widget", $.proxy(function (mock, utils) {
|
||||
describe("The 'Add Contact' widget", $.proxy(function (mock, test_utils) {
|
||||
it("opens up an add form when you click on it", $.proxy(function () {
|
||||
var panel = this.chatboxviews.get('controlbox').contactspanel;
|
||||
spyOn(panel, 'toggleContactForm').andCallThrough();
|
||||
@ -713,16 +713,16 @@
|
||||
panel.$el.find('a.toggle-xmpp-contact-form').click();
|
||||
}, converse));
|
||||
|
||||
}, converse, mock, utils));
|
||||
}, converse, mock, test_utils));
|
||||
|
||||
describe("The Controlbox Tabs", $.proxy(function () {
|
||||
beforeEach($.proxy(function () {
|
||||
runs(function () {
|
||||
utils.closeAllChatBoxes();
|
||||
test_utils.closeAllChatBoxes();
|
||||
});
|
||||
waits(50);
|
||||
runs(function () {
|
||||
utils.openControlBox();
|
||||
test_utils.openControlBox();
|
||||
});
|
||||
}, converse));
|
||||
|
||||
@ -739,11 +739,11 @@
|
||||
describe("chatrooms panel", $.proxy(function () {
|
||||
beforeEach($.proxy(function () {
|
||||
runs(function () {
|
||||
utils.closeAllChatBoxes();
|
||||
test_utils.closeAllChatBoxes();
|
||||
});
|
||||
waits(50);
|
||||
runs(function () {
|
||||
utils.openControlBox();
|
||||
test_utils.openControlBox();
|
||||
});
|
||||
}, converse));
|
||||
|
||||
@ -792,5 +792,5 @@
|
||||
}, converse));
|
||||
}, converse));
|
||||
}, converse));
|
||||
}, converse, mock, utils));
|
||||
}, converse, mock, test_utils));
|
||||
}));
|
||||
|
@ -1,13 +1,13 @@
|
||||
(function (root, factory) {
|
||||
define([
|
||||
"mock",
|
||||
"utils"
|
||||
], function (mock, utils) {
|
||||
return factory(mock, utils);
|
||||
"test_utils"
|
||||
], function (mock, test_utils) {
|
||||
return factory(mock, test_utils);
|
||||
}
|
||||
);
|
||||
} (this, function (mock, utils) {
|
||||
return describe("Converse", $.proxy(function(mock, utils) {
|
||||
} (this, function (mock, test_utils) {
|
||||
return describe("Converse", $.proxy(function(mock, test_utils) {
|
||||
|
||||
beforeEach($.proxy(function () {
|
||||
window.localStorage.clear();
|
||||
@ -43,5 +43,5 @@
|
||||
// Restore the connection
|
||||
converse.connection = old_connection;
|
||||
}, converse));
|
||||
}, converse, mock, utils));
|
||||
}, converse, mock, test_utils));
|
||||
}));
|
||||
|
@ -1,13 +1,13 @@
|
||||
(function (root, factory) {
|
||||
define([
|
||||
"mock",
|
||||
"utils"
|
||||
], function (mock, utils) {
|
||||
return factory(mock, utils);
|
||||
"test_utils"
|
||||
], function (mock, test_utils) {
|
||||
return factory(mock, test_utils);
|
||||
}
|
||||
);
|
||||
} (this, function (mock, utils) {
|
||||
return describe("The Converse Event Emitter", $.proxy(function(mock, utils) {
|
||||
} (this, function (mock, test_utils) {
|
||||
return describe("The Converse Event Emitter", $.proxy(function(mock, test_utils) {
|
||||
window.localStorage.clear();
|
||||
window.sessionStorage.clear();
|
||||
|
||||
@ -64,5 +64,5 @@
|
||||
expect(this.anotherCallback.callCount, 3);
|
||||
expect(this.neverCalled).not.toHaveBeenCalled();
|
||||
});
|
||||
}, converse, mock, utils));
|
||||
}, converse, mock, test_utils));
|
||||
}));
|
||||
|
@ -1,23 +1,23 @@
|
||||
(function (root, factory) {
|
||||
define([
|
||||
"mock",
|
||||
"utils"
|
||||
], function (mock, utils) {
|
||||
return factory(mock, utils);
|
||||
"test_utils"
|
||||
], function (mock, test_utils) {
|
||||
return factory(mock, test_utils);
|
||||
}
|
||||
);
|
||||
} (this, function (mock, utils) {
|
||||
return describe("The Minimized Chats Widget", $.proxy(function(mock, utils) {
|
||||
} (this, function (mock, test_utils) {
|
||||
return describe("The Minimized Chats Widget", $.proxy(function(mock, test_utils) {
|
||||
|
||||
beforeEach(function () {
|
||||
runs(function () {
|
||||
utils.closeAllChatBoxes();
|
||||
utils.removeControlBox();
|
||||
test_utils.closeAllChatBoxes();
|
||||
test_utils.removeControlBox();
|
||||
converse.roster.browserStorage._clear();
|
||||
utils.initConverse();
|
||||
utils.createContacts();
|
||||
utils.openControlBox();
|
||||
utils.openContactsPanel();
|
||||
test_utils.initConverse();
|
||||
test_utils.createContacts();
|
||||
test_utils.openControlBox();
|
||||
test_utils.openContactsPanel();
|
||||
converse.minimized_chats.toggleview.model.browserStorage._clear();
|
||||
converse.minimized_chats.initToggle();
|
||||
});
|
||||
@ -26,7 +26,7 @@
|
||||
it("shows chats that have been minimized", $.proxy(function () {
|
||||
var contact_jid, chatview;
|
||||
contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||
utils.openChatBoxFor(contact_jid);
|
||||
test_utils.openChatBoxFor(contact_jid);
|
||||
chatview = converse.chatboxviews.get(contact_jid);
|
||||
expect(chatview.model.get('minimized')).toBeFalsy();
|
||||
expect(this.minimized_chats.$el.is(':visible')).toBeFalsy();
|
||||
@ -37,7 +37,7 @@
|
||||
expect(this.minimized_chats.keys()[0]).toBe(contact_jid);
|
||||
|
||||
contact_jid = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||
utils.openChatBoxFor(contact_jid);
|
||||
test_utils.openChatBoxFor(contact_jid);
|
||||
chatview = converse.chatboxviews.get(contact_jid);
|
||||
expect(chatview.model.get('minimized')).toBeFalsy();
|
||||
chatview.$el.find('.toggle-chatbox-button').click();
|
||||
@ -49,7 +49,7 @@
|
||||
|
||||
it("can be toggled to hide or show minimized chats", $.proxy(function () {
|
||||
var contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||
utils.openChatBoxFor(contact_jid);
|
||||
test_utils.openChatBoxFor(contact_jid);
|
||||
var chatview = converse.chatboxviews.get(contact_jid);
|
||||
expect(this.minimized_chats.$el.is(':visible')).toBeFalsy();
|
||||
chatview.model.set({'minimized': true});
|
||||
@ -70,7 +70,7 @@
|
||||
expect(this.minimized_chats.toggleview.$('.unread-message-count').is(':visible')).toBeFalsy();
|
||||
for (i=0; i<3; i++) {
|
||||
contact_jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
|
||||
utils.openChatBoxFor(contact_jid);
|
||||
test_utils.openChatBoxFor(contact_jid);
|
||||
chatview = converse.chatboxviews.get(contact_jid);
|
||||
chatview.model.set({'minimized': true});
|
||||
msg = $msg({
|
||||
@ -86,5 +86,5 @@
|
||||
}
|
||||
}, converse));
|
||||
|
||||
}, converse, mock, utils));
|
||||
}, converse, mock, test_utils));
|
||||
}));
|
||||
|
12
spec/otr.js
12
spec/otr.js
@ -1,13 +1,13 @@
|
||||
(function (root, factory) {
|
||||
define([
|
||||
"mock",
|
||||
"utils"
|
||||
], function (mock, utils) {
|
||||
return factory(mock, utils);
|
||||
"test_utils"
|
||||
], function (mock, test_utils) {
|
||||
return factory(mock, test_utils);
|
||||
}
|
||||
);
|
||||
} (this, function (mock, utils) {
|
||||
return describe("The OTR module", $.proxy(function(mock, utils) {
|
||||
} (this, function (mock, test_utils) {
|
||||
return describe("The OTR module", $.proxy(function(mock, test_utils) {
|
||||
|
||||
beforeEach($.proxy(function () {
|
||||
window.localStorage.clear();
|
||||
@ -36,5 +36,5 @@
|
||||
// Clean up
|
||||
this.prebind = false;
|
||||
}, converse));
|
||||
}, converse, mock, utils));
|
||||
}, converse, mock, test_utils));
|
||||
}));
|
||||
|
@ -25,6 +25,7 @@
|
||||
"strophe.disco": "components/strophe.disco/index",
|
||||
"converse-dependencies": "src/deps-no-otr",
|
||||
"jquery.browser": "components/jquery.browser/dist/jquery.browser",
|
||||
"utils": "src/utils",
|
||||
"moment":"components/momentjs/moment",
|
||||
"converse-templates":"src/templates",
|
||||
"tpl": "components/requirejs-tpl-jcbrand/tpl",
|
||||
|
@ -29,6 +29,7 @@
|
||||
"ru": "locale/ru/LC_MESSAGES/ru",
|
||||
"zh": "locale/zh/LC_MESSAGES/zh",
|
||||
"jquery.browser": "components/jquery.browser/dist/jquery.browser",
|
||||
"utils": "src/utils",
|
||||
"underscore": "components/underscore/underscore",
|
||||
"backbone": "components/backbone/backbone",
|
||||
"backbone.browserStorage": "components/backbone.browserStorage/backbone.browserStorage",
|
||||
|
@ -29,6 +29,7 @@
|
||||
"ru": "locale/ru/LC_MESSAGES/ru",
|
||||
"zh": "locale/zh/LC_MESSAGES/zh",
|
||||
"jquery.browser": "components/jquery.browser/dist/jquery.browser",
|
||||
"utils": "src/utils",
|
||||
"underscore": "components/underscore/underscore",
|
||||
"backbone": "components/backbone/backbone",
|
||||
"backbone.browserStorage": "components/backbone.browserStorage/backbone.browserStorage",
|
||||
|
@ -35,6 +35,7 @@
|
||||
"backbone.overview": "components/backbone.overview/backbone.overview",
|
||||
"bootstrap": "components/bootstrap/dist/js/bootstrap", // XXX: Only required for https://conversejs.org website
|
||||
"jquery.easing": "components/jquery-easing-original/jquery.easing.1.3", // XXX: Only required for https://conversejs.org website
|
||||
"utils": "src/utils",
|
||||
"strophe": "components/strophe/strophe",
|
||||
"strophe.muc": "components/strophe.muc/index",
|
||||
"strophe.roster": "components/strophe.roster/index",
|
||||
|
@ -29,6 +29,7 @@
|
||||
"ru": "locale/ru/LC_MESSAGES/ru",
|
||||
"zh": "locale/zh/LC_MESSAGES/zh",
|
||||
"jquery.browser": "components/jquery.browser/dist/jquery.browser",
|
||||
"utils": "src/utils",
|
||||
"underscore": "components/underscore/underscore",
|
||||
"backbone": "components/backbone/backbone",
|
||||
"backbone.browserStorage": "components/backbone.browserStorage/backbone.browserStorage",
|
||||
|
@ -5,6 +5,7 @@ define("converse-dependencies", [
|
||||
"backbone.browserStorage",
|
||||
"backbone.overview",
|
||||
"jquery.browser",
|
||||
"utils",
|
||||
"strophe",
|
||||
"strophe.muc",
|
||||
"strophe.roster",
|
||||
|
@ -4,6 +4,7 @@ define("converse-dependencies", [
|
||||
"backbone.browserStorage",
|
||||
"backbone.overview",
|
||||
"jquery.browser",
|
||||
"utils",
|
||||
"strophe",
|
||||
"strophe.muc",
|
||||
"strophe.roster",
|
||||
|
@ -6,6 +6,7 @@ define("converse-dependencies", [
|
||||
"backbone.overview",
|
||||
"jquery.browser",
|
||||
"jquery.easing", // XXX: Can be removed, only for https://conversejs.org
|
||||
"utils",
|
||||
"strophe",
|
||||
"strophe.muc",
|
||||
"strophe.roster",
|
||||
|
@ -2,11 +2,12 @@ define("converse-dependencies", [
|
||||
"otr",
|
||||
"moment",
|
||||
"locales",
|
||||
"bootstrap", // XXX: Can be removed, only for https://conversejs.org
|
||||
"bootstrap", // XXX: Only for https://conversejs.org
|
||||
"backbone.browserStorage",
|
||||
"backbone.overview",
|
||||
"jquery.browser",
|
||||
"jquery.easing", // XXX: Can be removed, only for https://conversejs.org
|
||||
"jquery.easing", // XXX: Only for https://conversejs.org
|
||||
"utils",
|
||||
"strophe",
|
||||
"strophe.muc",
|
||||
"strophe.roster",
|
||||
|
@ -32,6 +32,7 @@ define("converse-templates", [
|
||||
"tpl!src/templates/room_description",
|
||||
"tpl!src/templates/room_item",
|
||||
"tpl!src/templates/room_panel",
|
||||
"tpl!src/templates/roster",
|
||||
"tpl!src/templates/roster_item",
|
||||
"tpl!src/templates/select_option",
|
||||
"tpl!src/templates/status_option",
|
||||
@ -73,11 +74,12 @@ define("converse-templates", [
|
||||
room_description: arguments[30],
|
||||
room_item: arguments[31],
|
||||
room_panel: arguments[32],
|
||||
roster_item: arguments[33],
|
||||
select_option: arguments[34],
|
||||
status_option: arguments[35],
|
||||
toggle_chats: arguments[36],
|
||||
toolbar: arguments[37],
|
||||
trimmed_chat: arguments[38]
|
||||
roster: arguments[33],
|
||||
roster_item: arguments[34],
|
||||
select_option: arguments[35],
|
||||
status_option: arguments[36],
|
||||
toggle_chats: arguments[37],
|
||||
toolbar: arguments[38],
|
||||
trimmed_chat: arguments[39]
|
||||
};
|
||||
});
|
||||
|
6
src/templates/roster.html
Normal file
6
src/templates/roster.html
Normal file
@ -0,0 +1,6 @@
|
||||
<input class="roster-filter" placeholder="{{placeholder}}">
|
||||
<select class="filter-type">
|
||||
<option value="contacts">{{label_contacts}}</option>
|
||||
<option value="groups">{{label_groups}}</option>
|
||||
</select>
|
||||
<dl class="roster-contacts" style="display: block;">
|
10
src/utils.js
Normal file
10
src/utils.js
Normal file
@ -0,0 +1,10 @@
|
||||
jQuery.fn.hasScrollBar = function() {
|
||||
if (!$.contains(document, this.get(0))) {
|
||||
return false;
|
||||
}
|
||||
if(this.parent().height() < this.get(0).scrollHeight) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Extra test dependencies
|
||||
config.paths.mock = "tests/mock";
|
||||
config.paths.utils = "tests/utils";
|
||||
config.paths.test_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";
|
||||
|
@ -1,5 +1,5 @@
|
||||
(function (root, factory) {
|
||||
define("utils", [
|
||||
define("test_utils", [
|
||||
'jquery',
|
||||
'mock'
|
||||
],
|
||||
|
Loading…
Reference in New Issue
Block a user