Commit 8c20388b authored by JC Brand's avatar JC Brand

Merge branch 'groups-refactor'

Conflicts:
	index.html
parents d24c1610 0c7252f9
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
.svn/ .svn/
.project .project
.pydevproject .pydevproject
Backbone.Overview
node_modules node_modules
components components
docs/doctrees/environment.pickle docs/doctrees/environment.pickle
......
...@@ -9,13 +9,6 @@ deactivate () { ...@@ -9,13 +9,6 @@ deactivate () {
unset _OLD_VIRTUAL_PATH unset _OLD_VIRTUAL_PATH
fi fi
# This should detect bash and zsh, which have a hash command that must
# be called to get it to forget past commands. Without forgetting
# past commands the $PATH changes we made may not be respected
if [ -n "$BASH" -o -n "$ZSH_VERSION" ] ; then
hash -r
fi
if [ -n "$_OLD_VIRTUAL_PS1" ] ; then if [ -n "$_OLD_VIRTUAL_PS1" ] ; then
PS1="$_OLD_VIRTUAL_PS1" PS1="$_OLD_VIRTUAL_PS1"
export PS1 export PS1
...@@ -32,7 +25,7 @@ deactivate () { ...@@ -32,7 +25,7 @@ deactivate () {
# unset irrelavent variables # unset irrelavent variables
deactivate nondestructive deactivate nondestructive
VIRTUAL_ENV="/home/jc/dev/converse.js" VIRTUAL_ENV="~/converse.js"
export VIRTUAL_ENV export VIRTUAL_ENV
_OLD_VIRTUAL_PATH="$PATH" _OLD_VIRTUAL_PATH="$PATH"
...@@ -54,10 +47,3 @@ if [ -z "$VIRTUAL_ENV_DISABLE_PROMPT" ] ; then ...@@ -54,10 +47,3 @@ if [ -z "$VIRTUAL_ENV_DISABLE_PROMPT" ] ; then
fi fi
export PS1 export PS1
fi fi
# This should detect bash and zsh, which have a hash command that must
# be called to get it to forget past commands. Without forgetting
# past commands the $PATH changes we made may not be respected
if [ -n "$BASH" -o -n "$ZSH_VERSION" ] ; then
hash -r
fi
...@@ -25,7 +25,9 @@ ...@@ -25,7 +25,9 @@
root.converse = factory(jQuery, _, OTR, DSA, JST, moment); root.converse = factory(jQuery, _, OTR, DSA, JST, moment);
} }
}(this, function ($, _, OTR, DSA, templates, moment) { }(this, function ($, _, OTR, DSA, templates, moment) {
"use strict"; // "use strict";
// Cannot use this due to Safari bug.
// See https://github.com/jcbrand/converse.js/issues/196
if (typeof console === "undefined" || typeof console.log === "undefined") { if (typeof console === "undefined" || typeof console.log === "undefined") {
console = { log: function () {}, error: function () {} }; console = { log: function () {}, error: function () {} };
} }
...@@ -104,7 +106,7 @@ ...@@ -104,7 +106,7 @@
if ($.browser.webkit) { if ($.browser.webkit) {
var conversejs = document.getElementById('conversejs'); var conversejs = document.getElementById('conversejs');
conversejs.style.display = 'none'; conversejs.style.display = 'none';
conversejs.style.height = conversejs.offsetHeight; conversejs.offsetHeight = conversejs.offsetHeight;
conversejs.style.display = 'block'; conversejs.style.display = 'block';
} }
} }
...@@ -122,6 +124,14 @@ ...@@ -122,6 +124,14 @@
var KEY = { var KEY = {
ENTER: 13 ENTER: 13
}; };
var STATUS_WEIGHTS = {
'offline': 6,
'unavailable': 5,
'xa': 4,
'away': 3,
'dnd': 2,
'online': 1
};
var HAS_CSPRNG = ((typeof crypto !== 'undefined') && var HAS_CSPRNG = ((typeof crypto !== 'undefined') &&
((typeof crypto.randomBytes === 'function') || ((typeof crypto.randomBytes === 'function') ||
(typeof crypto.getRandomValues === 'function') (typeof crypto.getRandomValues === 'function')
...@@ -132,6 +142,9 @@ ...@@ -132,6 +142,9 @@
(typeof DSA !== "undefined") (typeof DSA !== "undefined")
); );
var OPENED = 'opened';
var CLOSED = 'closed';
// Default configuration values // Default configuration values
// ---------------------------- // ----------------------------
this.allow_contact_requests = true; this.allow_contact_requests = true;
...@@ -146,13 +159,14 @@ ...@@ -146,13 +159,14 @@
this.cache_otr_key = false; this.cache_otr_key = false;
this.debug = false; this.debug = false;
this.default_box_height = 324; // The default height, in pixels, for the control box, chat boxes and chatrooms. this.default_box_height = 324; // The default height, in pixels, for the control box, chat boxes and chatrooms.
this.message_carbons = false;
this.expose_rid_and_sid = false; this.expose_rid_and_sid = false;
this.forward_messages = false; this.forward_messages = false;
this.hide_muc_server = false; this.hide_muc_server = false;
this.i18n = locales.en; this.i18n = locales.en;
this.message_carbons = false;
this.no_trimming = false; // Set to true for phantomjs tests (where browser apparently has no width) this.no_trimming = false; // Set to true for phantomjs tests (where browser apparently has no width)
this.prebind = false; this.prebind = false;
this.roster_groups = false;
this.show_controlbox_by_default = false; this.show_controlbox_by_default = false;
this.show_only_online_users = false; this.show_only_online_users = false;
this.show_toolbar = true; this.show_toolbar = true;
...@@ -190,10 +204,11 @@ ...@@ -190,10 +204,11 @@
'fullname', 'fullname',
'hide_muc_server', 'hide_muc_server',
'i18n', 'i18n',
'no_trimming',
'jid', 'jid',
'no_trimming',
'prebind', 'prebind',
'rid', 'rid',
'roster_groups',
'show_controlbox_by_default', 'show_controlbox_by_default',
'show_only_online_users', 'show_only_online_users',
'show_toolbar', 'show_toolbar',
...@@ -270,6 +285,18 @@ ...@@ -270,6 +285,18 @@
'xa': __('This contact is away for an extended period'), 'xa': __('This contact is away for an extended period'),
'away': __('This contact is away') 'away': __('This contact is away')
}; };
var DESC_GROUP_TOGGLE = __('Click to hide these contacts');
var HEADER_CURRENT_CONTACTS = __('My contacts');
var HEADER_PENDING_CONTACTS = __('Pending contacts');
var HEADER_REQUESTING_CONTACTS = __('Contact requests');
var HEADER_UNGROUPED = __('Ungrouped');
var HEADER_WEIGHTS = {};
HEADER_WEIGHTS[HEADER_CURRENT_CONTACTS] = 0;
HEADER_WEIGHTS[HEADER_UNGROUPED] = 1;
HEADER_WEIGHTS[HEADER_REQUESTING_CONTACTS] = 2;
HEADER_WEIGHTS[HEADER_PENDING_CONTACTS] = 3;
// Module-level variables // Module-level variables
// ---------------------- // ----------------------
...@@ -313,10 +340,10 @@ ...@@ -313,10 +340,10 @@
img_type = $vcard.find('TYPE').text(), img_type = $vcard.find('TYPE').text(),
url = $vcard.find('URL').text(); url = $vcard.find('URL').text();
if (jid) { if (jid) {
var rosteritem = converse.roster.get(jid); var contact = converse.roster.get(jid);
if (rosteritem) { if (contact) {
fullname = _.isEmpty(fullname)? rosteritem.get('fullname') || jid: fullname; fullname = _.isEmpty(fullname)? contact.get('fullname') || jid: fullname;
rosteritem.save({ contact.save({
'fullname': fullname, 'fullname': fullname,
'image_type': img_type, 'image_type': img_type,
'image': img, 'image': img,
...@@ -332,9 +359,9 @@ ...@@ -332,9 +359,9 @@
jid, jid,
function (iq) { function (iq) {
// Error callback // Error callback
var rosteritem = converse.roster.get(jid); var contact = converse.roster.get(jid);
if (rosteritem) { if (contact) {
rosteritem.save({ contact.save({
'vcard_updated': moment().format() 'vcard_updated': moment().format()
}); });
} }
...@@ -454,40 +481,6 @@ ...@@ -454,40 +481,6 @@
this.xmppstatus.fetch({success: callback, error: callback}); this.xmppstatus.fetch({success: callback, error: callback});
}; };
this.registerRosterHandler = function () {
// Register handlers that depend on the roster
this.connection.roster.registerCallback(
$.proxy(this.roster.rosterHandler, this.roster),
null, 'presence', null);
};
this.registerRosterXHandler = function () {
this.connection.addHandler(
$.proxy(this.roster.subscribeToSuggestedItems, this.roster),
'http://jabber.org/protocol/rosterx', 'message', null);
};
this.registerPresenceHandler = function () {
this.connection.addHandler(
$.proxy(function (presence) {
this.presenceHandler(presence);
return true;
}, this.roster), null, 'presence', null);
};
this.initRoster = function () {
// Set up the roster
this.roster = new this.RosterItems();
this.roster.browserStorage = new Backbone.BrowserStorage[converse.storage](
b64_sha1('converse.rosteritems-'+converse.bare_jid));
this.registerRosterHandler();
this.registerRosterXHandler();
this.registerPresenceHandler();
// Now create the view which will fetch roster items from
// browserStorage
this.rosterview = new this.RosterView({'model':this.roster});
};
this.registerGlobalEventHandlers = function () { this.registerGlobalEventHandlers = function () {
$(document).click(function() { $(document).click(function() {
if ($('.toggle-otr ul').is(':visible')) { if ($('.toggle-otr ul').is(':visible')) {
...@@ -574,7 +567,8 @@ ...@@ -574,7 +567,8 @@
this.features = new this.Features(); this.features = new this.Features();
this.enableCarbons(); this.enableCarbons();
this.initStatus($.proxy(function () { this.initStatus($.proxy(function () {
this.initRoster(); this.roster = new converse.RosterContacts();
this.rosterview = new this.RosterView({model: new this.RosterGroups()});
this.chatboxes.onConnected(); this.chatboxes.onConnected();
this.connection.roster.get(function () {}); this.connection.roster.get(function () {});
this.giveFeedback(__('Online Contacts')); this.giveFeedback(__('Online Contacts'));
...@@ -635,8 +629,7 @@ ...@@ -635,8 +629,7 @@
} }
}); });
this.Message = Backbone.Model.extend(); this.Message = Backbone.Model;
this.Messages = Backbone.Collection.extend({ this.Messages = Backbone.Collection.extend({
model: converse.Message model: converse.Message
}); });
...@@ -1343,8 +1336,8 @@ ...@@ -1343,8 +1336,8 @@
updateVCard: function () { updateVCard: function () {
var jid = this.model.get('jid'), var jid = this.model.get('jid'),
rosteritem = converse.roster.get(jid); contact = converse.roster.get(jid);
if ((rosteritem) && (!rosteritem.get('vcard_updated'))) { if ((contact) && (!contact.get('vcard_updated'))) {
converse.getVCard( converse.getVCard(
jid, jid,
$.proxy(function (jid, fullname, image, image_type, url) { $.proxy(function (jid, fullname, image, image_type, url) {
...@@ -2712,9 +2705,7 @@ ...@@ -2712,9 +2705,7 @@
}, },
toggle: function (ev) { toggle: function (ev) {
if (ev && ev.preventDefault) { if (ev && ev.preventDefault) { ev.preventDefault(); }
ev.preventDefault();
}
this.toggleview.model.save({'collapsed': !this.toggleview.model.get('collapsed')}); this.toggleview.model.save({'collapsed': !this.toggleview.model.get('collapsed')});
this.$('.minimized-chats-flyout').toggle(); this.$('.minimized-chats-flyout').toggle();
}, },
...@@ -2746,7 +2737,8 @@ ...@@ -2746,7 +2737,8 @@
}, },
updateUnreadMessagesCounter: function () { updateUnreadMessagesCounter: function () {
var ls = this.model.pluck('num_unread'), count = 0; var ls = this.model.pluck('num_unread'),
count = 0, i;
for (i=0; i<ls.length; i++) { count += ls[i]; } for (i=0; i<ls.length; i++) { count += ls[i]; }
this.toggleview.model.set({'num_unread': count}); this.toggleview.model.set({'num_unread': count});
this.render(); this.render();
...@@ -2787,7 +2779,7 @@ ...@@ -2787,7 +2779,7 @@
}, },
}); });
this.RosterItem = Backbone.Model.extend({ this.RosterContact = Backbone.Model.extend({
initialize: function (attributes, options) { initialize: function (attributes, options) {
var jid = attributes.jid; var jid = attributes.jid;
if (!attributes.fullname) { if (!attributes.fullname) {
...@@ -2797,15 +2789,15 @@ ...@@ -2797,15 +2789,15 @@
'id': jid, 'id': jid,
'user_id': Strophe.getNodeFromJid(jid), 'user_id': Strophe.getNodeFromJid(jid),
'resources': [], 'resources': [],
'groups': [],
'status': '' 'status': ''
}, attributes); }, attributes);
attrs.sorted = false;
attrs.chat_status = 'offline'; attrs.chat_status = 'offline';
this.set(attrs); this.set(attrs);
} }
}); });
this.RosterItemView = Backbone.View.extend({ this.RosterContactView = Backbone.View.extend({
tagName: 'dd', tagName: 'dd',
events: { events: {
...@@ -2815,8 +2807,27 @@ ...@@ -2815,8 +2807,27 @@
"click .remove-xmpp-contact": "removeContact" "click .remove-xmpp-contact": "removeContact"
}, },
initialize: function () {
this.model.on("change", this.onChange, 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) { openChat: function (ev) {
ev.preventDefault(); if (ev && ev.preventDefault) { ev.preventDefault(); }
return converse.chatboxviews.showChat({ return converse.chatboxviews.showChat({
'id': this.model.get('jid'), 'id': this.model.get('jid'),
'jid': this.model.get('jid'), 'jid': this.model.get('jid'),
...@@ -2829,14 +2840,16 @@ ...@@ -2829,14 +2840,16 @@
}, },
removeContact: function (ev) { removeContact: function (ev) {
ev.preventDefault(); if (ev && ev.preventDefault) { ev.preventDefault(); }
var result = confirm(__("Are you sure you want to remove this contact?")); var result = confirm(__("Are you sure you want to remove this contact?"));
if (result === true) { if (result === true) {
var bare_jid = this.model.get('jid'); var bare_jid = this.model.get('jid');
converse.connection.roster.remove(bare_jid, function (iq) { converse.connection.roster.remove(bare_jid, $.proxy(function (iq) {
converse.connection.roster.unauthorize(bare_jid); converse.connection.roster.unauthorize(bare_jid);
converse.rosterview.model.remove(bare_jid); converse.rosterview.model.remove(bare_jid);
}); this.model.destroy();
this.remove();
}, this));
} }
}, },
...@@ -2862,6 +2875,7 @@ ...@@ -2862,6 +2875,7 @@
render: function () { render: function () {
var item = this.model, var item = this.model,
ask = item.get('ask'), ask = item.get('ask'),
chat_status = item.get('chat_status'),
requesting = item.get('requesting'), requesting = item.get('requesting'),
subscription = item.get('subscription'); subscription = item.get('subscription');
...@@ -2877,10 +2891,20 @@ ...@@ -2877,10 +2891,20 @@
this.$el.removeClass(cls); this.$el.removeClass(cls);
} }
}, this); }, this);
this.$el.addClass(chat_status).data('status', chat_status);
this.$el.addClass(item.get('chat_status'));
if ((ask === 'subscribe') || (subscription === 'from')) {
if (ask === 'subscribe') { /* ask === 'subscribe'
* Means we have asked to subscribe to them.
*
* subscription === 'from'
* They are subscribed to use, but not vice versa.
* We assume that there is a pending subscription
* from us to them (otherwise we're in a state not
* supported by converse.js).
*
* So in both cases the user is a "pending" contact.
*/
this.$el.addClass('pending-xmpp-contact'); this.$el.addClass('pending-xmpp-contact');
this.$el.html(converse.templates.pending_contact( this.$el.html(converse.templates.pending_contact(
_.extend(item.toJSON(), { _.extend(item.toJSON(), {
...@@ -2900,7 +2924,7 @@ ...@@ -2900,7 +2924,7 @@
this.$el.addClass('current-xmpp-contact'); this.$el.addClass('current-xmpp-contact');
this.$el.html(converse.templates.roster_item( this.$el.html(converse.templates.roster_item(
_.extend(item.toJSON(), { _.extend(item.toJSON(), {
'desc_status': STATUSES[item.get('chat_status')||'offline'], 'desc_status': STATUSES[chat_status||'offline'],
'desc_chat': __('Click to chat with this contact'), 'desc_chat': __('Click to chat with this contact'),
'desc_remove': __('Click to remove this contact') 'desc_remove': __('Click to remove this contact')
}) })
...@@ -2910,32 +2934,21 @@ ...@@ -2910,32 +2934,21 @@
} }
}); });
this.RosterItems = Backbone.Collection.extend({ this.RosterContacts = Backbone.Collection.extend({
model: converse.RosterItem, model: converse.RosterContact,
comparator : function (rosteritem) { browserStorage: new Backbone.BrowserStorage[converse.storage](
var chat_status = rosteritem.get('chat_status'), b64_sha1('converse.contacts-'+converse.bare_jid)),
rank = 4;
switch(chat_status) { comparator: function (contact1, contact2) {
case 'offline': var name1 = contact1.get('fullname').toLowerCase();
rank = 0; var status1 = contact1.get('chat_status') || 'offline';
break; var name2 = contact2.get('fullname').toLowerCase();
case 'unavailable': var status2 = contact2.get('chat_status') || 'offline';
rank = 1; if (STATUS_WEIGHTS[status1] === STATUS_WEIGHTS[status2]) {
break; return name1 < name2 ? -1 : (name1 > name2? 1 : 0);
case 'xa': } else {
rank = 2; return STATUS_WEIGHTS[status1] < STATUS_WEIGHTS[status2] ? -1 : 1;
break;
case 'away':
rank = 3;
break;
case 'dnd':
rank = 4;
break;
case 'online':
rank = 5;
break;
} }
return rank;
}, },
subscribeToSuggestedItems: function (msg) { subscribeToSuggestedItems: function (msg) {
...@@ -3070,7 +3083,6 @@ ...@@ -3070,7 +3083,6 @@
ask: item.ask, ask: item.ask,
fullname: item.name || item.jid, fullname: item.name || item.jid,
groups: item.groups, groups: item.groups,
is_last: is_last,
jid: item.jid, jid: item.jid,
subscription: item.subscription subscription: item.subscription
}); });
...@@ -3136,8 +3148,7 @@ ...@@ -3136,8 +3148,7 @@
image: img, image: img,
image_type: img_type, image_type: img_type,
url: url, url: url,
vcard_updated: moment().format(), vcard_updated: moment().format()
is_last: true
}); });
}, this), }, this),
$.proxy(function (jid, fullname, img, img_type, url) { $.proxy(function (jid, fullname, img, img_type, url) {
...@@ -3148,8 +3159,7 @@ ...@@ -3148,8 +3159,7 @@
subscription: 'none', subscription: 'none',
ask: null, ask: null,
requesting: true, requesting: true,
fullname: jid, fullname: jid
is_last: true
}); });
}, this) }, this)
); );
...@@ -3173,7 +3183,7 @@ ...@@ -3173,7 +3183,7 @@
$show = $presence.find('show'), $show = $presence.find('show'),
chat_status = $show.text() || 'online', chat_status = $show.text() || 'online',
status_message = $presence.find('status'), status_message = $presence.find('status'),
item; contact;
if (this.isSelf(bare_jid)) { if (this.isSelf(bare_jid)) {
if ((converse.connection.jid !== jid)&&(presence_type !== 'unavailable')) { if ((converse.connection.jid !== jid)&&(presence_type !== 'unavailable')) {
...@@ -3184,9 +3194,9 @@ ...@@ -3184,9 +3194,9 @@
} else if (($presence.find('x').attr('xmlns') || '').indexOf(Strophe.NS.MUC) === 0) { } else if (($presence.find('x').attr('xmlns') || '').indexOf(Strophe.NS.MUC) === 0) {
return true; // Ignore MUC return true; // Ignore MUC
} }
item = this.get(bare_jid); contact = this.get(bare_jid);
if (item && (status_message.text() != item.get('status'))) { if (contact && (status_message.text() != contact.get('status'))) {
item.save({'status': status_message.text()}); contact.save({'status': status_message.text()});
} }
if ((presence_type === 'subscribed') || (presence_type === 'unsubscribe')) { if ((presence_type === 'subscribed') || (presence_type === 'unsubscribe')) {
return true; return true;
...@@ -3196,185 +3206,300 @@ ...@@ -3196,185 +3206,300 @@
this.unsubscribe(bare_jid); this.unsubscribe(bare_jid);
} else if (presence_type === 'unavailable') { } else if (presence_type === 'unavailable') {
if (this.removeResource(bare_jid, resource) === 0) { if (this.removeResource(bare_jid, resource) === 0) {
if (item) { if (contact) {
item.save({'chat_status': 'offline'}); contact.save({'chat_status': 'offline'});
} }
} }
} else if (item) { } else if (contact) {
// presence_type is undefined // presence_type is undefined
this.addResource(bare_jid, resource); this.addResource(bare_jid, resource);
item.save({'chat_status': chat_status}); contact.save({'chat_status': chat_status});
} }
return true; return true;
} }
}); });
this.RosterView = Backbone.Overview.extend({ this.RosterGroup = Backbone.Model.extend({
tagName: 'dl', initialize: function (attributes, options) {
id: 'converse-roster', this.set(_.extend({
description: DESC_GROUP_TOGGLE,
state: OPENED
}, attributes));
// Collection of contacts belonging to this group.
this.contacts = new converse.RosterContacts();
}
});
this.RosterGroupView = Backbone.Overview.extend({
tagName: 'dt',
className: 'roster-group',
events: {
"click a.group-toggle": "toggle"
},
initialize: function () { initialize: function () {
this.model.on("add", function (item) { this.model.contacts.on("add", this.addContact, this);
this.addRosterItemView(item).render(item); this.model.contacts.on("change:chat_status", function (contact) {
if (!item.get('vcard_updated')) { // This might be optimized by instead of first sorting, finding the correct position in positionContact
// This will update the vcard, which triggers a change this.model.contacts.sort();
// request which will rerender the roster item. this.positionContact(contact).render();
converse.getVCard(item.get('jid'));
}
}, this); }, this);
this.model.contacts.on("destroy", this.onRemove, this);
this.model.contacts.on("remove", this.onRemove, this);
converse.roster.on('change:groups', this.onContactGroupChange, this);
},
this.model.on('change', function (item) { render: function () {
if ((_.size(item.changed) === 1) && _.contains(_.keys(item.changed), 'sorted')) { this.$el.attr('data-group', this.model.get('name'));
return; this.$el.html(
} $(converse.templates.group_header({
this.updateChatBox(item).render(item); label_group: this.model.get('name'),
}, this); desc_group_toggle: this.model.get('description'),
toggle_state: this.model.get('state')
}))
);
return this;
},
this.model.on("remove", function (item) { this.removeRosterItemView(item); }, this); positionContact: function (contact) {
this.model.on("destroy", function (item) { this.removeRosterItemView(item); }, this); /* Place the contact's DOM element in the correct alphabetical
this.model.on("reset", function () { this.removeAllRosterItemViewss(); }, this); * position amongst the other contacts in this group.
*/
var view = this.get(contact.get('id'));
var index = this.model.contacts.indexOf(contact);
if (index === 0) {
this.$el.after(view.$el);
} else if (index == (this.model.contacts.length-1)) {
this.$el.nextUntil('dt').last().after(view.$el);
} else {
this.$el.nextUntil('dt').eq(index).before(view.$el);
}
return view;
},
var roster_markup = converse.templates.contacts({ toggle: function (ev) {
'label_contacts': __('My contacts') if (ev && ev.preventDefault) { ev.preventDefault(); }
}); var $el = $(ev.target);
if (converse.allow_contact_requests) { this.$el.nextUntil('dt').slideToggle();
roster_markup = if ($el.hasClass("icon-opened")) {
converse.templates.requesting_contacts({ this.model.save({state: CLOSED});
'label_contact_requests': __('Contact requests') $el.removeClass("icon-opened").addClass("icon-closed");
}) + } else {
roster_markup + $el.removeClass("icon-closed").addClass("icon-opened");
converse.templates.pending_contacts({ this.model.save({state: OPENED});
'label_pending_contacts': __('Pending contacts')
});
} }
this.$el.hide().html(roster_markup);
this.model.fetch({add: true}); // Get the cached roster items from localstorage
}, },
updateChatBox: function (item, changed) { addContact: function (contact) {
var chatbox = converse.chatboxes.get(item.get('jid')), var view = new converse.RosterContactView({model: contact});
changes = {}; this.add(contact.get('id'), view);
if (!chatbox) { var view = this.positionContact(contact).render();
return this; if (this.model.get('state') === CLOSED) {
view.$el.hide();
} }
if (_.has(item.changed, 'chat_status')) { this.$el.show();
changes.chat_status = item.get('chat_status'); },
onContactGroupChange: function (contact) {
var in_this_group = _.contains(contact.get('groups'), this.model.get('name'));
var cid = contact.get('id');
var in_this_overview = !this.get(cid);
if (in_this_group && !in_this_overview) {
this.remove(cid); // Contact has been added to this group
} else if (!in_this_group && in_this_overview) {
this.addContact(contact); // Contact has been removed from this group
} }
if (_.has(item.changed, 'status')) { },
changes.status = item.get('status');
onRemove: function (contact) {
if (this.model.contacts.length === 0) {
this.$el.hide();
} }
chatbox.save(changes); }
});
this.RosterGroups = Backbone.Collection.extend({
model: converse.RosterGroup,
comparator: function (a, b) {
/* Groups are sorted alphabetically, ignoring case.
* However, Ungrouped, Requesting Contacts and Pending Contacts
* appear last and in that order. */
a = a.get('name');
b = b.get('name');
var special_groups = _.keys(HEADER_WEIGHTS);
var a_is_special = _.contains(special_groups, a);
var b_is_special = _.contains(special_groups, b);
if (!a_is_special && !b_is_special ) {
return a.toLowerCase() < b.toLowerCase() ? -1 : (a.toLowerCase() > b.toLowerCase() ? 1 : 0);
} else if (a_is_special && b_is_special) {
return HEADER_WEIGHTS[a] < HEADER_WEIGHTS[b] ? -1 : (HEADER_WEIGHTS[a] > HEADER_WEIGHTS[b] ? 1 : 0);
} else if (!a_is_special && b_is_special) {
return (b === HEADER_CURRENT_CONTACTS) ? 1 : -1;
} else if (a_is_special && !b_is_special) {
return (a === HEADER_CURRENT_CONTACTS) ? -1 : 1;
}
},
initialize: function () {
this.browserStorage = new Backbone.BrowserStorage[converse.storage](
b64_sha1('converse.roster.groups'+converse.bare_jid));
}
});
this.RosterView = Backbone.Overview.extend({
tagName: 'dl',
id: 'converse-roster',
initialize: function () {
this.registerRosterHandler();
this.registerRosterXHandler();
this.registerPresenceHandler();
converse.roster.on("add", this.onContactAdd, this);
converse.roster.on('change', this.onContactChange, this);
converse.roster.on("destroy", this.update, this);
converse.roster.on("remove", this.update, this);
this.model.on("add", this.onGroupAdd, this);
this.model.on("reset", this.reset, this);
this.render();
this.model.fetch({add: true});
converse.roster.fetch({add: true});
},
render: function () {
this.$el.empty();
return this; return this;
}, },
addRosterItemView: function (item) { update: function () {
var view = new converse.RosterItemView({model: item}); // XXX: Is this still being used/valid?
this.add(item.id, view); var $count = $('#online-count');
$count.text('('+converse.roster.getNumOnlineContacts()+')');
if (!$count.is(':visible')) {
$count.show();
}
return this; return this;
}, },
removeAllRosterItemViewss: function () { reset: function () {
var views = this.removeAll(); converse.roster.reset();
this.render(); this.removeAll();
this.render().update();
return this; return this;
}, },
removeRosterItemView: function (item) { registerRosterHandler: function () {
if (this.get(item.id)) { // Register handlers that depend on the roster
this.get(item.id).remove(); converse.connection.roster.registerCallback(
this.render(); $.proxy(converse.roster.rosterHandler, converse.roster),
null, 'presence', null);
},
registerRosterXHandler: function () {
converse.connection.addHandler(
$.proxy(converse.roster.subscribeToSuggestedItems, converse.roster),
'http://jabber.org/protocol/rosterx', 'message', null);
},
registerPresenceHandler: function () {
converse.connection.addHandler(
$.proxy(function (presence) {
converse.roster.presenceHandler(presence);
return true;
}, this), null, 'presence', null);
},
onGroupAdd: function (group) {
var view = new converse.RosterGroupView({model: group});
this.add(group.get('name'), view.render());
this.positionGroup(view);
},
onContactAdd: function (contact) {
this.addRosterContact(contact).update();
if (!contact.get('vcard_updated')) {
// This will update the vcard, which triggers a change
// request which will rerender the roster contact.
converse.getVCard(contact.get('jid'));
} }
return this;
}, },
renderRosterItem: function (item, view) { onContactChange: function (contact) {
if ((converse.show_only_online_users) && (item.get('chat_status') !== 'online')) { this.updateChatBox(contact).update();
view.$el.remove(); },
view.delegateEvents();
updateChatBox: function (contact, changed) {
var chatbox = converse.chatboxes.get(contact.get('jid')),
changes = {};
if (!chatbox) {
return this; return this;
} }
if ($.contains(document.documentElement, view.el)) { if (_.has(contact.changed, 'chat_status')) {
view.render(); changes.chat_status = contact.get('chat_status');
}
if (_.has(contact.changed, 'status')) {
changes.status = contact.get('status');
}
chatbox.save(changes);
return this;
},
positionGroup: function (view) {
/* 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);
if (index === 0) {
this.$el.prepend(view.$el);
} else if (index == (this.model.length-1)) {
this.$('.roster-group').last().siblings('dd').last().after(view.$el);
} else { } else {
this.$el.find('#xmpp-contacts').after(view.render().el); $(this.$('.roster-group').eq(index)).before(view.$el);
} }
}, },
render: function (item) { getGroup: function (name) {
var $my_contacts = this.$el.find('#xmpp-contacts'), /* Returns the group as specified by name.
$contact_requests = this.$el.find('#xmpp-contact-requests'), * Creates the group if it doesn't exist.
$pending_contacts = this.$el.find('#pending-xmpp-contacts'), */
sorted = false, var view = this.get(name);
$count, changed_presence; if (view) {
if (item) { return view.model;
var jid = item.id,
view = this.get(item.id),
ask = item.get('ask'),
subscription = item.get('subscription'),
requesting = item.get('requesting'),
crit = {order:'asc'};
if ((ask === 'subscribe') && (subscription == 'none')) {
$pending_contacts.after(view.render().el);
$pending_contacts.after($pending_contacts.siblings('dd.pending-xmpp-contact').tsort(crit));
} else if ((ask === 'subscribe') && (subscription == 'from')) {
// TODO: We have accepted an incoming subscription
// request and (automatically) made our own subscription request back.
// It would be useful to update the roster here to show
// things are happening... (see docs/DEVELOPER.rst)
$pending_contacts.after(view.render().el);
$pending_contacts.after($pending_contacts.siblings('dd.pending-xmpp-contact').tsort(crit));
} else if (requesting === true) {
$contact_requests.after(view.render().el);
$contact_requests.after($contact_requests.siblings('dd.requesting-xmpp-contact').tsort(crit));
} else if (subscription === 'both' || subscription === 'to') {
this.renderRosterItem(item, view);
}
changed_presence = item.changed.chat_status;
if (changed_presence) {
this.sortRoster(changed_presence);
sorted = true;
}
if (item.get('is_last')) {
if (!sorted) {
this.sortRoster(item.get('chat_status'));
}
if (!this.$el.is(':visible')) {
// Once all initial roster items have been added, we
// can show the roster.
this.$el.show();
}
}
} }
// Hide the headings if there are no contacts under them return this.model.create({name: name, id: b64_sha1(name)});
_.each([$my_contacts, $contact_requests, $pending_contacts], function (h) { },
if (h.nextUntil('dt').length) {
if (!h.is(':visible')) { addContactToGroup: function (contact, name) {
h.show(); this.getGroup(name).contacts.add(contact);
} },
}
else if (h.is(':visible')) { addCurrentContact: function (contact) {
h.hide(); var groups;
if (converse.roster_groups) {
groups = contact.get('groups');
if (groups.length === 0) {
groups = [HEADER_UNGROUPED];
} }
}); } else {
$count = $('#online-count'); groups = [HEADER_CURRENT_CONTACTS];
$count.text('('+this.model.getNumOnlineContacts()+')');
if (!$count.is(':visible')) {
$count.show();
} }
converse.emit('rosterViewUpdated'); _.each(groups, $.proxy(function (name) {
return this; this.addContactToGroup(contact, name);
}, this));
}, },
sortRoster: function (chat_status) { addRosterContact: function (contact) {
var $my_contacts = this.$el.find('#xmpp-contacts'); var view;
$my_contacts.siblings('dd.current-xmpp-contact.'+chat_status).tsort('a', {order:'asc'}); if (contact.get('subscription') === 'both' || contact.get('subscription') === 'to') {
$my_contacts.after($my_contacts.siblings('dd.current-xmpp-contact.offline')); this.addCurrentContact(contact);
$my_contacts.after($my_contacts.siblings('dd.current-xmpp-contact.unavailable')); } else {
$my_contacts.after($my_contacts.siblings('dd.current-xmpp-contact.xa')); view = (new converse.RosterContactView({model: contact})).render();
$my_contacts.after($my_contacts.siblings('dd.current-xmpp-contact.away')); if ((contact.get('ask') === 'subscribe') || (contact.get('subscription') === 'from')) {
$my_contacts.after($my_contacts.siblings('dd.current-xmpp-contact.dnd')); this.addContactToGroup(contact, HEADER_PENDING_CONTACTS);
$my_contacts.after($my_contacts.siblings('dd.current-xmpp-contact.online')); } else if (contact.get('requesting') === true) {
this.addContactToGroup(contact, HEADER_REQUESTING_CONTACTS);
}
}
return this;
} }
}); });
......
...@@ -38,8 +38,14 @@ ...@@ -38,8 +38,14 @@
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.icon-closed:before {
content: "\25ba";
}
.icon-opened:before {
content: "\25bc";
}
.icon-checkmark:before { .icon-checkmark:before {
content: "\e600"; content: "\2713";
} }
#conversejs .icon-home:before { #conversejs .icon-home:before {
content: "\e000"; content: "\e000";
...@@ -812,8 +818,7 @@ dl.add-converse-contact { ...@@ -812,8 +818,7 @@ dl.add-converse-contact {
top: 1px; top: 1px;
} }
#conversejs .controlbox-pane dt { #conversejs .controlbox-pane dt {
margin: 0; padding: 3px;
padding-top: 0.5em;
} }
#conversejs .chatroom-form-container { #conversejs .chatroom-form-container {
height: 100%; height: 100%;
...@@ -847,11 +852,11 @@ dl.add-converse-contact { ...@@ -847,11 +852,11 @@ dl.add-converse-contact {
#conversejs .chatroom-form label select { #conversejs .chatroom-form label select {
float: right; float: right;
} }
#conversejs #converse-roster dd.odd { #converse-roster dd.odd {
background-color: #DCEAC5; background-color: #DCEAC5;
/* Make this difference */ /* Make this difference */
} }
#conversejs #converse-roster dd.current-xmpp-contact span { #converse-roster dd.current-xmpp-contact span {
font-size: 16px; font-size: 16px;
float: left; float: left;
color: #4f4f4f; color: #4f4f4f;
...@@ -860,18 +865,25 @@ dl.add-converse-contact { ...@@ -860,18 +865,25 @@ dl.add-converse-contact {
margin-left: 0.5em; margin-left: 0.5em;
float: right; float: right;
} }
#conversejs #converse-roster dd a, #converse-roster dd a,
#conversejs #converse-roster dd span { #converse-roster dd span {
text-shadow: 0 1px 0 #fafafa; text-shadow: 0 1px 0 #fafafa;
display: inline-block; display: inline-block;
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
#conversejs #converse-roster dd span { #conversejs #converse-roster span.req-contact-name {
width: 65%;
}
#conversejs #converse-roster span.pending-contact-name,
#conversejs #converse-roster a.open-chat {
width: 80%;
}
#converse-roster dd span {
padding: 0 5px 0 0; padding: 0 5px 0 0;
} }
#conversejs #converse-roster { #converse-roster {
overflow-y: auto; overflow-y: auto;
overflow-x: hidden; overflow-x: hidden;
width: 100%; width: 100%;
...@@ -880,6 +892,9 @@ dl.add-converse-contact { ...@@ -880,6 +892,9 @@ dl.add-converse-contact {
height: 254px; height: 254px;
height: calc(100% - 70px); height: calc(100% - 70px);
} }
#converse-roster .group-toggle {
color: #666;
}
#conversejs dd.available-chatroom { #conversejs dd.available-chatroom {
overflow-x: hidden; overflow-x: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
...@@ -889,8 +904,8 @@ dl.add-converse-contact { ...@@ -889,8 +904,8 @@ dl.add-converse-contact {
#conversejs dd.available-chatroom a.open-room { #conversejs dd.available-chatroom a.open-room {
width: 148px; width: 148px;
} }
#conversejs #available-chatrooms dt, #available-chatrooms dt,
#conversejs #converse-roster dt { #converse-roster dt {
font-weight: normal; font-weight: normal;
font-size: 13px; font-size: 13px;
color: #666; color: #666;
...@@ -898,7 +913,7 @@ dl.add-converse-contact { ...@@ -898,7 +913,7 @@ dl.add-converse-contact {
padding: 0.3em 0 0 0.5em; padding: 0.3em 0 0 0.5em;
text-shadow: 0 1px 0 #fafafa; text-shadow: 0 1px 0 #fafafa;
} }
#conversejs #converse-roster dt { #converse-roster dt {
display: none; display: none;
} }
#conversejs .room-info { #conversejs .room-info {
...@@ -950,6 +965,11 @@ dl.add-converse-contact { ...@@ -950,6 +965,11 @@ dl.add-converse-contact {
#conversejs #converse-roster dd { #conversejs #converse-roster dd {
line-height: 16px; line-height: 16px;
} }
#conversejs .group-toggle {
display: block;
width: 100%;
}
#conversejs .roster-group:hover,
#conversejs dd.available-chatroom:hover, #conversejs dd.available-chatroom:hover,
#conversejs #converse-roster dd:hover { #conversejs #converse-roster dd:hover {
background-color: #eee; background-color: #eee;
...@@ -967,9 +987,6 @@ dl.add-converse-contact { ...@@ -967,9 +987,6 @@ dl.add-converse-contact {
#conversejs #converse-roster dd:hover a.remove-xmpp-contact { #conversejs #converse-roster dd:hover a.remove-xmpp-contact {
display: inline-block; display: inline-block;
} }
#conversejs #converse-roster a.open-chat {
width: 80%;
}
#conversejs .chatbox, #conversejs .chatbox,
#conversejs .chatroom { #conversejs .chatroom {
height: 25px; height: 25px;
...@@ -1287,6 +1304,9 @@ input.custom-xmpp-status { ...@@ -1287,6 +1304,9 @@ input.custom-xmpp-status {
#conversejs .chatbox .dropdown dd ul li:hover { #conversejs .chatbox .dropdown dd ul li:hover {
background-color: #bed6e5; background-color: #bed6e5;
} }
#conversejs .chatbox .dropdown dd.search-xmpp ul li:hover {
background-color: #bed6e5;
}
#conversejs .xmpp-status-menu li a { #conversejs .xmpp-status-menu li a {
width: 100%; width: 100%;
} }
......
...@@ -20,10 +20,14 @@ Changelog ...@@ -20,10 +20,14 @@ Changelog
Message forwarding was before a default behavior but is now optional (and disabled by default). [jcbrand] Message forwarding was before a default behavior but is now optional (and disabled by default). [jcbrand]
* Newly opened chat boxes always appear immediately left of the controlbox. [jcbrand] * Newly opened chat boxes always appear immediately left of the controlbox. [jcbrand]
* #71 Chat boxes and rooms can be minimized. [jcbrand] * #71 Chat boxes and rooms can be minimized. [jcbrand]
* #83 Roster contacts can be shown according to their groups. [jcbrand]
Note: Converse.js can show users under groups if you have assigned them
already via another client or server configuration. There is not yet a way
to assign contacts to groups from within converse.js itself.
* #123 Show converse.js in the resource assigned to a user. [jcbrand] * #123 Show converse.js in the resource assigned to a user. [jcbrand]
* #130 Fixed bootstrap conflicts. [jcbrand] * #130 Fixed bootstrap conflicts. [jcbrand]
* #132 Support for `XEP-0280: Message Carbons <https://xmpp.org/extensions/xep-0280.html'>`_. * #132 Support for `XEP-0280: Message Carbons <https://xmpp.org/extensions/xep-0280.html'>`_.
Configured via `message_carbons <https://conversejs.org/docs/html/index.html#message_carbons>`_ [hejazee] Configured via `message_carbons <https://conversejs.org/docs/html/index.html#message_carbons>`_ [hejazee]
* #176 Add support for caching in sessionStorage as opposed to localStorage. [jcbrand] * #176 Add support for caching in sessionStorage as opposed to localStorage. [jcbrand]
* #180 RID and SID undefined [g8g3] * #180 RID and SID undefined [g8g3]
* #191 No messages history [heban] * #191 No messages history [heban]
......
...@@ -30,7 +30,7 @@ subscription and subscribes back. ...@@ -30,7 +30,7 @@ subscription and subscribes back.
<presence type="subscribed" to="contact1@localhost"/> <presence type="subscribed" to="contact1@localhost"/>
<presence type="subscribe" to="contact1@localhost"/> <presence type="subscribe" to="contact1@localhost"/>
Contact2 receives a roster update IF Contact1 is still online and likewise subscribes back, Contact2 will receive a roster update
:: ::
<iq type="set" to="contact2@localhost"> <iq type="set" to="contact2@localhost">
...@@ -39,6 +39,13 @@ Contact2 receives a roster update ...@@ -39,6 +39,13 @@ Contact2 receives a roster update
</query> </query>
</iq> </iq>
ELSE, Contact 2 will receive a roster update (but not an IQ stanza)
::
ask = null
subscription = "from"
Contact1's converse.js client will automatically Contact1's converse.js client will automatically
approve. approve.
......
...@@ -784,8 +784,6 @@ Here are the different events that are emitted: ...@@ -784,8 +784,6 @@ Here are the different events that are emitted:
+----------------------------------+---------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+ +----------------------------------+---------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
| **roster** | When the roster is updated. | ``converse.on('roster', function (items) { ... });`` | | **roster** | When the roster is updated. | ``converse.on('roster', function (items) { ... });`` |
+----------------------------------+---------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+ +----------------------------------+---------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
| **rosterViewUpdated** | Whenever the roster view (i.e. the rendered HTML) has changed. | ``converse.on('rosterViewUpdated', function (items) { ... });`` |
+----------------------------------+---------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
| **callButtonClicked** | When a call button (i.e. with class .toggle-call) on a chat box has been clicked. | ``converse.on('callButtonClicked', function (connection, model) { ... });`` | | **callButtonClicked** | When a call button (i.e. with class .toggle-call) on a chat box has been clicked. | ``converse.on('callButtonClicked', function (connection, model) { ... });`` |
+----------------------------------+---------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+ +----------------------------------+---------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------+
| **chatBoxOpened** | When a chat box has been opened. | ``converse.on('chatBoxOpened', function (chatbox) { ... });`` | | **chatBoxOpened** | When a chat box has been opened. | ``converse.on('chatBoxOpened', function (chatbox) { ... });`` |
...@@ -1003,6 +1001,18 @@ values as ``jid``, ``sid``, ``rid``. ...@@ -1003,6 +1001,18 @@ values as ``jid``, ``sid``, ``rid``.
Additionally, you have to specify ``bosh_service_url``. Additionally, you have to specify ``bosh_service_url``.
roster_groups
-------------
Default: ``false``
If set to ``true``, converse.js will show any roster groups you might have
configured.
.. Note ::
It's currently not possible to use converse.js to assign contacts to groups.
Converse.js can only show users and groups that were previously configured
elsewhere.
show_controlbox_by_default show_controlbox_by_default
-------------------------- --------------------------
......
...@@ -150,6 +150,3 @@ p { ...@@ -150,6 +150,3 @@ p {
.fs1 { .fs1 {
font-size: 32px; font-size: 32px;
} }
.fs2 {
font-size: 32px;
}
...@@ -9,27 +9,50 @@ ...@@ -9,27 +9,50 @@
<link rel="stylesheet" href="style.css"></head> <link rel="stylesheet" href="style.css"></head>
<body> <body>
<div class="bgc1 clearfix"> <div class="bgc1 clearfix">
<h1 class="mhmm mvm"><span class="fgc1">Font Name:</span> icomoon <small class="fgc1">(Glyphs:&nbsp;86)</small></h1> <h1 class="mhmm mvm"><span class="fgc1">Font Name:</span> icomoon <small class="fgc1">(Glyphs:&nbsp;88)</small></h1>
</div> </div>
<div class="clearfix mhl ptl"> <div class="clearfix mhl ptl">
<h1 class="mvm mtn bshadow fgc1">Grid Size: 16</h1> <h1 class="mvm mtn bshadow fgc1">Grid Size: 16</h1>
<div class="glyph fs1">
<div class="clearfix bshadow0 pbs">
<span class="icon-closed"></span><span class="mls"> icon-closed</span>
</div>
<fieldset class="fs0 size1of1 clearfix hidden-false">
<input type="text" readonly value="25ba" class="unit size1of2" />
<input type="text" maxlength="1" readonly value="&#x25ba;" class="unitRight size1of2 talign-right" />
</fieldset>
<div class="fs0 bshadow0 clearfix hidden-true">
<span class="unit pvs fgc1">liga: </span>
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs1">
<div class="clearfix bshadow0 pbs">
<span class="icon-opened"></span><span class="mls"> icon-opened</span>
</div>
<fieldset class="fs0 size1of1 clearfix hidden-false">
<input type="text" readonly value="25bc" class="unit size1of2" />
<input type="text" maxlength="1" readonly value="&#x25bc;" class="unitRight size1of2 talign-right" />
</fieldset>
<div class="fs0 bshadow0 clearfix hidden-true">
<span class="unit pvs fgc1">liga: </span>
<input type="text" readonly value="" class="liga unitRight" />
</div>
</div>
<div class="glyph fs1"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-checkmark"></span><span class="mls"> icon-checkmark</span> <span class="icon-checkmark"></span><span class="mls"> icon-checkmark</span>
</div> </div>
<fieldset class="fs0 size1of1 clearfix hidden-false"> <fieldset class="fs0 size1of1 clearfix hidden-false">
<input type="text" readonly value="e600" class="unit size1of2" /> <input type="text" readonly value="2713" class="unit size1of2" />
<input type="text" maxlength="1" readonly value="&#xe600;" class="unitRight size1of2 talign-right" /> <input type="text" maxlength="1" readonly value="&#x2713;" class="unitRight size1of2 talign-right" />
</fieldset> </fieldset>
<div class="fs0 bshadow0 clearfix hidden-true"> <div class="fs0 bshadow0 clearfix hidden-true">
<span class="unit pvs fgc1">liga: </span> <span class="unit pvs fgc1">liga: </span>
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
</div> <div class="glyph fs1">
<div class="clearfix mhl ptl">
<h1 class="mvm mtn bshadow fgc1">Grid Size: Unknown</h1>
<div class="glyph fs2">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-home"></span><span class="mls"> icon-home</span> <span class="icon-home"></span><span class="mls"> icon-home</span>
</div> </div>
...@@ -42,7 +65,7 @@ ...@@ -42,7 +65,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-pencil"></span><span class="mls"> icon-pencil</span> <span class="icon-pencil"></span><span class="mls"> icon-pencil</span>
</div> </div>
...@@ -55,7 +78,7 @@ ...@@ -55,7 +78,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-camera"></span><span class="mls"> icon-camera</span> <span class="icon-camera"></span><span class="mls"> icon-camera</span>
</div> </div>
...@@ -68,7 +91,7 @@ ...@@ -68,7 +91,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-camera2"></span><span class="mls"> icon-camera2</span> <span class="icon-camera2"></span><span class="mls"> icon-camera2</span>
</div> </div>
...@@ -81,9 +104,9 @@ ...@@ -81,9 +104,9 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-play"></span><span class="mls"> icon-play</span> <span class="icon-play22"></span><span class="mls"> icon-play22</span>
</div> </div>
<fieldset class="fs0 size1of1 clearfix hidden-false"> <fieldset class="fs0 size1of1 clearfix hidden-false">
<input type="text" readonly value="25d9" class="unit size1of2" /> <input type="text" readonly value="25d9" class="unit size1of2" />
...@@ -94,7 +117,7 @@ ...@@ -94,7 +117,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-music"></span><span class="mls"> icon-music</span> <span class="icon-music"></span><span class="mls"> icon-music</span>
</div> </div>
...@@ -107,7 +130,7 @@ ...@@ -107,7 +130,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-headphones"></span><span class="mls"> icon-headphones</span> <span class="icon-headphones"></span><span class="mls"> icon-headphones</span>
</div> </div>
...@@ -120,7 +143,7 @@ ...@@ -120,7 +143,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-phone"></span><span class="mls"> icon-phone</span> <span class="icon-phone"></span><span class="mls"> icon-phone</span>
</div> </div>
...@@ -133,7 +156,7 @@ ...@@ -133,7 +156,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-phone-hang-up"></span><span class="mls"> icon-phone-hang-up</span> <span class="icon-phone-hang-up"></span><span class="mls"> icon-phone-hang-up</span>
</div> </div>
...@@ -146,7 +169,7 @@ ...@@ -146,7 +169,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-address-book"></span><span class="mls"> icon-address-book</span> <span class="icon-address-book"></span><span class="mls"> icon-address-book</span>
</div> </div>
...@@ -159,7 +182,7 @@ ...@@ -159,7 +182,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-notebook"></span><span class="mls"> icon-notebook</span> <span class="icon-notebook"></span><span class="mls"> icon-notebook</span>
</div> </div>
...@@ -172,7 +195,7 @@ ...@@ -172,7 +195,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-envelop"></span><span class="mls"> icon-envelop</span> <span class="icon-envelop"></span><span class="mls"> icon-envelop</span>
</div> </div>
...@@ -185,7 +208,7 @@ ...@@ -185,7 +208,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-pushpin"></span><span class="mls"> icon-pushpin</span> <span class="icon-pushpin"></span><span class="mls"> icon-pushpin</span>
</div> </div>
...@@ -198,7 +221,7 @@ ...@@ -198,7 +221,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-bubble"></span><span class="mls"> icon-bubble</span> <span class="icon-bubble"></span><span class="mls"> icon-bubble</span>
</div> </div>
...@@ -211,7 +234,7 @@ ...@@ -211,7 +234,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-bubble2"></span><span class="mls"> icon-bubble2</span> <span class="icon-bubble2"></span><span class="mls"> icon-bubble2</span>
</div> </div>
...@@ -224,7 +247,7 @@ ...@@ -224,7 +247,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-bubbles"></span><span class="mls"> icon-bubbles</span> <span class="icon-bubbles"></span><span class="mls"> icon-bubbles</span>
</div> </div>
...@@ -237,7 +260,7 @@ ...@@ -237,7 +260,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-bubbles2"></span><span class="mls"> icon-bubbles2</span> <span class="icon-bubbles2"></span><span class="mls"> icon-bubbles2</span>
</div> </div>
...@@ -250,7 +273,7 @@ ...@@ -250,7 +273,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-bubbles3"></span><span class="mls"> icon-bubbles3</span> <span class="icon-bubbles3"></span><span class="mls"> icon-bubbles3</span>
</div> </div>
...@@ -263,7 +286,7 @@ ...@@ -263,7 +286,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-user"></span><span class="mls"> icon-user</span> <span class="icon-user"></span><span class="mls"> icon-user</span>
</div> </div>
...@@ -276,7 +299,7 @@ ...@@ -276,7 +299,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-users"></span><span class="mls"> icon-users</span> <span class="icon-users"></span><span class="mls"> icon-users</span>
</div> </div>
...@@ -289,7 +312,7 @@ ...@@ -289,7 +312,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-quotes-left"></span><span class="mls"> icon-quotes-left</span> <span class="icon-quotes-left"></span><span class="mls"> icon-quotes-left</span>
</div> </div>
...@@ -302,7 +325,7 @@ ...@@ -302,7 +325,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-spinner"></span><span class="mls"> icon-spinner</span> <span class="icon-spinner"></span><span class="mls"> icon-spinner</span>
</div> </div>
...@@ -315,7 +338,7 @@ ...@@ -315,7 +338,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-search"></span><span class="mls"> icon-search</span> <span class="icon-search"></span><span class="mls"> icon-search</span>
</div> </div>
...@@ -328,7 +351,7 @@ ...@@ -328,7 +351,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-cogs"></span><span class="mls"> icon-cogs</span> <span class="icon-cogs"></span><span class="mls"> icon-cogs</span>
</div> </div>
...@@ -341,7 +364,7 @@ ...@@ -341,7 +364,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-wrench"></span><span class="mls"> icon-wrench</span> <span class="icon-wrench"></span><span class="mls"> icon-wrench</span>
</div> </div>
...@@ -354,7 +377,7 @@ ...@@ -354,7 +377,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-unlocked"></span><span class="mls"> icon-unlocked</span> <span class="icon-unlocked"></span><span class="mls"> icon-unlocked</span>
</div> </div>
...@@ -367,7 +390,7 @@ ...@@ -367,7 +390,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-lock"></span><span class="mls"> icon-lock</span> <span class="icon-lock"></span><span class="mls"> icon-lock</span>
</div> </div>
...@@ -380,7 +403,7 @@ ...@@ -380,7 +403,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-lock2"></span><span class="mls"> icon-lock2</span> <span class="icon-lock2"></span><span class="mls"> icon-lock2</span>
</div> </div>
...@@ -393,7 +416,7 @@ ...@@ -393,7 +416,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-key"></span><span class="mls"> icon-key</span> <span class="icon-key"></span><span class="mls"> icon-key</span>
</div> </div>
...@@ -406,7 +429,7 @@ ...@@ -406,7 +429,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-key2"></span><span class="mls"> icon-key2</span> <span class="icon-key2"></span><span class="mls"> icon-key2</span>
</div> </div>
...@@ -419,7 +442,7 @@ ...@@ -419,7 +442,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-zoomout"></span><span class="mls"> icon-zoomout</span> <span class="icon-zoomout"></span><span class="mls"> icon-zoomout</span>
</div> </div>
...@@ -432,7 +455,7 @@ ...@@ -432,7 +455,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-zoomin"></span><span class="mls"> icon-zoomin</span> <span class="icon-zoomin"></span><span class="mls"> icon-zoomin</span>
</div> </div>
...@@ -445,7 +468,7 @@ ...@@ -445,7 +468,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-cog"></span><span class="mls"> icon-cog</span> <span class="icon-cog"></span><span class="mls"> icon-cog</span>
</div> </div>
...@@ -458,7 +481,7 @@ ...@@ -458,7 +481,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-remove"></span><span class="mls"> icon-remove</span> <span class="icon-remove"></span><span class="mls"> icon-remove</span>
</div> </div>
...@@ -471,7 +494,7 @@ ...@@ -471,7 +494,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-remove2"></span><span class="mls"> icon-remove2</span> <span class="icon-remove2"></span><span class="mls"> icon-remove2</span>
</div> </div>
...@@ -484,7 +507,7 @@ ...@@ -484,7 +507,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-eye"></span><span class="mls"> icon-eye</span> <span class="icon-eye"></span><span class="mls"> icon-eye</span>
</div> </div>
...@@ -497,7 +520,7 @@ ...@@ -497,7 +520,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-eye-blocked"></span><span class="mls"> icon-eye-blocked</span> <span class="icon-eye-blocked"></span><span class="mls"> icon-eye-blocked</span>
</div> </div>
...@@ -510,7 +533,7 @@ ...@@ -510,7 +533,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-attachment"></span><span class="mls"> icon-attachment</span> <span class="icon-attachment"></span><span class="mls"> icon-attachment</span>
</div> </div>
...@@ -523,7 +546,7 @@ ...@@ -523,7 +546,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-globe"></span><span class="mls"> icon-globe</span> <span class="icon-globe"></span><span class="mls"> icon-globe</span>
</div> </div>
...@@ -536,7 +559,7 @@ ...@@ -536,7 +559,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-heart"></span><span class="mls"> icon-heart</span> <span class="icon-heart"></span><span class="mls"> icon-heart</span>
</div> </div>
...@@ -549,7 +572,7 @@ ...@@ -549,7 +572,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-happy"></span><span class="mls"> icon-happy</span> <span class="icon-happy"></span><span class="mls"> icon-happy</span>
</div> </div>
...@@ -562,7 +585,7 @@ ...@@ -562,7 +585,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-thumbs-up"></span><span class="mls"> icon-thumbs-up</span> <span class="icon-thumbs-up"></span><span class="mls"> icon-thumbs-up</span>
</div> </div>
...@@ -575,7 +598,7 @@ ...@@ -575,7 +598,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-smiley"></span><span class="mls"> icon-smiley</span> <span class="icon-smiley"></span><span class="mls"> icon-smiley</span>
</div> </div>
...@@ -588,7 +611,7 @@ ...@@ -588,7 +611,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-tongue"></span><span class="mls"> icon-tongue</span> <span class="icon-tongue"></span><span class="mls"> icon-tongue</span>
</div> </div>
...@@ -601,7 +624,7 @@ ...@@ -601,7 +624,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-sad"></span><span class="mls"> icon-sad</span> <span class="icon-sad"></span><span class="mls"> icon-sad</span>
</div> </div>
...@@ -614,7 +637,7 @@ ...@@ -614,7 +637,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-wink"></span><span class="mls"> icon-wink</span> <span class="icon-wink"></span><span class="mls"> icon-wink</span>
</div> </div>
...@@ -627,7 +650,7 @@ ...@@ -627,7 +650,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-wondering"></span><span class="mls"> icon-wondering</span> <span class="icon-wondering"></span><span class="mls"> icon-wondering</span>
</div> </div>
...@@ -640,7 +663,7 @@ ...@@ -640,7 +663,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-confused"></span><span class="mls"> icon-confused</span> <span class="icon-confused"></span><span class="mls"> icon-confused</span>
</div> </div>
...@@ -653,7 +676,7 @@ ...@@ -653,7 +676,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-shocked"></span><span class="mls"> icon-shocked</span> <span class="icon-shocked"></span><span class="mls"> icon-shocked</span>
</div> </div>
...@@ -666,7 +689,7 @@ ...@@ -666,7 +689,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-evil"></span><span class="mls"> icon-evil</span> <span class="icon-evil"></span><span class="mls"> icon-evil</span>
</div> </div>
...@@ -679,7 +702,7 @@ ...@@ -679,7 +702,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-angry"></span><span class="mls"> icon-angry</span> <span class="icon-angry"></span><span class="mls"> icon-angry</span>
</div> </div>
...@@ -692,7 +715,7 @@ ...@@ -692,7 +715,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-cool"></span><span class="mls"> icon-cool</span> <span class="icon-cool"></span><span class="mls"> icon-cool</span>
</div> </div>
...@@ -705,7 +728,7 @@ ...@@ -705,7 +728,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-grin"></span><span class="mls"> icon-grin</span> <span class="icon-grin"></span><span class="mls"> icon-grin</span>
</div> </div>
...@@ -718,7 +741,7 @@ ...@@ -718,7 +741,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-info"></span><span class="mls"> icon-info</span> <span class="icon-info"></span><span class="mls"> icon-info</span>
</div> </div>
...@@ -731,7 +754,7 @@ ...@@ -731,7 +754,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-notification"></span><span class="mls"> icon-notification</span> <span class="icon-notification"></span><span class="mls"> icon-notification</span>
</div> </div>
...@@ -744,7 +767,7 @@ ...@@ -744,7 +767,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-warning"></span><span class="mls"> icon-warning</span> <span class="icon-warning"></span><span class="mls"> icon-warning</span>
</div> </div>
...@@ -757,7 +780,7 @@ ...@@ -757,7 +780,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-spell-check"></span><span class="mls"> icon-spell-check</span> <span class="icon-spell-check"></span><span class="mls"> icon-spell-check</span>
</div> </div>
...@@ -770,7 +793,7 @@ ...@@ -770,7 +793,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-volume-high"></span><span class="mls"> icon-volume-high</span> <span class="icon-volume-high"></span><span class="mls"> icon-volume-high</span>
</div> </div>
...@@ -783,7 +806,7 @@ ...@@ -783,7 +806,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-volume-medium"></span><span class="mls"> icon-volume-medium</span> <span class="icon-volume-medium"></span><span class="mls"> icon-volume-medium</span>
</div> </div>
...@@ -796,7 +819,7 @@ ...@@ -796,7 +819,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-volume-low"></span><span class="mls"> icon-volume-low</span> <span class="icon-volume-low"></span><span class="mls"> icon-volume-low</span>
</div> </div>
...@@ -809,7 +832,7 @@ ...@@ -809,7 +832,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-volume-mute"></span><span class="mls"> icon-volume-mute</span> <span class="icon-volume-mute"></span><span class="mls"> icon-volume-mute</span>
</div> </div>
...@@ -822,7 +845,7 @@ ...@@ -822,7 +845,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-volume-mute2"></span><span class="mls"> icon-volume-mute2</span> <span class="icon-volume-mute2"></span><span class="mls"> icon-volume-mute2</span>
</div> </div>
...@@ -835,7 +858,7 @@ ...@@ -835,7 +858,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-volume-decrease"></span><span class="mls"> icon-volume-decrease</span> <span class="icon-volume-decrease"></span><span class="mls"> icon-volume-decrease</span>
</div> </div>
...@@ -848,7 +871,7 @@ ...@@ -848,7 +871,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-volume-increase"></span><span class="mls"> icon-volume-increase</span> <span class="icon-volume-increase"></span><span class="mls"> icon-volume-increase</span>
</div> </div>
...@@ -861,7 +884,7 @@ ...@@ -861,7 +884,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-bold"></span><span class="mls"> icon-bold</span> <span class="icon-bold"></span><span class="mls"> icon-bold</span>
</div> </div>
...@@ -874,7 +897,7 @@ ...@@ -874,7 +897,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-underline"></span><span class="mls"> icon-underline</span> <span class="icon-underline"></span><span class="mls"> icon-underline</span>
</div> </div>
...@@ -887,7 +910,7 @@ ...@@ -887,7 +910,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-italic"></span><span class="mls"> icon-italic</span> <span class="icon-italic"></span><span class="mls"> icon-italic</span>
</div> </div>
...@@ -900,7 +923,7 @@ ...@@ -900,7 +923,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-strikethrough"></span><span class="mls"> icon-strikethrough</span> <span class="icon-strikethrough"></span><span class="mls"> icon-strikethrough</span>
</div> </div>
...@@ -913,7 +936,7 @@ ...@@ -913,7 +936,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-newtab"></span><span class="mls"> icon-newtab</span> <span class="icon-newtab"></span><span class="mls"> icon-newtab</span>
</div> </div>
...@@ -926,7 +949,7 @@ ...@@ -926,7 +949,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-youtube"></span><span class="mls"> icon-youtube</span> <span class="icon-youtube"></span><span class="mls"> icon-youtube</span>
</div> </div>
...@@ -939,7 +962,7 @@ ...@@ -939,7 +962,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-close"></span><span class="mls"> icon-close</span> <span class="icon-close"></span><span class="mls"> icon-close</span>
</div> </div>
...@@ -952,7 +975,7 @@ ...@@ -952,7 +975,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-blocked"></span><span class="mls"> icon-blocked</span> <span class="icon-blocked"></span><span class="mls"> icon-blocked</span>
</div> </div>
...@@ -965,7 +988,7 @@ ...@@ -965,7 +988,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-cancel-circle"></span><span class="mls"> icon-cancel-circle</span> <span class="icon-cancel-circle"></span><span class="mls"> icon-cancel-circle</span>
</div> </div>
...@@ -978,7 +1001,7 @@ ...@@ -978,7 +1001,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-minus"></span><span class="mls"> icon-minus</span> <span class="icon-minus"></span><span class="mls"> icon-minus</span>
</div> </div>
...@@ -991,7 +1014,7 @@ ...@@ -991,7 +1014,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-plus"></span><span class="mls"> icon-plus</span> <span class="icon-plus"></span><span class="mls"> icon-plus</span>
</div> </div>
...@@ -1004,7 +1027,7 @@ ...@@ -1004,7 +1027,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-checkbox-checked"></span><span class="mls"> icon-checkbox-checked</span> <span class="icon-checkbox-checked"></span><span class="mls"> icon-checkbox-checked</span>
</div> </div>
...@@ -1017,7 +1040,7 @@ ...@@ -1017,7 +1040,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-checkbox-unchecked"></span><span class="mls"> icon-checkbox-unchecked</span> <span class="icon-checkbox-unchecked"></span><span class="mls"> icon-checkbox-unchecked</span>
</div> </div>
...@@ -1030,7 +1053,7 @@ ...@@ -1030,7 +1053,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-checkbox-partial"></span><span class="mls"> icon-checkbox-partial</span> <span class="icon-checkbox-partial"></span><span class="mls"> icon-checkbox-partial</span>
</div> </div>
...@@ -1043,7 +1066,7 @@ ...@@ -1043,7 +1066,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-radio-checked"></span><span class="mls"> icon-radio-checked</span> <span class="icon-radio-checked"></span><span class="mls"> icon-radio-checked</span>
</div> </div>
...@@ -1056,7 +1079,7 @@ ...@@ -1056,7 +1079,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-radio-unchecked"></span><span class="mls"> icon-radio-unchecked</span> <span class="icon-radio-unchecked"></span><span class="mls"> icon-radio-unchecked</span>
</div> </div>
...@@ -1069,7 +1092,7 @@ ...@@ -1069,7 +1092,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-info2"></span><span class="mls"> icon-info2</span> <span class="icon-info2"></span><span class="mls"> icon-info2</span>
</div> </div>
...@@ -1082,7 +1105,7 @@ ...@@ -1082,7 +1105,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-newspaper"></span><span class="mls"> icon-newspaper</span> <span class="icon-newspaper"></span><span class="mls"> icon-newspaper</span>
</div> </div>
...@@ -1095,7 +1118,7 @@ ...@@ -1095,7 +1118,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-image"></span><span class="mls"> icon-image</span> <span class="icon-image"></span><span class="mls"> icon-image</span>
</div> </div>
...@@ -1108,7 +1131,7 @@ ...@@ -1108,7 +1131,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-offline"></span><span class="mls"> icon-offline</span> <span class="icon-offline"></span><span class="mls"> icon-offline</span>
</div> </div>
...@@ -1121,7 +1144,7 @@ ...@@ -1121,7 +1144,7 @@
<input type="text" readonly value="" class="liga unitRight" /> <input type="text" readonly value="" class="liga unitRight" />
</div> </div>
</div> </div>
<div class="glyph fs2"> <div class="glyph fs1">
<div class="clearfix bshadow0 pbs"> <div class="clearfix bshadow0 pbs">
<span class="icon-busy"></span><span class="mls"> icon-busy</span> <span class="icon-busy"></span><span class="mls"> icon-busy</span>
</div> </div>
......
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
<glyph unicode="&#x2364;" d="M256-32c141.385 0 256 114.615 256 256s-114.615 256-256 256-256-114.615-256-256 114.615-256 256-256zM256 432c114.875 0 208-93.125 208-208s-93.125-208-208-208-208 93.125-208 208 93.125 208 208 208zM192 128c0 35.346 28.654 64 64 64s64-28.654 64-64c0-35.346-28.654-64-64-64s-64 28.654-64 64zM320 304c0-26.51 14.327-48 32-48s32 21.49 32 48c0 26.51-14.327 48-32 48s-32-21.49-32-48zM128 304c0-26.51 14.327-48 32-48s32 21.49 32 48c0 26.51-14.327 48-32 48s-32-21.49-32-48z" /> <glyph unicode="&#x2364;" d="M256-32c141.385 0 256 114.615 256 256s-114.615 256-256 256-256-114.615-256-256 114.615-256 256-256zM256 432c114.875 0 208-93.125 208-208s-93.125-208-208-208-208 93.125-208 208 93.125 208 208 208zM192 128c0 35.346 28.654 64 64 64s64-28.654 64-64c0-35.346-28.654-64-64-64s-64 28.654-64 64zM320 304c0-26.51 14.327-48 32-48s32 21.49 32 48c0 26.51-14.327 48-32 48s-32-21.49-32-48zM128 304c0-26.51 14.327-48 32-48s32 21.49 32 48c0 26.51-14.327 48-32 48s-32-21.49-32-48z" />
<glyph unicode="&#x2368;" d="M256-32c141.385 0 256 114.615 256 256s-114.615 256-256 256-256-114.615-256-256 114.615-256 256-256zM256 432c114.875 0 208-93.125 208-208s-93.125-208-208-208-208 93.125-208 208 93.125 208 208 208zM128 320c0-17.673 14.327-32 32-32s32 14.327 32 32c0 17.673-14.327 32-32 32s-32-14.327-32-32zM320 320c0-17.673 14.327-32 32-32s32 14.327 32 32c0 17.673-14.327 32-32 32s-32-14.327-32-32zM363.053 160h32.432c4.623-36.253-16.226-72.265-51.979-85.28-41.452-15.088-87.45 6.358-102.54 47.808-9.054 24.872-36.653 37.741-61.524 28.686-22.781-8.294-35.478-32.149-30.494-55.212h-32.43c-4.621 36.254 16.225 72.264 51.978 85.28 41.452 15.089 87.451-6.358 102.541-47.807 9.052-24.874 36.653-37.741 61.522-28.686 22.781 8.292 35.478 32.149 30.494 55.211z" /> <glyph unicode="&#x2368;" d="M256-32c141.385 0 256 114.615 256 256s-114.615 256-256 256-256-114.615-256-256 114.615-256 256-256zM256 432c114.875 0 208-93.125 208-208s-93.125-208-208-208-208 93.125-208 208 93.125 208 208 208zM128 320c0-17.673 14.327-32 32-32s32 14.327 32 32c0 17.673-14.327 32-32 32s-32-14.327-32-32zM320 320c0-17.673 14.327-32 32-32s32 14.327 32 32c0 17.673-14.327 32-32 32s-32-14.327-32-32zM363.053 160h32.432c4.623-36.253-16.226-72.265-51.979-85.28-41.452-15.088-87.45 6.358-102.54 47.808-9.054 24.872-36.653 37.741-61.524 28.686-22.781-8.294-35.478-32.149-30.494-55.212h-32.43c-4.621 36.254 16.225 72.264 51.978 85.28 41.452 15.089 87.451-6.358 102.541-47.807 9.052-24.874 36.653-37.741 61.522-28.686 22.781 8.292 35.478 32.149 30.494 55.211z" />
<glyph unicode="&#x2369;" d="M256-32c141.385 0 256 114.615 256 256s-114.615 256-256 256-256-114.615-256-256 114.615-256 256-256zM256 432c114.875 0 208-93.125 208-208s-93.125-208-208-208-208 93.125-208 208 93.125 208 208 208zM372.87 179.19l11.244-38.388-218.504-64.001-11.244 38.388zM128 320c0 17.673 14.327 32 32 32s32-14.327 32-32c0-17.673-14.327-32-32-32s-32 14.327-32 32zM320 320c0 17.673 14.327 32 32 32s32-14.327 32-32c0-17.673-14.327-32-32-32s-32 14.327-32 32z" /> <glyph unicode="&#x2369;" d="M256-32c141.385 0 256 114.615 256 256s-114.615 256-256 256-256-114.615-256-256 114.615-256 256-256zM256 432c114.875 0 208-93.125 208-208s-93.125-208-208-208-208 93.125-208 208 93.125 208 208 208zM372.87 179.19l11.244-38.388-218.504-64.001-11.244 38.388zM128 320c0 17.673 14.327 32 32 32s32-14.327 32-32c0-17.673-14.327-32-32-32s-32 14.327-32 32zM320 320c0 17.673 14.327 32 32 32s32-14.327 32-32c0-17.673-14.327-32-32-32s-32 14.327-32 32z" />
<glyph unicode="&#x25ba;" d="M96 416l320-192-320-192z" />
<glyph unicode="&#x25bc;" d="M448 384l-192-320-192 320z" />
<glyph unicode="&#x25d9;" d="M490.594 399.946c-71.816 10.325-151.166 16.054-234.593 16.054-83.43 0-162.778-5.729-234.597-16.054-13.765-53.863-21.404-113.375-21.404-175.946 0-62.57 7.639-122.083 21.404-175.945 71.819-10.326 151.168-16.055 234.597-16.055 83.427 0 162.776 5.729 234.593 16.055 13.766 53.862 21.406 113.375 21.406 175.945 0 62.571-7.64 122.083-21.406 175.946zM192.001 128v192l160-96-160-96z" /> <glyph unicode="&#x25d9;" d="M490.594 399.946c-71.816 10.325-151.166 16.054-234.593 16.054-83.43 0-162.778-5.729-234.597-16.054-13.765-53.863-21.404-113.375-21.404-175.946 0-62.57 7.639-122.083 21.404-175.945 71.819-10.326 151.168-16.055 234.597-16.055 83.427 0 162.776 5.729 234.593 16.055 13.766 53.862 21.406 113.375 21.406 175.945 0 62.571-7.64 122.083-21.406 175.946zM192.001 128v192l160-96-160-96z" />
<glyph unicode="&#x25fb;" d="M256 384c-27.466 0-53.994-4.331-78.847-12.871-23.356-8.027-44.153-19.372-61.814-33.722-33.107-26.899-51.339-61.492-51.339-97.407 0-20.149 5.594-39.689 16.626-58.076 11.376-18.96 28.491-36.293 49.494-50.126 15.178-9.996 25.39-25.974 28.088-43.947 0.9-5.992 1.464-12.044 1.685-18.062 3.735 3.097 7.375 6.423 10.94 9.988 12.077 12.076 28.39 18.745 45.251 18.745 2.684 0 5.381-0.168 8.078-0.512 10.487-1.333 21.199-2.010 31.838-2.010 27.467 0 53.994 4.33 78.847 12.871 23.356 8.027 44.153 19.372 61.814 33.722 33.107 26.898 51.339 61.492 51.339 97.407s-18.232 70.508-51.339 97.407c-17.661 14.349-38.458 25.695-61.814 33.722-24.853 8.54-51.38 12.871-78.847 12.871zM256 448v0c141.385 0 256-93.125 256-208s-114.615-208-256-208c-13.578 0-26.905 0.867-39.912 2.522-54.989-54.989-120.625-64.85-184.088-66.298v13.458c34.268 16.789 64 47.37 64 82.318 0 4.877-0.379 9.665-1.082 14.348-57.898 38.132-94.918 96.377-94.918 161.652 0 114.875 114.615 208 256 208z" /> <glyph unicode="&#x25fb;" d="M256 384c-27.466 0-53.994-4.331-78.847-12.871-23.356-8.027-44.153-19.372-61.814-33.722-33.107-26.899-51.339-61.492-51.339-97.407 0-20.149 5.594-39.689 16.626-58.076 11.376-18.96 28.491-36.293 49.494-50.126 15.178-9.996 25.39-25.974 28.088-43.947 0.9-5.992 1.464-12.044 1.685-18.062 3.735 3.097 7.375 6.423 10.94 9.988 12.077 12.076 28.39 18.745 45.251 18.745 2.684 0 5.381-0.168 8.078-0.512 10.487-1.333 21.199-2.010 31.838-2.010 27.467 0 53.994 4.33 78.847 12.871 23.356 8.027 44.153 19.372 61.814 33.722 33.107 26.898 51.339 61.492 51.339 97.407s-18.232 70.508-51.339 97.407c-17.661 14.349-38.458 25.695-61.814 33.722-24.853 8.54-51.38 12.871-78.847 12.871zM256 448v0c141.385 0 256-93.125 256-208s-114.615-208-256-208c-13.578 0-26.905 0.867-39.912 2.522-54.989-54.989-120.625-64.85-184.088-66.298v13.458c34.268 16.789 64 47.37 64 82.318 0 4.877-0.379 9.665-1.082 14.348-57.898 38.132-94.918 96.377-94.918 161.652 0 114.875 114.615 208 256 208z" />
<glyph unicode="&#x25fc;" d="M256 448c141.385 0 256-93.125 256-208s-114.615-208-256-208c-13.578 0-26.905 0.867-39.912 2.522-54.989-54.989-120.625-64.85-184.088-66.298v13.458c34.268 16.789 64 47.37 64 82.318 0 4.877-0.379 9.665-1.082 14.348-57.898 38.132-94.918 96.377-94.918 161.652 0 114.875 114.615 208 256 208z" /> <glyph unicode="&#x25fc;" d="M256 448c141.385 0 256-93.125 256-208s-114.615-208-256-208c-13.578 0-26.905 0.867-39.912 2.522-54.989-54.989-120.625-64.85-184.088-66.298v13.458c34.268 16.789 64 47.37 64 82.318 0 4.877-0.379 9.665-1.082 14.348-57.898 38.132-94.918 96.377-94.918 161.652 0 114.875 114.615 208 256 208z" />
...@@ -31,6 +33,7 @@ ...@@ -31,6 +33,7 @@
<glyph unicode="&#x270e;" d="M432 480c44.182 0 80-35.817 80-80 0-18.010-5.955-34.629-16-48l-32-32-112 112 32 32c13.371 10.045 29.989 16 48 16zM32 112l-32-144 144 32 296 296-112 112-296-296zM357.789 298.211l-224-224-27.578 27.578 224 224 27.578-27.578z" /> <glyph unicode="&#x270e;" d="M432 480c44.182 0 80-35.817 80-80 0-18.010-5.955-34.629-16-48l-32-32-112 112 32 32c13.371 10.045 29.989 16 48 16zM32 112l-32-144 144 32 296 296-112 112-296-296zM357.789 298.211l-224-224-27.578 27.578 224 224 27.578-27.578z" />
<glyph unicode="&#x270f;" d="M480 352c17.673 0 32 14.327 32 32v64h-64v32h-416c-17.6 0-32-14.399-32-32v-448c0-17.6 14.398-32 32-32h416v128h32c17.673 0 32 14.327 32 32v64h-64v32h32c17.673 0 32 14.327 32 32v64h-64v32h32zM288 351.835c35.255 0 63.835-28.58 63.835-63.835s-28.58-63.835-63.835-63.835c-35.255 0-63.835 28.58-63.835 63.835s28.58 63.835 63.835 63.835zM128 0h-32v448h32v-448zM384 96h-192v32c0 35.347 28.654 64 64 64v0h64c35.348 0 64-28.653 64-64v-32z" /> <glyph unicode="&#x270f;" d="M480 352c17.673 0 32 14.327 32 32v64h-64v32h-416c-17.6 0-32-14.399-32-32v-448c0-17.6 14.398-32 32-32h416v128h32c17.673 0 32 14.327 32 32v64h-64v32h32c17.673 0 32 14.327 32 32v64h-64v32h32zM288 351.835c35.255 0 63.835-28.58 63.835-63.835s-28.58-63.835-63.835-63.835c-35.255 0-63.835 28.58-63.835 63.835s28.58 63.835 63.835 63.835zM128 0h-32v448h32v-448zM384 96h-192v32c0 35.347 28.654 64 64 64v0h64c35.348 0 64-28.653 64-64v-32z" />
<glyph unicode="&#x2710;" d="M449.18 448h-385.18v-64h-46.82c-8.8 0-17.18-6.264-17.18-15.064v-32c0-8.8 8.38-16.936 17.18-16.936h46.82v-32h-46.82c-8.8 0-17.18-6.264-17.18-15.064v-32c0-8.8 8.38-16.936 17.18-16.936h46.82v-32h-46.82c-8.8 0-17.18-6.264-17.18-15.064v-32c0-8.799 8.38-16.936 17.18-16.936h46.82v-32h-46.82c-8.8 0-17.18-6.264-17.18-15.064v-32c0-8.8 8.38-16.936 17.18-16.936h46.82v-64h385.18c17.674 0 30.82 15.263 30.82 32.936v416c0 17.673-13.146 31.064-30.82 31.064zM160 0h-64v32h17.18c8.8 0 14.82 8.136 14.82 16.936v32c0 8.801-6.021 15.064-14.82 15.064h-17.18v32h17.18c8.8 0 14.82 8.136 14.82 16.936v32c0 8.801-6.021 15.064-14.82 15.064h-17.18v32h17.18c8.8 0 14.82 8.136 14.82 16.936v32c0 8.801-6.021 15.064-14.82 15.064h-17.18v32h17.18c8.8 0 14.82 8.136 14.82 16.936v32c0 8.801-6.020 15.064-14.82 15.064h-17.18v32h64v-416z" /> <glyph unicode="&#x2710;" d="M449.18 448h-385.18v-64h-46.82c-8.8 0-17.18-6.264-17.18-15.064v-32c0-8.8 8.38-16.936 17.18-16.936h46.82v-32h-46.82c-8.8 0-17.18-6.264-17.18-15.064v-32c0-8.8 8.38-16.936 17.18-16.936h46.82v-32h-46.82c-8.8 0-17.18-6.264-17.18-15.064v-32c0-8.799 8.38-16.936 17.18-16.936h46.82v-32h-46.82c-8.8 0-17.18-6.264-17.18-15.064v-32c0-8.8 8.38-16.936 17.18-16.936h46.82v-64h385.18c17.674 0 30.82 15.263 30.82 32.936v416c0 17.673-13.146 31.064-30.82 31.064zM160 0h-64v32h17.18c8.8 0 14.82 8.136 14.82 16.936v32c0 8.801-6.021 15.064-14.82 15.064h-17.18v32h17.18c8.8 0 14.82 8.136 14.82 16.936v32c0 8.801-6.021 15.064-14.82 15.064h-17.18v32h17.18c8.8 0 14.82 8.136 14.82 16.936v32c0 8.801-6.021 15.064-14.82 15.064h-17.18v32h17.18c8.8 0 14.82 8.136 14.82 16.936v32c0 8.801-6.020 15.064-14.82 15.064h-17.18v32h64v-416z" />
<glyph unicode="&#x2713;" d="M432 416l-240-240-112 112-80-80 192-192 320 320z" />
<glyph unicode="&#x2715;" d="M507.331 68.67c-0.002 0.002-0.004 0.004-0.006 0.005l-155.322 155.325 155.322 155.325c0.002 0.002 0.004 0.003 0.006 0.005 1.672 1.673 2.881 3.627 3.656 5.708 2.123 5.688 0.912 12.341-3.662 16.915l-73.373 73.373c-4.574 4.573-11.225 5.783-16.914 3.66-2.080-0.775-4.035-1.984-5.709-3.655 0-0.002-0.002-0.003-0.004-0.005l-155.324-155.326-155.324 155.325c-0.002 0.002-0.003 0.003-0.005 0.005-1.673 1.671-3.627 2.88-5.707 3.655-5.69 2.124-12.341 0.913-16.915-3.66l-73.374-73.374c-4.574-4.574-5.784-11.226-3.661-16.914 0.776-2.080 1.985-4.036 3.656-5.708 0.002-0.001 0.003-0.003 0.005-0.005l155.325-155.324-155.325-155.326c-0.001-0.002-0.003-0.003-0.004-0.005-1.671-1.673-2.88-3.627-3.657-5.707-2.124-5.688-0.913-12.341 3.661-16.915l73.374-73.373c4.575-4.574 11.226-5.784 16.915-3.661 2.080 0.776 4.035 1.985 5.708 3.656 0.001 0.002 0.003 0.003 0.005 0.005l155.324 155.325 155.324-155.325c0.002-0.001 0.004-0.003 0.006-0.004 1.674-1.672 3.627-2.881 5.707-3.657 5.689-2.123 12.342-0.913 16.914 3.661l73.373 73.374c4.574 4.574 5.785 11.227 3.662 16.915-0.776 2.080-1.985 4.034-3.657 5.707z" /> <glyph unicode="&#x2715;" d="M507.331 68.67c-0.002 0.002-0.004 0.004-0.006 0.005l-155.322 155.325 155.322 155.325c0.002 0.002 0.004 0.003 0.006 0.005 1.672 1.673 2.881 3.627 3.656 5.708 2.123 5.688 0.912 12.341-3.662 16.915l-73.373 73.373c-4.574 4.573-11.225 5.783-16.914 3.66-2.080-0.775-4.035-1.984-5.709-3.655 0-0.002-0.002-0.003-0.004-0.005l-155.324-155.326-155.324 155.325c-0.002 0.002-0.003 0.003-0.005 0.005-1.673 1.671-3.627 2.88-5.707 3.655-5.69 2.124-12.341 0.913-16.915-3.66l-73.374-73.374c-4.574-4.574-5.784-11.226-3.661-16.914 0.776-2.080 1.985-4.036 3.656-5.708 0.002-0.001 0.003-0.003 0.005-0.005l155.325-155.324-155.325-155.326c-0.001-0.002-0.003-0.003-0.004-0.005-1.671-1.673-2.88-3.627-3.657-5.707-2.124-5.688-0.913-12.341 3.661-16.915l73.374-73.373c4.575-4.574 11.226-5.784 16.915-3.661 2.080 0.776 4.035 1.985 5.708 3.656 0.001 0.002 0.003 0.003 0.005 0.005l155.324 155.325 155.324-155.325c0.002-0.001 0.004-0.003 0.006-0.004 1.674-1.672 3.627-2.881 5.707-3.657 5.689-2.123 12.342-0.913 16.914 3.661l73.373 73.374c4.574 4.574 5.785 11.227 3.662 16.915-0.776 2.080-1.985 4.034-3.657 5.707z" />
<glyph unicode="&#x2718;" d="M0 224c0-141.385 114.615-256 256-256s256 114.615 256 256-114.614 256-256 256c-141.385 0-256-114.615-256-256zM448 224c0-36.618-10.256-70.84-28.044-99.956l-263.911 263.912c29.115 17.789 63.337 28.044 99.955 28.044 106.038 0 192-85.961 192-192zM64 224c0 36.618 10.256 70.839 28.045 99.956l263.911-263.912c-29.117-17.789-63.338-28.044-99.956-28.044-106.038 0-192 85.961-192 192z" /> <glyph unicode="&#x2718;" d="M0 224c0-141.385 114.615-256 256-256s256 114.615 256 256-114.614 256-256 256c-141.385 0-256-114.615-256-256zM448 224c0-36.618-10.256-70.84-28.044-99.956l-263.911 263.912c29.115 17.789 63.337 28.044 99.955 28.044 106.038 0 192-85.961 192-192zM64 224c0 36.618 10.256 70.839 28.045 99.956l263.911-263.912c-29.117-17.789-63.338-28.044-99.956-28.044-106.038 0-192 85.961-192 192z" />
<glyph unicode="&#x271a;" d="M496 288h-176v176c0 8.836-7.164 16-16 16h-96c-8.836 0-16-7.164-16-16v-176h-176c-8.836 0-16-7.164-16-16v-96c0-8.836 7.164-16 16-16h176v-176c0-8.836 7.164-16 16-16h96c8.836 0 16 7.164 16 16v176h176c8.836 0 16 7.164 16 16v96c0 8.836-7.164 16-16 16z" /> <glyph unicode="&#x271a;" d="M496 288h-176v176c0 8.836-7.164 16-16 16h-96c-8.836 0-16-7.164-16-16v-176h-176c-8.836 0-16-7.164-16-16v-96c0-8.836 7.164-16 16-16h176v-176c0-8.836 7.164-16 16-16h96c8.836 0 16 7.164 16 16v176h176c8.836 0 16 7.164 16 16v96c0 8.836-7.164 16-16 16z" />
...@@ -92,5 +95,4 @@ ...@@ -92,5 +95,4 @@
<glyph unicode="&#xe058;" d="M256 480c-141.385 0-256-114.615-256-256s114.615-256 256-256 256 114.615 256 256-114.615 256-256 256zM384 306.745l-82.744-82.745 82.744-82.744v-45.256h-45.256l-82.744 82.744-82.745-82.744h-45.255v45.256l82.745 82.744-82.745 82.745v45.255h45.255l82.745-82.745 82.744 82.745h45.256v-45.255z" /> <glyph unicode="&#xe058;" d="M256 480c-141.385 0-256-114.615-256-256s114.615-256 256-256 256 114.615 256 256-114.615 256-256 256zM384 306.745l-82.744-82.745 82.744-82.744v-45.256h-45.256l-82.744 82.744-82.745-82.744h-45.255v45.256l82.745 82.744-82.745 82.745v45.255h45.255l82.745-82.745 82.744 82.745h45.256v-45.255z" />
<glyph unicode="&#xe059;" d="M256 480c-141.385 0-256-114.615-256-256s114.615-256 256-256 256 114.615 256 256-114.615 256-256 256zM224 384h64v-64h-64v64zM320 64h-128v32h32v128h-32v32h96v-160h32v-32z" /> <glyph unicode="&#xe059;" d="M256 480c-141.385 0-256-114.615-256-256s114.615-256 256-256 256 114.615 256 256-114.615 256-256 256zM224 384h64v-64h-64v64zM320 64h-128v32h32v128h-32v32h96v-160h32v-32z" />
<glyph unicode="&#xe05a;" d="M0 272v-96c0-8.836 7.164-16 16-16h480c8.836 0 16 7.164 16 16v96c0 8.836-7.164 16-16 16h-480c-8.836 0-16-7.164-16-16z" /> <glyph unicode="&#xe05a;" d="M0 272v-96c0-8.836 7.164-16 16-16h480c8.836 0 16 7.164 16 16v96c0 8.836-7.164 16-16 16h-480c-8.836 0-16-7.164-16-16z" />
<glyph unicode="&#xe600;" d="M432 416l-240-240-112 112-80-80 192-192 320 320z" />
</font></defs></svg> </font></defs></svg>
\ No newline at end of file
{ {
"IcoMoonType": "selection", "IcoMoonType": "selection",
"icons": [ "icons": [
{
"icon": {
"paths": [
"M192 128l640 384-640 384z"
],
"tags": [
"play",
"media control",
"audio"
],
"grid": 16
},
"properties": {
"order": 89,
"id": 451,
"prevSize": 32,
"code": 9658,
"name": "closed",
"ligatures": ""
},
"setIdx": 0,
"iconIdx": 266
},
{
"icon": {
"paths": [
"M896 192l-384 640-384-640z"
],
"tags": [
"opened"
],
"grid": 16
},
"properties": {
"id": 266,
"order": 88,
"prevSize": 32,
"code": 9660,
"name": "opened",
"ligatures": ""
},
"setIdx": 0,
"iconIdx": 267
},
{ {
"icon": { "icon": {
"paths": [ "paths": [
...@@ -19,12 +63,12 @@ ...@@ -19,12 +63,12 @@
"order": 1, "order": 1,
"id": 85, "id": 85,
"prevSize": 32, "prevSize": 32,
"code": 58880, "code": 10003,
"name": "checkmark", "name": "checkmark",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 0 "iconIdx": 88
}, },
{ {
"icon": { "icon": {
...@@ -37,7 +81,7 @@ ...@@ -37,7 +81,7 @@
"building" "building"
], ],
"defaultCode": 57344, "defaultCode": 57344,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 0, "id": 0,
...@@ -47,8 +91,8 @@ ...@@ -47,8 +91,8 @@
"name": "home", "name": "home",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 1 "iconIdx": 89
}, },
{ {
"icon": { "icon": {
...@@ -63,7 +107,7 @@ ...@@ -63,7 +107,7 @@
"note" "note"
], ],
"defaultCode": 9998, "defaultCode": 9998,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 1, "id": 1,
...@@ -73,8 +117,8 @@ ...@@ -73,8 +117,8 @@
"name": "pencil", "name": "pencil",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 2 "iconIdx": 90
}, },
{ {
"icon": { "icon": {
...@@ -88,7 +132,7 @@ ...@@ -88,7 +132,7 @@
"image" "image"
], ],
"defaultCode": 57347, "defaultCode": 57347,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 2, "id": 2,
...@@ -98,8 +142,8 @@ ...@@ -98,8 +142,8 @@
"name": "camera", "name": "camera",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 3 "iconIdx": 91
}, },
{ {
"icon": { "icon": {
...@@ -114,7 +158,7 @@ ...@@ -114,7 +158,7 @@
"movie" "movie"
], ],
"defaultCode": 9750, "defaultCode": 9750,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 3, "id": 3,
...@@ -124,8 +168,8 @@ ...@@ -124,8 +168,8 @@
"name": "camera2", "name": "camera2",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 4 "iconIdx": 92
}, },
{ {
"icon": { "icon": {
...@@ -138,18 +182,18 @@ ...@@ -138,18 +182,18 @@
"movie" "movie"
], ],
"defaultCode": 9689, "defaultCode": 9689,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 4, "id": 4,
"order": 6, "order": 6,
"prevSize": 32, "prevSize": 32,
"code": 9689, "code": 9689,
"name": "play", "name": "play22",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 5 "iconIdx": 93
}, },
{ {
"icon": { "icon": {
...@@ -163,7 +207,7 @@ ...@@ -163,7 +207,7 @@
"sound" "sound"
], ],
"defaultCode": 9835, "defaultCode": 9835,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 5, "id": 5,
...@@ -173,8 +217,8 @@ ...@@ -173,8 +217,8 @@
"name": "music", "name": "music",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 6 "iconIdx": 94
}, },
{ {
"icon": { "icon": {
...@@ -189,7 +233,7 @@ ...@@ -189,7 +233,7 @@
"audio" "audio"
], ],
"defaultCode": 9836, "defaultCode": 9836,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 6, "id": 6,
...@@ -199,8 +243,8 @@ ...@@ -199,8 +243,8 @@
"name": "headphones", "name": "headphones",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 7 "iconIdx": 95
}, },
{ {
"icon": { "icon": {
...@@ -215,7 +259,7 @@ ...@@ -215,7 +259,7 @@
"call" "call"
], ],
"defaultCode": 9743, "defaultCode": 9743,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 7, "id": 7,
...@@ -225,8 +269,8 @@ ...@@ -225,8 +269,8 @@
"name": "phone", "name": "phone",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 8 "iconIdx": 96
}, },
{ {
"icon": { "icon": {
...@@ -241,7 +285,7 @@ ...@@ -241,7 +285,7 @@
"call" "call"
], ],
"defaultCode": 9742, "defaultCode": 9742,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 8, "id": 8,
...@@ -251,8 +295,8 @@ ...@@ -251,8 +295,8 @@
"name": "phone-hang-up", "name": "phone-hang-up",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 9 "iconIdx": 97
}, },
{ {
"icon": { "icon": {
...@@ -265,7 +309,7 @@ ...@@ -265,7 +309,7 @@
"contacts" "contacts"
], ],
"defaultCode": 9999, "defaultCode": 9999,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 9, "id": 9,
...@@ -275,8 +319,8 @@ ...@@ -275,8 +319,8 @@
"name": "address-book", "name": "address-book",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 10 "iconIdx": 98
}, },
{ {
"icon": { "icon": {
...@@ -290,7 +334,7 @@ ...@@ -290,7 +334,7 @@
"journal" "journal"
], ],
"defaultCode": 10000, "defaultCode": 10000,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 10, "id": 10,
...@@ -300,8 +344,8 @@ ...@@ -300,8 +344,8 @@
"name": "notebook", "name": "notebook",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 11 "iconIdx": 99
}, },
{ {
"icon": { "icon": {
...@@ -316,7 +360,7 @@ ...@@ -316,7 +360,7 @@
"letter" "letter"
], ],
"defaultCode": 9993, "defaultCode": 9993,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 11, "id": 11,
...@@ -326,8 +370,8 @@ ...@@ -326,8 +370,8 @@
"name": "envelop", "name": "envelop",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 12 "iconIdx": 100
}, },
{ {
"icon": { "icon": {
...@@ -339,7 +383,7 @@ ...@@ -339,7 +383,7 @@
"pin" "pin"
], ],
"defaultCode": 57362, "defaultCode": 57362,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 12, "id": 12,
...@@ -349,8 +393,8 @@ ...@@ -349,8 +393,8 @@
"name": "pushpin", "name": "pushpin",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 13 "iconIdx": 101
}, },
{ {
"icon": { "icon": {
...@@ -364,7 +408,7 @@ ...@@ -364,7 +408,7 @@
"talk" "talk"
], ],
"defaultCode": 9724, "defaultCode": 9724,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 13, "id": 13,
...@@ -374,8 +418,8 @@ ...@@ -374,8 +418,8 @@
"name": "bubble", "name": "bubble",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 14 "iconIdx": 102
}, },
{ {
"icon": { "icon": {
...@@ -389,7 +433,7 @@ ...@@ -389,7 +433,7 @@
"talk" "talk"
], ],
"defaultCode": 9723, "defaultCode": 9723,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 14, "id": 14,
...@@ -399,8 +443,8 @@ ...@@ -399,8 +443,8 @@
"name": "bubble2", "name": "bubble2",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 15 "iconIdx": 103
}, },
{ {
"icon": { "icon": {
...@@ -415,7 +459,7 @@ ...@@ -415,7 +459,7 @@
"talk" "talk"
], ],
"defaultCode": 57365, "defaultCode": 57365,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 15, "id": 15,
...@@ -425,8 +469,8 @@ ...@@ -425,8 +469,8 @@
"name": "bubbles", "name": "bubbles",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 16 "iconIdx": 104
}, },
{ {
"icon": { "icon": {
...@@ -441,7 +485,7 @@ ...@@ -441,7 +485,7 @@
"talk" "talk"
], ],
"defaultCode": 57366, "defaultCode": 57366,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 16, "id": 16,
...@@ -451,8 +495,8 @@ ...@@ -451,8 +495,8 @@
"name": "bubbles2", "name": "bubbles2",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 17 "iconIdx": 105
}, },
{ {
"icon": { "icon": {
...@@ -467,7 +511,7 @@ ...@@ -467,7 +511,7 @@
"talk" "talk"
], ],
"defaultCode": 57367, "defaultCode": 57367,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 17, "id": 17,
...@@ -477,8 +521,8 @@ ...@@ -477,8 +521,8 @@
"name": "bubbles3", "name": "bubbles3",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 18 "iconIdx": 106
}, },
{ {
"icon": { "icon": {
...@@ -494,7 +538,7 @@ ...@@ -494,7 +538,7 @@
"member" "member"
], ],
"defaultCode": 57370, "defaultCode": 57370,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 18, "id": 18,
...@@ -504,8 +548,8 @@ ...@@ -504,8 +548,8 @@
"name": "user", "name": "user",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 19 "iconIdx": 107
}, },
{ {
"icon": { "icon": {
...@@ -521,7 +565,7 @@ ...@@ -521,7 +565,7 @@
"community" "community"
], ],
"defaultCode": 57371, "defaultCode": 57371,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 19, "id": 19,
...@@ -531,8 +575,8 @@ ...@@ -531,8 +575,8 @@
"name": "users", "name": "users",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 20 "iconIdx": 108
}, },
{ {
"icon": { "icon": {
...@@ -544,7 +588,7 @@ ...@@ -544,7 +588,7 @@
"ldquo" "ldquo"
], ],
"defaultCode": 57373, "defaultCode": 57373,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 20, "id": 20,
...@@ -554,8 +598,8 @@ ...@@ -554,8 +598,8 @@
"name": "quotes-left", "name": "quotes-left",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 21 "iconIdx": 109
}, },
{ {
"icon": { "icon": {
...@@ -570,7 +614,7 @@ ...@@ -570,7 +614,7 @@
"wheel" "wheel"
], ],
"defaultCode": 8987, "defaultCode": 8987,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 21, "id": 21,
...@@ -580,8 +624,8 @@ ...@@ -580,8 +624,8 @@
"name": "spinner", "name": "spinner",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 22 "iconIdx": 110
}, },
{ {
"icon": { "icon": {
...@@ -595,7 +639,7 @@ ...@@ -595,7 +639,7 @@
"find" "find"
], ],
"defaultCode": 57377, "defaultCode": 57377,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 22, "id": 22,
...@@ -605,8 +649,8 @@ ...@@ -605,8 +649,8 @@
"name": "search", "name": "search",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 23 "iconIdx": 111
}, },
{ {
"icon": { "icon": {
...@@ -622,7 +666,7 @@ ...@@ -622,7 +666,7 @@
"options" "options"
], ],
"defaultCode": 57378, "defaultCode": 57378,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 23, "id": 23,
...@@ -632,8 +676,8 @@ ...@@ -632,8 +676,8 @@
"name": "cogs", "name": "cogs",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 24 "iconIdx": 112
}, },
{ {
"icon": { "icon": {
...@@ -650,7 +694,7 @@ ...@@ -650,7 +694,7 @@
"fix" "fix"
], ],
"defaultCode": 57380, "defaultCode": 57380,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 24, "id": 24,
...@@ -660,8 +704,8 @@ ...@@ -660,8 +704,8 @@
"name": "wrench", "name": "wrench",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 25 "iconIdx": 113
}, },
{ {
"icon": { "icon": {
...@@ -673,7 +717,7 @@ ...@@ -673,7 +717,7 @@
"lock" "lock"
], ],
"defaultCode": 57381, "defaultCode": 57381,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 25, "id": 25,
...@@ -683,8 +727,8 @@ ...@@ -683,8 +727,8 @@
"name": "unlocked", "name": "unlocked",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 26 "iconIdx": 114
}, },
{ {
"icon": { "icon": {
...@@ -698,7 +742,7 @@ ...@@ -698,7 +742,7 @@
"encrypted" "encrypted"
], ],
"defaultCode": 57382, "defaultCode": 57382,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 26, "id": 26,
...@@ -708,8 +752,8 @@ ...@@ -708,8 +752,8 @@
"name": "lock", "name": "lock",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 27 "iconIdx": 115
}, },
{ {
"icon": { "icon": {
...@@ -723,7 +767,7 @@ ...@@ -723,7 +767,7 @@
"encrypted" "encrypted"
], ],
"defaultCode": 57383, "defaultCode": 57383,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 27, "id": 27,
...@@ -733,8 +777,8 @@ ...@@ -733,8 +777,8 @@
"name": "lock2", "name": "lock2",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 28 "iconIdx": 116
}, },
{ {
"icon": { "icon": {
...@@ -750,7 +794,7 @@ ...@@ -750,7 +794,7 @@
"sign in" "sign in"
], ],
"defaultCode": 57384, "defaultCode": 57384,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 28, "id": 28,
...@@ -760,8 +804,8 @@ ...@@ -760,8 +804,8 @@
"name": "key", "name": "key",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 29 "iconIdx": 117
}, },
{ {
"icon": { "icon": {
...@@ -777,7 +821,7 @@ ...@@ -777,7 +821,7 @@
"sign in" "sign in"
], ],
"defaultCode": 57385, "defaultCode": 57385,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 29, "id": 29,
...@@ -787,8 +831,8 @@ ...@@ -787,8 +831,8 @@
"name": "key2", "name": "key2",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 30 "iconIdx": 118
}, },
{ {
"icon": { "icon": {
...@@ -802,7 +846,7 @@ ...@@ -802,7 +846,7 @@
"reduce" "reduce"
], ],
"defaultCode": 57386, "defaultCode": 57386,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 30, "id": 30,
...@@ -812,8 +856,8 @@ ...@@ -812,8 +856,8 @@
"name": "zoomout", "name": "zoomout",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 31 "iconIdx": 119
}, },
{ {
"icon": { "icon": {
...@@ -826,7 +870,7 @@ ...@@ -826,7 +870,7 @@
"scale" "scale"
], ],
"defaultCode": 57387, "defaultCode": 57387,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 31, "id": 31,
...@@ -836,8 +880,8 @@ ...@@ -836,8 +880,8 @@
"name": "zoomin", "name": "zoomin",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 32 "iconIdx": 120
}, },
{ {
"icon": { "icon": {
...@@ -854,7 +898,7 @@ ...@@ -854,7 +898,7 @@
"options" "options"
], ],
"defaultCode": 57391, "defaultCode": 57391,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 32, "id": 32,
...@@ -864,8 +908,8 @@ ...@@ -864,8 +908,8 @@
"name": "cog", "name": "cog",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 33 "iconIdx": 121
}, },
{ {
"icon": { "icon": {
...@@ -881,7 +925,7 @@ ...@@ -881,7 +925,7 @@
"dispose" "dispose"
], ],
"defaultCode": 57389, "defaultCode": 57389,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 33, "id": 33,
...@@ -891,8 +935,8 @@ ...@@ -891,8 +935,8 @@
"name": "remove", "name": "remove",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 34 "iconIdx": 122
}, },
{ {
"icon": { "icon": {
...@@ -908,7 +952,7 @@ ...@@ -908,7 +952,7 @@
"dispose" "dispose"
], ],
"defaultCode": 57390, "defaultCode": 57390,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 34, "id": 34,
...@@ -918,8 +962,8 @@ ...@@ -918,8 +962,8 @@
"name": "remove2", "name": "remove2",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 35 "iconIdx": 123
}, },
{ {
"icon": { "icon": {
...@@ -933,7 +977,7 @@ ...@@ -933,7 +977,7 @@
"visit" "visit"
], ],
"defaultCode": 57392, "defaultCode": 57392,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 35, "id": 35,
...@@ -943,8 +987,8 @@ ...@@ -943,8 +987,8 @@
"name": "eye", "name": "eye",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 36 "iconIdx": 124
}, },
{ {
"icon": { "icon": {
...@@ -962,7 +1006,7 @@ ...@@ -962,7 +1006,7 @@
"private" "private"
], ],
"defaultCode": 57393, "defaultCode": 57393,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 36, "id": 36,
...@@ -972,8 +1016,8 @@ ...@@ -972,8 +1016,8 @@
"name": "eye-blocked", "name": "eye-blocked",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 37 "iconIdx": 125
}, },
{ {
"icon": { "icon": {
...@@ -985,7 +1029,7 @@ ...@@ -985,7 +1029,7 @@
"paperclip" "paperclip"
], ],
"defaultCode": 57394, "defaultCode": 57394,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 37, "id": 37,
...@@ -995,8 +1039,8 @@ ...@@ -995,8 +1039,8 @@
"name": "attachment", "name": "attachment",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 38 "iconIdx": 126
}, },
{ {
"icon": { "icon": {
...@@ -1011,7 +1055,7 @@ ...@@ -1011,7 +1055,7 @@
"sphere" "sphere"
], ],
"defaultCode": 57395, "defaultCode": 57395,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 38, "id": 38,
...@@ -1021,8 +1065,8 @@ ...@@ -1021,8 +1065,8 @@
"name": "globe", "name": "globe",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 39 "iconIdx": 127
}, },
{ {
"icon": { "icon": {
...@@ -1036,7 +1080,7 @@ ...@@ -1036,7 +1080,7 @@
"favorite" "favorite"
], ],
"defaultCode": 10084, "defaultCode": 10084,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 39, "id": 39,
...@@ -1046,8 +1090,8 @@ ...@@ -1046,8 +1090,8 @@
"name": "heart", "name": "heart",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 40 "iconIdx": 128
}, },
{ {
"icon": { "icon": {
...@@ -1061,7 +1105,7 @@ ...@@ -1061,7 +1105,7 @@
"face" "face"
], ],
"defaultCode": 9787, "defaultCode": 9787,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 40, "id": 40,
...@@ -1071,8 +1115,8 @@ ...@@ -1071,8 +1115,8 @@
"name": "happy", "name": "happy",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 41 "iconIdx": 129
}, },
{ {
"icon": { "icon": {
...@@ -1087,7 +1131,7 @@ ...@@ -1087,7 +1131,7 @@
"vote up" "vote up"
], ],
"defaultCode": 9757, "defaultCode": 9757,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 41, "id": 41,
...@@ -1097,8 +1141,8 @@ ...@@ -1097,8 +1141,8 @@
"name": "thumbs-up", "name": "thumbs-up",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 42 "iconIdx": 130
}, },
{ {
"icon": { "icon": {
...@@ -1111,7 +1155,7 @@ ...@@ -1111,7 +1155,7 @@
"face" "face"
], ],
"defaultCode": 9786, "defaultCode": 9786,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 42, "id": 42,
...@@ -1121,8 +1165,8 @@ ...@@ -1121,8 +1165,8 @@
"name": "smiley", "name": "smiley",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 43 "iconIdx": 131
}, },
{ {
"icon": { "icon": {
...@@ -1136,7 +1180,7 @@ ...@@ -1136,7 +1180,7 @@
"face" "face"
], ],
"defaultCode": 57400, "defaultCode": 57400,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 43, "id": 43,
...@@ -1146,8 +1190,8 @@ ...@@ -1146,8 +1190,8 @@
"name": "tongue", "name": "tongue",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 44 "iconIdx": 132
}, },
{ {
"icon": { "icon": {
...@@ -1161,7 +1205,7 @@ ...@@ -1161,7 +1205,7 @@
"face" "face"
], ],
"defaultCode": 9785, "defaultCode": 9785,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 44, "id": 44,
...@@ -1171,8 +1215,8 @@ ...@@ -1171,8 +1215,8 @@
"name": "sad", "name": "sad",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 45 "iconIdx": 133
}, },
{ {
"icon": { "icon": {
...@@ -1186,7 +1230,7 @@ ...@@ -1186,7 +1230,7 @@
"face" "face"
], ],
"defaultCode": 57402, "defaultCode": 57402,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 45, "id": 45,
...@@ -1196,8 +1240,8 @@ ...@@ -1196,8 +1240,8 @@
"name": "wink", "name": "wink",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 46 "iconIdx": 134
}, },
{ {
"icon": { "icon": {
...@@ -1212,7 +1256,7 @@ ...@@ -1212,7 +1256,7 @@
"question" "question"
], ],
"defaultCode": 9065, "defaultCode": 9065,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 46, "id": 46,
...@@ -1222,8 +1266,8 @@ ...@@ -1222,8 +1266,8 @@
"name": "wondering", "name": "wondering",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 47 "iconIdx": 135
}, },
{ {
"icon": { "icon": {
...@@ -1238,7 +1282,7 @@ ...@@ -1238,7 +1282,7 @@
"bewildered" "bewildered"
], ],
"defaultCode": 9064, "defaultCode": 9064,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 47, "id": 47,
...@@ -1248,8 +1292,8 @@ ...@@ -1248,8 +1292,8 @@
"name": "confused", "name": "confused",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 48 "iconIdx": 136
}, },
{ {
"icon": { "icon": {
...@@ -1263,7 +1307,7 @@ ...@@ -1263,7 +1307,7 @@
"face" "face"
], ],
"defaultCode": 9060, "defaultCode": 9060,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 48, "id": 48,
...@@ -1273,8 +1317,8 @@ ...@@ -1273,8 +1317,8 @@
"name": "shocked", "name": "shocked",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 49 "iconIdx": 137
}, },
{ {
"icon": { "icon": {
...@@ -1288,7 +1332,7 @@ ...@@ -1288,7 +1332,7 @@
"face" "face"
], ],
"defaultCode": 9759, "defaultCode": 9759,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 49, "id": 49,
...@@ -1298,8 +1342,8 @@ ...@@ -1298,8 +1342,8 @@
"name": "evil", "name": "evil",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 50 "iconIdx": 138
}, },
{ {
"icon": { "icon": {
...@@ -1314,7 +1358,7 @@ ...@@ -1314,7 +1358,7 @@
"rage" "rage"
], ],
"defaultCode": 57407, "defaultCode": 57407,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 50, "id": 50,
...@@ -1324,8 +1368,8 @@ ...@@ -1324,8 +1368,8 @@
"name": "angry", "name": "angry",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 51 "iconIdx": 139
}, },
{ {
"icon": { "icon": {
...@@ -1339,7 +1383,7 @@ ...@@ -1339,7 +1383,7 @@
"face" "face"
], ],
"defaultCode": 57408, "defaultCode": 57408,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 51, "id": 51,
...@@ -1349,8 +1393,8 @@ ...@@ -1349,8 +1393,8 @@
"name": "cool", "name": "cool",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 52 "iconIdx": 140
}, },
{ {
"icon": { "icon": {
...@@ -1364,7 +1408,7 @@ ...@@ -1364,7 +1408,7 @@
"face" "face"
], ],
"defaultCode": 57409, "defaultCode": 57409,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 52, "id": 52,
...@@ -1374,8 +1418,8 @@ ...@@ -1374,8 +1418,8 @@
"name": "grin", "name": "grin",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 53 "iconIdx": 141
}, },
{ {
"icon": { "icon": {
...@@ -1387,7 +1431,7 @@ ...@@ -1387,7 +1431,7 @@
"information" "information"
], ],
"defaultCode": 9056, "defaultCode": 9056,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 53, "id": 53,
...@@ -1397,8 +1441,8 @@ ...@@ -1397,8 +1441,8 @@
"name": "info", "name": "info",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 54 "iconIdx": 142
}, },
{ {
"icon": { "icon": {
...@@ -1413,7 +1457,7 @@ ...@@ -1413,7 +1457,7 @@
"exclamation" "exclamation"
], ],
"defaultCode": 57375, "defaultCode": 57375,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 54, "id": 54,
...@@ -1423,8 +1467,8 @@ ...@@ -1423,8 +1467,8 @@
"name": "notification", "name": "notification",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 55 "iconIdx": 143
}, },
{ {
"icon": { "icon": {
...@@ -1436,7 +1480,7 @@ ...@@ -1436,7 +1480,7 @@
"sign" "sign"
], ],
"defaultCode": 9888, "defaultCode": 9888,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 55, "id": 55,
...@@ -1446,8 +1490,8 @@ ...@@ -1446,8 +1490,8 @@
"name": "warning", "name": "warning",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 56 "iconIdx": 144
}, },
{ {
"icon": { "icon": {
...@@ -1459,7 +1503,7 @@ ...@@ -1459,7 +1503,7 @@
"correct" "correct"
], ],
"defaultCode": 57413, "defaultCode": 57413,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 56, "id": 56,
...@@ -1469,8 +1513,8 @@ ...@@ -1469,8 +1513,8 @@
"name": "spell-check", "name": "spell-check",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 57 "iconIdx": 145
}, },
{ {
"icon": { "icon": {
...@@ -1485,7 +1529,7 @@ ...@@ -1485,7 +1529,7 @@
"audio" "audio"
], ],
"defaultCode": 57414, "defaultCode": 57414,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 57, "id": 57,
...@@ -1495,8 +1539,8 @@ ...@@ -1495,8 +1539,8 @@
"name": "volume-high", "name": "volume-high",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 58 "iconIdx": 146
}, },
{ {
"icon": { "icon": {
...@@ -1510,7 +1554,7 @@ ...@@ -1510,7 +1554,7 @@
"audio" "audio"
], ],
"defaultCode": 57415, "defaultCode": 57415,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 58, "id": 58,
...@@ -1520,8 +1564,8 @@ ...@@ -1520,8 +1564,8 @@
"name": "volume-medium", "name": "volume-medium",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 59 "iconIdx": 147
}, },
{ {
"icon": { "icon": {
...@@ -1535,7 +1579,7 @@ ...@@ -1535,7 +1579,7 @@
"audio" "audio"
], ],
"defaultCode": 57416, "defaultCode": 57416,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 59, "id": 59,
...@@ -1545,8 +1589,8 @@ ...@@ -1545,8 +1589,8 @@
"name": "volume-low", "name": "volume-low",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 60 "iconIdx": 148
}, },
{ {
"icon": { "icon": {
...@@ -1561,7 +1605,7 @@ ...@@ -1561,7 +1605,7 @@
"mute" "mute"
], ],
"defaultCode": 57417, "defaultCode": 57417,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 60, "id": 60,
...@@ -1571,8 +1615,8 @@ ...@@ -1571,8 +1615,8 @@
"name": "volume-mute", "name": "volume-mute",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 61 "iconIdx": 149
}, },
{ {
"icon": { "icon": {
...@@ -1587,7 +1631,7 @@ ...@@ -1587,7 +1631,7 @@
"mute" "mute"
], ],
"defaultCode": 57418, "defaultCode": 57418,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 61, "id": 61,
...@@ -1597,8 +1641,8 @@ ...@@ -1597,8 +1641,8 @@
"name": "volume-mute2", "name": "volume-mute2",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 62 "iconIdx": 150
}, },
{ {
"icon": { "icon": {
...@@ -1612,7 +1656,7 @@ ...@@ -1612,7 +1656,7 @@
"audio" "audio"
], ],
"defaultCode": 57419, "defaultCode": 57419,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 62, "id": 62,
...@@ -1622,8 +1666,8 @@ ...@@ -1622,8 +1666,8 @@
"name": "volume-decrease", "name": "volume-decrease",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 63 "iconIdx": 151
}, },
{ {
"icon": { "icon": {
...@@ -1637,7 +1681,7 @@ ...@@ -1637,7 +1681,7 @@
"audio" "audio"
], ],
"defaultCode": 57420, "defaultCode": 57420,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 63, "id": 63,
...@@ -1647,8 +1691,8 @@ ...@@ -1647,8 +1691,8 @@
"name": "volume-increase", "name": "volume-increase",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 64 "iconIdx": 152
}, },
{ {
"icon": { "icon": {
...@@ -1660,7 +1704,7 @@ ...@@ -1660,7 +1704,7 @@
"wysiwyg" "wysiwyg"
], ],
"defaultCode": 57421, "defaultCode": 57421,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 64, "id": 64,
...@@ -1670,8 +1714,8 @@ ...@@ -1670,8 +1714,8 @@
"name": "bold", "name": "bold",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 65 "iconIdx": 153
}, },
{ {
"icon": { "icon": {
...@@ -1683,7 +1727,7 @@ ...@@ -1683,7 +1727,7 @@
"wysiwyg" "wysiwyg"
], ],
"defaultCode": 57422, "defaultCode": 57422,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 65, "id": 65,
...@@ -1693,8 +1737,8 @@ ...@@ -1693,8 +1737,8 @@
"name": "underline", "name": "underline",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 66 "iconIdx": 154
}, },
{ {
"icon": { "icon": {
...@@ -1706,7 +1750,7 @@ ...@@ -1706,7 +1750,7 @@
"wysiwyg" "wysiwyg"
], ],
"defaultCode": 57423, "defaultCode": 57423,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 66, "id": 66,
...@@ -1716,8 +1760,8 @@ ...@@ -1716,8 +1760,8 @@
"name": "italic", "name": "italic",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 67 "iconIdx": 155
}, },
{ {
"icon": { "icon": {
...@@ -1729,7 +1773,7 @@ ...@@ -1729,7 +1773,7 @@
"wysiwyg" "wysiwyg"
], ],
"defaultCode": 57424, "defaultCode": 57424,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 67, "id": 67,
...@@ -1739,8 +1783,8 @@ ...@@ -1739,8 +1783,8 @@
"name": "strikethrough", "name": "strikethrough",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 68 "iconIdx": 156
}, },
{ {
"icon": { "icon": {
...@@ -1756,7 +1800,7 @@ ...@@ -1756,7 +1800,7 @@
"blank" "blank"
], ],
"defaultCode": 57427, "defaultCode": 57427,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 68, "id": 68,
...@@ -1766,8 +1810,8 @@ ...@@ -1766,8 +1810,8 @@
"name": "newtab", "name": "newtab",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 69 "iconIdx": 157
}, },
{ {
"icon": { "icon": {
...@@ -1779,7 +1823,7 @@ ...@@ -1779,7 +1823,7 @@
"social" "social"
], ],
"defaultCode": 57429, "defaultCode": 57429,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 69, "id": 69,
...@@ -1789,8 +1833,8 @@ ...@@ -1789,8 +1833,8 @@
"name": "youtube", "name": "youtube",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 70 "iconIdx": 158
}, },
{ {
"icon": { "icon": {
...@@ -1805,7 +1849,7 @@ ...@@ -1805,7 +1849,7 @@
"cross" "cross"
], ],
"defaultCode": 10005, "defaultCode": 10005,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 70, "id": 70,
...@@ -1815,8 +1859,8 @@ ...@@ -1815,8 +1859,8 @@
"name": "close", "name": "close",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 71 "iconIdx": 159
}, },
{ {
"icon": { "icon": {
...@@ -1832,7 +1876,7 @@ ...@@ -1832,7 +1876,7 @@
"banned" "banned"
], ],
"defaultCode": 10008, "defaultCode": 10008,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 71, "id": 71,
...@@ -1842,8 +1886,8 @@ ...@@ -1842,8 +1886,8 @@
"name": "blocked", "name": "blocked",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 72 "iconIdx": 160
}, },
{ {
"icon": { "icon": {
...@@ -1857,7 +1901,7 @@ ...@@ -1857,7 +1901,7 @@
"delete" "delete"
], ],
"defaultCode": 57432, "defaultCode": 57432,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 72, "id": 72,
...@@ -1867,8 +1911,8 @@ ...@@ -1867,8 +1911,8 @@
"name": "cancel-circle", "name": "cancel-circle",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 73 "iconIdx": 161
}, },
{ {
"icon": { "icon": {
...@@ -1881,7 +1925,7 @@ ...@@ -1881,7 +1925,7 @@
"subtract" "subtract"
], ],
"defaultCode": 57434, "defaultCode": 57434,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 73, "id": 73,
...@@ -1891,8 +1935,8 @@ ...@@ -1891,8 +1935,8 @@
"name": "minus", "name": "minus",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 74 "iconIdx": 162
}, },
{ {
"icon": { "icon": {
...@@ -1905,7 +1949,7 @@ ...@@ -1905,7 +1949,7 @@
"sum" "sum"
], ],
"defaultCode": 10010, "defaultCode": 10010,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 74, "id": 74,
...@@ -1915,8 +1959,8 @@ ...@@ -1915,8 +1959,8 @@
"name": "plus", "name": "plus",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 75 "iconIdx": 163
}, },
{ {
"icon": { "icon": {
...@@ -1930,7 +1974,7 @@ ...@@ -1930,7 +1974,7 @@
"selected" "selected"
], ],
"defaultCode": 9745, "defaultCode": 9745,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 75, "id": 75,
...@@ -1940,8 +1984,8 @@ ...@@ -1940,8 +1984,8 @@
"name": "checkbox-checked", "name": "checkbox-checked",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 76 "iconIdx": 164
}, },
{ {
"icon": { "icon": {
...@@ -1954,7 +1998,7 @@ ...@@ -1954,7 +1998,7 @@
"square" "square"
], ],
"defaultCode": 11047, "defaultCode": 11047,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 76, "id": 76,
...@@ -1964,8 +2008,8 @@ ...@@ -1964,8 +2008,8 @@
"name": "checkbox-unchecked", "name": "checkbox-unchecked",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 77 "iconIdx": 165
}, },
{ {
"icon": { "icon": {
...@@ -1977,7 +2021,7 @@ ...@@ -1977,7 +2021,7 @@
"partial" "partial"
], ],
"defaultCode": 11048, "defaultCode": 11048,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 77, "id": 77,
...@@ -1987,8 +2031,8 @@ ...@@ -1987,8 +2031,8 @@
"name": "checkbox-partial", "name": "checkbox-partial",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 78 "iconIdx": 166
}, },
{ {
"icon": { "icon": {
...@@ -1999,7 +2043,7 @@ ...@@ -1999,7 +2043,7 @@
"radio-checked" "radio-checked"
], ],
"defaultCode": 11046, "defaultCode": 11046,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 78, "id": 78,
...@@ -2009,8 +2053,8 @@ ...@@ -2009,8 +2053,8 @@
"name": "radio-checked", "name": "radio-checked",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 79 "iconIdx": 167
}, },
{ {
"icon": { "icon": {
...@@ -2022,7 +2066,7 @@ ...@@ -2022,7 +2066,7 @@
"circle" "circle"
], ],
"defaultCode": 11045, "defaultCode": 11045,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 79, "id": 79,
...@@ -2032,8 +2076,8 @@ ...@@ -2032,8 +2076,8 @@
"name": "radio-unchecked", "name": "radio-unchecked",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 80 "iconIdx": 168
}, },
{ {
"icon": { "icon": {
...@@ -2045,7 +2089,7 @@ ...@@ -2045,7 +2089,7 @@
"information" "information"
], ],
"defaultCode": 57433, "defaultCode": 57433,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 80, "id": 80,
...@@ -2055,8 +2099,8 @@ ...@@ -2055,8 +2099,8 @@
"name": "info2", "name": "info2",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 81 "iconIdx": 169
}, },
{ {
"icon": { "icon": {
...@@ -2068,7 +2112,7 @@ ...@@ -2068,7 +2112,7 @@
"paper" "paper"
], ],
"defaultCode": 57345, "defaultCode": 57345,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 81, "id": 81,
...@@ -2078,8 +2122,8 @@ ...@@ -2078,8 +2122,8 @@
"name": "newspaper", "name": "newspaper",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 82 "iconIdx": 170
}, },
{ {
"icon": { "icon": {
...@@ -2093,7 +2137,7 @@ ...@@ -2093,7 +2137,7 @@
"graphic" "graphic"
], ],
"defaultCode": 11028, "defaultCode": 11028,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 82, "id": 82,
...@@ -2103,8 +2147,8 @@ ...@@ -2103,8 +2147,8 @@
"name": "image", "name": "image",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 83 "iconIdx": 171
}, },
{ {
"icon": { "icon": {
...@@ -2115,7 +2159,7 @@ ...@@ -2115,7 +2159,7 @@
"offline" "offline"
], ],
"defaultCode": 57346, "defaultCode": 57346,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 83, "id": 83,
...@@ -2125,8 +2169,8 @@ ...@@ -2125,8 +2169,8 @@
"name": "offline", "name": "offline",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 84 "iconIdx": 172
}, },
{ {
"icon": { "icon": {
...@@ -2137,7 +2181,7 @@ ...@@ -2137,7 +2181,7 @@
"busy" "busy"
], ],
"defaultCode": 57348, "defaultCode": 57348,
"grid": 0 "grid": 16
}, },
"properties": { "properties": {
"id": 84, "id": 84,
...@@ -2147,8 +2191,8 @@ ...@@ -2147,8 +2191,8 @@
"name": "busy", "name": "busy",
"ligatures": "" "ligatures": ""
}, },
"setIdx": 0, "setIdx": 1,
"iconIdx": 85 "iconIdx": 173
} }
], ],
"height": 1024, "height": 1024,
...@@ -2172,6 +2216,7 @@ ...@@ -2172,6 +2216,7 @@
"imagePref": {}, "imagePref": {},
"historySize": 100, "historySize": 100,
"showCodes": true, "showCodes": true,
"search": "" "search": "",
"gridSize": 16
} }
} }
\ No newline at end of file
@font-face { @font-face {
font-family: 'icomoon'; font-family: 'icomoon';
src:url('fonts/icomoon.eot?7poj4t'); src:url('fonts/icomoon.eot?-m2p76k');
src:url('fonts/icomoon.eot?#iefix7poj4t') format('embedded-opentype'), src:url('fonts/icomoon.eot?#iefix-m2p76k') format('embedded-opentype'),
url('fonts/icomoon.woff?7poj4t') format('woff'), url('fonts/icomoon.woff?-m2p76k') format('woff'),
url('fonts/icomoon.ttf?7poj4t') format('truetype'), url('fonts/icomoon.ttf?-m2p76k') format('truetype'),
url('fonts/icomoon.svg?7poj4t#icomoon') format('svg'); url('fonts/icomoon.svg?-m2p76k#icomoon') format('svg');
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
} }
...@@ -23,8 +23,14 @@ ...@@ -23,8 +23,14 @@
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.icon-closed:before {
content: "\25ba";
}
.icon-opened:before {
content: "\25bc";
}
.icon-checkmark:before { .icon-checkmark:before {
content: "\e600"; content: "\2713";
} }
.icon-home:before { .icon-home:before {
content: "\e000"; content: "\e000";
...@@ -38,7 +44,7 @@ ...@@ -38,7 +44,7 @@
.icon-camera2:before { .icon-camera2:before {
content: "\2616"; content: "\2616";
} }
.icon-play:before { .icon-play22:before {
content: "\25d9"; content: "\25d9";
} }
.icon-music:before { .icon-music:before {
......
...@@ -226,13 +226,14 @@ ...@@ -226,13 +226,14 @@
allow_otr: true, allow_otr: true,
auto_list_rooms: false, auto_list_rooms: false,
auto_subscribe: false, auto_subscribe: false,
bosh_service_url: 'https://bind.opkode.com', // Please use this connection manager only for testing purposes bosh_service_url: 'https://bind.conversejs.org', // Please use this connection manager only for testing purposes
debug: true , debug: true ,
hide_muc_server: false, hide_muc_server: false,
i18n: locales['en'], // Refer to ./locale/locales.js to see which locales are supported i18n: locales['en'], // Refer to ./locale/locales.js to see which locales are supported
prebind: false, prebind: false,
show_controlbox_by_default: true, show_controlbox_by_default: true,
xhr_user_search: false, xhr_user_search: false,
roster_groups: true
}); });
}); });
</script> </script>
......
...@@ -46,8 +46,14 @@ ...@@ -46,8 +46,14 @@
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.icon-closed:before {
content: "\25ba";
}
.icon-opened:before {
content: "\25bc";
}
.icon-checkmark:before { .icon-checkmark:before {
content: "\e600"; content: "\2713";
} }
#conversejs .icon-home:before { #conversejs .icon-home:before {
content: "\e000"; content: "\e000";
...@@ -897,8 +903,7 @@ dl.add-converse-contact { ...@@ -897,8 +903,7 @@ dl.add-converse-contact {
} }
#conversejs .controlbox-pane dt { #conversejs .controlbox-pane dt {
margin: 0; padding: 3px;
padding-top: 0.5em;
} }
#conversejs .chatroom-form-container { #conversejs .chatroom-form-container {
...@@ -939,11 +944,11 @@ dl.add-converse-contact { ...@@ -939,11 +944,11 @@ dl.add-converse-contact {
float: right; float: right;
} }
#conversejs #converse-roster dd.odd { #converse-roster dd.odd {
background-color: #DCEAC5; /* Make this difference */ background-color: #DCEAC5; /* Make this difference */
} }
#conversejs #converse-roster dd.current-xmpp-contact span { #converse-roster dd.current-xmpp-contact span {
font-size: 16px; font-size: 16px;
float: left; float: left;
color: rgb(79, 79, 79); color: rgb(79, 79, 79);
...@@ -954,8 +959,8 @@ dl.add-converse-contact { ...@@ -954,8 +959,8 @@ dl.add-converse-contact {
float: right; float: right;
} }
#conversejs #converse-roster dd a, #converse-roster dd a,
#conversejs #converse-roster dd span { #converse-roster dd span {
text-shadow: 0 1px 0 rgba(250, 250, 250, 1); text-shadow: 0 1px 0 rgba(250, 250, 250, 1);
display: inline-block; display: inline-block;
overflow: hidden; overflow: hidden;
...@@ -963,11 +968,20 @@ dl.add-converse-contact { ...@@ -963,11 +968,20 @@ dl.add-converse-contact {
text-overflow: ellipsis; text-overflow: ellipsis;
} }
#conversejs #converse-roster dd span { #conversejs #converse-roster span.req-contact-name {
width: 65%;
}
#conversejs #converse-roster span.pending-contact-name,
#conversejs #converse-roster a.open-chat {
width: 80%;
}
#converse-roster dd span {
padding: 0 5px 0 0; padding: 0 5px 0 0;
} }
#conversejs #converse-roster { #converse-roster {
overflow-y: auto; overflow-y: auto;
overflow-x: hidden; overflow-x: hidden;
width: 100%; width: 100%;
...@@ -977,6 +991,10 @@ dl.add-converse-contact { ...@@ -977,6 +991,10 @@ dl.add-converse-contact {
height: ~"calc(100% - 70px)"; height: ~"calc(100% - 70px)";
} }
#converse-roster .group-toggle {
color: #666;
}
#conversejs dd.available-chatroom { #conversejs dd.available-chatroom {
overflow-x: hidden; overflow-x: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
...@@ -988,8 +1006,8 @@ dl.add-converse-contact { ...@@ -988,8 +1006,8 @@ dl.add-converse-contact {
width: 148px; width: 148px;
} }
#conversejs #available-chatrooms dt, #available-chatrooms dt,
#conversejs #converse-roster dt { #converse-roster dt {
font-weight: normal; font-weight: normal;
font-size: 13px; font-size: 13px;
color: #666; color: #666;
...@@ -998,7 +1016,7 @@ dl.add-converse-contact { ...@@ -998,7 +1016,7 @@ dl.add-converse-contact {
text-shadow: 0 1px 0 rgba(250, 250, 250, 1); text-shadow: 0 1px 0 rgba(250, 250, 250, 1);
} }
#conversejs #converse-roster dt { #converse-roster dt {
display: none; display: none;
} }
...@@ -1060,6 +1078,12 @@ dl.add-converse-contact { ...@@ -1060,6 +1078,12 @@ dl.add-converse-contact {
line-height: 16px; line-height: 16px;
} }
#conversejs .group-toggle {
display: block;
width: 100%;
}
#conversejs .roster-group:hover,
#conversejs dd.available-chatroom:hover, #conversejs dd.available-chatroom:hover,
#conversejs #converse-roster dd:hover { #conversejs #converse-roster dd:hover {
background-color: #eee; background-color: #eee;
...@@ -1081,10 +1105,6 @@ dl.add-converse-contact { ...@@ -1081,10 +1105,6 @@ dl.add-converse-contact {
display: inline-block; display: inline-block;
} }
#conversejs #converse-roster a.open-chat {
width: 80%;
}
#conversejs .chatbox, #conversejs .chatbox,
#conversejs .chatroom { #conversejs .chatroom {
height: 25px; height: 25px;
...@@ -1462,6 +1482,10 @@ input.custom-xmpp-status { ...@@ -1462,6 +1482,10 @@ input.custom-xmpp-status {
background-color: #bed6e5; background-color: #bed6e5;
} }
#conversejs .chatbox .dropdown dd.search-xmpp ul li:hover {
background-color: #bed6e5;
}
#conversejs .xmpp-status-menu li a { #conversejs .xmpp-status-menu li a {
width: 100%; width: 100%;
} }
......
<!DOCTYPE html>
<html lang="en">
<head>
<title id="pageTitle">Converse.js: Mockup</title>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="description" content="Converse.js: Mockup" />
<link type="text/css" href="../css/theme.css" rel="stylesheet" media="screen" />
<link type="text/css" href="../css/converse.css" rel="stylesheet" media="screen" />
<script src="../components/jquery/dist/jquery.min.js"></script>
</head>
<body id="page-top" data-spy="scroll" data-target=".navbar-custom">
<!-- HEADER -->
<div id="header_wrap" class="outer">
<header class="inner">
<h1 id="project_title"><a href="http://conversejs.org">Converse.js</a></h1>
<h2 id="project_tagline">Static Mockup</h2>
</header>
</div>
<div id="conversejs">
<a id="toggle-controlbox" href="#" class="toggle-controlbox">
<span class="conn-feedback">Toggle Chat</span>
<span style="display: none" id="online-count">(0)</span>
</a>
<div id="controlbox" class="chatbox" style="opacity: 1; display: inline;">
<div class="box-flyout">
<div class="dragresize dragresize-tm"></div>
<div class="chat-head controlbox-head">
<ul id="controlbox-tabs">
<li><a class="current" href="#login">Sign in</a></li>
</ul>
<a class="close-chatbox-button icon-close"></a>
</div>
<div id="login-dialog">
<form id="converse-login">
<label>XMPP/Jabber Username:</label><input type="text" id="jid">
<label>Password:</label><input type="password" id="password">
<input class="login-submit" type="submit" value="Log In">
</form>
<span class="conn-feedback"></span>
</div>
</div>
</div>
<div id="controlbox" class="chatbox" style="opacity: 1; display: inline;">
<div class="box-flyout">
<div class="dragresize dragresize-tm"></div>
<div class="chat-head controlbox-head">
<ul id="controlbox-tabs">
<li><a class="s current" href="#users">Contacts</a></li>
<li><a class="s" href="#chatrooms">Rooms</a></li>
</ul>
<a class="close-chatbox-button icon-close"></a>
</div>
<div id="users" class="controlbox-pane" style="display: block;">
<form class="set-xmpp-status" action="" method="post">
<span id="xmpp-status-holder">
<dl id="target" class="dropdown">
<dt id="fancy-xmpp-status-select" class="fancy-dropdown">
<div class="xmpp-status">
<a class="choose-xmpp-status online" data-value="I am online" href="#" title="Click to change your chat status">
<span class="icon-online"></span>
I am online
</a>
<a class="change-xmpp-status-message icon-pencil" href="#" title="Click here to write a custom status message"></a>
</div>
</dt>
<dd>
<ul style="display: none;" class="xmpp-status-menu">
<li>
<a href="#" class="online" data-value="online">
<span class="icon-online"></span>
Online</a>
</li>
<li>
<a href="#" class="dnd" data-value="dnd">
<span class="icon-dnd"></span>
Busy</a>
</li>
<li>
<a href="#" class="away" data-value="away">
<span class="icon-away"></span>
Away</a>
</li>
<li>
<a href="#" class="offline" data-value="offline">
<span class="icon-offline"></span>
Offline</a>
</li>
</ul>
</dd>
</dl>
</span>
</form>
<dl class="add-converse-contact dropdown">
<dt id="xmpp-contact-search" class="fancy-dropdown">
<a class="toggle-xmpp-contact-form" href="#" title="Click to add new chat contacts">
<span class="icon-plus"></span>
Add a contact
</a>
</dt>
<dd class="search-xmpp" style="display:none">
<ul>
<li>
<form class="add-xmpp-contact">
<input type="text" name="identifier" class="username" placeholder="Contact username">
<button type="submit">Add</button>
</form>
</li>
<li></li>
</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>
<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="#" 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="#">&nbsp;</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>
<script>
$(document).ready(function () {
$('a[href=#chatrooms]').click(function (ev) {
switchTab(ev);
});
$('a[href=#users]').click(function (ev) {
switchTab(ev);
});
$("a.choose-xmpp-status").click(function (ev) {
ev.preventDefault();
$(ev.target).parent().parent().siblings('dd').find('ul').toggle('fast');
});
$("a.change-xmpp-status-message").click(function (ev) {
ev.preventDefault();
var form = ''+
'<form id="set-custom-xmpp-status">' +
'<input type="text" class="custom-xmpp-status"I am online"'+
'placeholder="I am online"/>' +
'<button type="submit">Save</button>' +
'</form>';
$(ev.target).closest('.xmpp-status').replaceWith(form);
$(ev.target).closest('.custom-xmpp-status').focus().focus();
});
$('.toggle-xmpp-contact-form').click(function (ev) {
ev.preventDefault();
$(ev.target).parent().parent().find('.search-xmpp').toggle('fast', function () {
if ($(this).is(':visible')) {
$(this).find('input.username').focus();
}
});
});
var switchTab = function (ev) {
ev.preventDefault();
var $tab = $(ev.target),
$sibling = $tab.parent().siblings('li').children('a'),
$tab_panel = $($tab.attr('href')),
$sibling_panel = $($sibling.attr('href'));
$sibling_panel.hide();
$sibling.removeClass('current');
$tab.addClass('current');
$tab_panel.show();
}
$(function() {
$('.group-toggle').click(function(ev) {
ev.preventDefault();
var $el = $(ev.target);
$el.parent().nextUntil('dt').slideToggle();
if ($el.hasClass("icon-opened")) {
$el.removeClass("icon-opened").addClass("icon-closed");
} else {
$el.removeClass("icon-closed").addClass("icon-opened");
}
});
$('.close-chatbox-button').click(function(ev) {
var $grandparent = $(ev.target).parent().parent().parent();
$grandparent.hide(300, function () {
// Webkit fix
document.getElementById('conversejs').style.display = 'none';
document.getElementById('conversejs').offsetHeight; // no need to store this anywhere, the reference is enough
document.getElementById('conversejs').style.display = 'block';
});
});
$('.toggle-chatbox-button').click(function(ev) {
var $grandparent = $(ev.target).parent().parent().parent();
$grandparent.fadeOut('fast');
});
// Clickable Dropdown
$('.toggle-otr').click(function(e) {
$('.toggle-otr ul').slideToggle(200);
e.stopPropagation();
});
$('.toggle-smiley').click(function(e) {
$(e.target).find('ul').slideToggle(200);
e.stopPropagation();
});
$(document).click(function() {
if ($('.toggle-otr ul').is(':visible')) {
$('.toggle-otr ul', this).slideUp(200);
}
if ($('.toggle-smiley ul').is(':visible')) {
$('.toggle-smiley ul', this).slideUp(200);
}
});
});
});
</script>
</html>
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
runs(function () { runs(function () {
utils.closeAllChatBoxes(); utils.closeAllChatBoxes();
utils.removeControlBox(); utils.removeControlBox();
converse.roster.browserStorage._clear(); utils.clearBrowserStorage();
utils.initConverse(); utils.initConverse();
utils.createContacts(); utils.createContacts();
utils.openControlBox(); utils.openControlBox();
...@@ -22,23 +22,19 @@ ...@@ -22,23 +22,19 @@
}); });
it("is created when you click on a roster item", $.proxy(function () { it("is created when you click on a roster item", $.proxy(function () {
var i, $el, click, jid, view, chatboxview; var i, $el, click, jid, chatboxview;
// openControlBox was called earlier, so the controlbox is // openControlBox was called earlier, so the controlbox is
// visible, but no other chat boxes have been created. // visible, but no other chat boxes have been created.
expect(this.chatboxes.length).toEqual(1); expect(this.chatboxes.length).toEqual(1);
spyOn(this.chatboxviews, 'trimChats'); spyOn(this.chatboxviews, 'trimChats');
expect($("#conversejs .chatbox").length).toBe(1); // Controlbox is open expect($("#conversejs .chatbox").length).toBe(1); // Controlbox is open
var online_contacts = this.rosterview.$el.find('dt#xmpp-contacts').siblings('dd.current-xmpp-contact').find('a.open-chat'); 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++) { for (i=0; i<online_contacts.length; i++) {
$el = $(online_contacts[i]); $el = $(online_contacts[i]);
jid = $el.text().replace(/ /g,'.').toLowerCase() + '@localhost'; jid = $el.text().replace(/ /g,'.').toLowerCase() + '@localhost';
view = this.rosterview.get(jid);
spyOn(view, 'openChat').andCallThrough();
view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
$el.click(); $el.click();
chatboxview = this.chatboxviews.get(jid); chatboxview = this.chatboxviews.get(jid);
expect(view.openChat).toHaveBeenCalled();
expect(this.chatboxes.length).toEqual(i+2); expect(this.chatboxes.length).toEqual(i+2);
expect(this.chatboxviews.trimChats).toHaveBeenCalled(); expect(this.chatboxviews.trimChats).toHaveBeenCalled();
// Check that new chat boxes are created to the left of the // Check that new chat boxes are created to the left of the
...@@ -49,7 +45,7 @@ ...@@ -49,7 +45,7 @@
}, converse)); }, converse));
it("can be trimmed to conserve space", $.proxy(function () { it("can be trimmed to conserve space", $.proxy(function () {
var i, $el, click, jid, key, view, chatbox, chatboxview; var i, $el, click, jid, key, chatbox, chatboxview;
// openControlBox was called earlier, so the controlbox is // openControlBox was called earlier, so the controlbox is
// visible, but no other chat boxes have been created. // visible, but no other chat boxes have been created.
var trimmed_chatboxes = converse.minimized_chats; var trimmed_chatboxes = converse.minimized_chats;
...@@ -60,11 +56,10 @@ ...@@ -60,11 +56,10 @@
expect($("#conversejs .chatbox").length).toBe(1); // Controlbox is open expect($("#conversejs .chatbox").length).toBe(1); // Controlbox is open
// Test that they can be trimmed // Test that they can be trimmed
var online_contacts = this.rosterview.$el.find('dt#xmpp-contacts').siblings('dd.current-xmpp-contact').find('a.open-chat'); 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++) { for (i=0; i<online_contacts.length; i++) {
$el = $(online_contacts[i]); $el = $(online_contacts[i]);
jid = $el.text().replace(/ /g,'.').toLowerCase() + '@localhost'; jid = $el.text().replace(/ /g,'.').toLowerCase() + '@localhost';
view = this.rosterview.get(jid);
$el.click(); $el.click();
expect(this.chatboxviews.trimChats).toHaveBeenCalled(); expect(this.chatboxviews.trimChats).toHaveBeenCalled();
...@@ -96,7 +91,7 @@ ...@@ -96,7 +91,7 @@
it("is focused if its already open and you click on its corresponding roster item", $.proxy(function () { it("is focused if its already open and you click on its corresponding roster item", $.proxy(function () {
var contact_jid = mock.cur_names[2].replace(/ /g,'.').toLowerCase() + '@localhost'; var contact_jid = mock.cur_names[2].replace(/ /g,'.').toLowerCase() + '@localhost';
var i, $el, click, jid, view, chatboxview, chatbox; var i, $el, click, jid, chatboxview, chatbox;
// openControlBox was called earlier, so the controlbox is // openControlBox was called earlier, so the controlbox is
// visible, but no other chat boxes have been created. // visible, but no other chat boxes have been created.
expect(this.chatboxes.length).toEqual(1); expect(this.chatboxes.length).toEqual(1);
...@@ -105,11 +100,7 @@ ...@@ -105,11 +100,7 @@
spyOn(chatboxview, 'focus'); spyOn(chatboxview, 'focus');
$el = this.rosterview.$el.find('a.open-chat:contains("'+chatbox.get('fullname')+'")'); $el = this.rosterview.$el.find('a.open-chat:contains("'+chatbox.get('fullname')+'")');
jid = $el.text().replace(/ /g,'.').toLowerCase() + '@localhost'; jid = $el.text().replace(/ /g,'.').toLowerCase() + '@localhost';
view = this.rosterview.get(jid);
spyOn(view, 'openChat').andCallThrough();
view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
$el.click(); $el.click();
expect(view.openChat).toHaveBeenCalled();
expect(this.chatboxes.length).toEqual(2); expect(this.chatboxes.length).toEqual(2);
expect(chatboxview.focus).toHaveBeenCalled(); expect(chatboxview.focus).toHaveBeenCalled();
}, converse)); }, converse));
......
...@@ -7,6 +7,23 @@ ...@@ -7,6 +7,23 @@
} }
); );
} (this, function (mock, utils) { } (this, function (mock, utils) {
var checkHeaderToggling = function ($header) {
var $toggle = $header.find('a.group-toggle');
expect($header.css('display')).toEqual('block');
expect($header.nextUntil('dt', 'dd').length === $header.nextUntil('dt', 'dd:visible').length).toBeTruthy();
expect($toggle.hasClass('icon-closed')).toBeFalsy();
expect($toggle.hasClass('icon-opened')).toBeTruthy();
$toggle.click();
expect($toggle.hasClass('icon-closed')).toBeTruthy();
expect($toggle.hasClass('icon-opened')).toBeFalsy();
expect($header.nextUntil('dt', 'dd').length === $header.nextUntil('dt', 'dd:hidden').length).toBeTruthy();
$toggle.click();
expect($toggle.hasClass('icon-closed')).toBeFalsy();
expect($toggle.hasClass('icon-opened')).toBeTruthy();
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, utils) {
beforeEach(function () { beforeEach(function () {
runs(function () { runs(function () {
...@@ -107,264 +124,416 @@ ...@@ -107,264 +124,416 @@
describe("The Contacts Roster", $.proxy(function (mock, utils) { describe("The Contacts Roster", $.proxy(function (mock, utils) {
describe("Pending Contacts", $.proxy(function () { describe("A Roster Group", $.proxy(function () {
beforeEach($.proxy(function () {
runs(function () { beforeEach(function () {
converse.rosterview.model.reset(); converse.roster_groups = true;
utils.createContacts('pending').openControlBox(); });
});
waits(50); afterEach(function () {
runs(function () { converse.roster_groups = false;
utils.openContactsPanel(); });
});
}, converse));
it("do not have a heading if there aren't any", $.proxy(function () { function _clearContacts () {
utils.clearBrowserStorage();
converse.rosterview.model.reset(); converse.rosterview.model.reset();
expect(this.rosterview.$el.find('dt#pending-xmpp-contacts').css('display')).toEqual('none'); }
it("can be used to organize existing contacts", $.proxy(function () {
_clearContacts();
var i=0, j=0, t;
spyOn(converse, 'emit');
spyOn(this.rosterview, 'update').andCallThrough();
converse.rosterview.render();
utils.createContacts('pending');
utils.createContacts('requesting');
var groups = {
'colleagues': 3,
'friends & acquaintences': 3,
'Family': 4,
'ænemies': 3,
'Ungrouped': 2
};
_.each(_.keys(groups), $.proxy(function (name) {
j = i;
for (i=j; i<j+groups[name]; i++) {
this.roster.create({
jid: mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost',
subscription: 'both',
ask: null,
groups: name === 'ungrouped'? [] : [name],
fullname: mock.cur_names[i]
});
}
}, converse));
// 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(); });
expect(group_titles).toEqual([
"colleagues",
"Family",
"friends & acquaintences",
"ænemies",
"Ungrouped",
"Contact requests",
"Pending contacts"
]);
// Check that usernames appear alphabetically per group
_.each(_.keys(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());
}, converse));
}, converse)); }, converse));
it("will have their own heading once they have been added", $.proxy(function () { it("can share contacts with other roster groups", $.proxy(function () {
expect(this.rosterview.$el.find('dt#pending-xmpp-contacts').css('display')).toEqual('block'); _clearContacts();
var i=0, j=0, t;
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',
subscription: 'both',
ask: null,
groups: groups,
fullname: mock.cur_names[i]
});
}
// 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));
}, converse));
it("remembers whether it is closed or opened", $.proxy(function () {
var i=0, j=0, t;
var groups = {
'colleagues': 3,
'friends & acquaintences': 3,
'Ungrouped': 2
};
_.each(_.keys(groups), $.proxy(function (name) {
j = i;
for (i=j; i<j+groups[name]; i++) {
this.roster.create({
jid: mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost',
subscription: 'both',
ask: null,
groups: name === 'ungrouped'? [] : [name],
fullname: mock.cur_names[i]
});
}
}, converse));
var view = this.rosterview.get('colleagues');
var $toggle = view.$el.find('a.group-toggle');
expect(view.model.get('state')).toBe('opened');
$toggle.click();
expect(view.model.get('state')).toBe('closed');
$toggle.click();
expect(view.model.get('state')).toBe('opened');
}, converse));
}, converse));
describe("Pending Contacts", $.proxy(function () {
function _clearContacts () {
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();
}
it("can be collapsed under their own header", $.proxy(function () {
_addContacts();
checkHeaderToggling.apply(this, [this.rosterview.get('Pending contacts').$el]);
}, converse)); }, converse));
it("can be added to the roster", $.proxy(function () { it("can be added to the roster", $.proxy(function () {
converse.rosterview.model.reset(); // We want to manually create users so that we can spy _clearContacts();
spyOn(converse, 'emit'); spyOn(converse, 'emit');
spyOn(this.rosterview, 'render').andCallThrough(); spyOn(this.rosterview, 'update').andCallThrough();
runs($.proxy(function () { runs($.proxy(function () {
this.roster.create({ this.roster.create({
jid: mock.pend_names[0].replace(/ /g,'.').toLowerCase() + '@localhost', jid: mock.pend_names[0].replace(/ /g,'.').toLowerCase() + '@localhost',
subscription: 'none', subscription: 'none',
ask: 'subscribe', ask: 'subscribe',
fullname: mock.pend_names[0], fullname: mock.pend_names[0]
is_last: true
}); });
}, converse)); }, converse));
waits(300); waits(300);
runs($.proxy(function () { runs($.proxy(function () {
expect(converse.emit).toHaveBeenCalledWith('rosterViewUpdated');
expect(this.rosterview.$el.is(':visible')).toEqual(true); expect(this.rosterview.$el.is(':visible')).toEqual(true);
expect(this.rosterview.render).toHaveBeenCalled(); expect(this.rosterview.update).toHaveBeenCalled();
}, converse)); }, converse));
}, converse)); }, converse));
it("can be removed by the user", $.proxy(function () { it("can be removed by the user", $.proxy(function () {
var jid = mock.pend_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; _addContacts();
var view = this.rosterview.get(jid); var name = mock.pend_names[0];
var jid = name.replace(/ /g,'.').toLowerCase() + '@localhost';
spyOn(window, 'confirm').andReturn(true); spyOn(window, 'confirm').andReturn(true);
spyOn(converse, 'emit'); spyOn(converse, 'emit');
spyOn(this.connection.roster, 'remove').andCallThrough(); spyOn(this.connection.roster, 'remove').andCallThrough();
spyOn(this.connection.roster, 'unauthorize'); spyOn(this.connection.roster, 'unauthorize');
spyOn(this.rosterview.model, 'remove').andCallThrough(); spyOn(this.rosterview.model, 'remove').andCallThrough();
view.$el.find('.remove-xmpp-contact').click(); converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')")
.siblings('.remove-xmpp-contact').click();
expect(window.confirm).toHaveBeenCalled(); expect(window.confirm).toHaveBeenCalled();
expect(this.connection.roster.remove).toHaveBeenCalled(); expect(this.connection.roster.remove).toHaveBeenCalled();
expect(this.connection.roster.unauthorize).toHaveBeenCalled(); expect(this.connection.roster.unauthorize).toHaveBeenCalled();
expect(this.rosterview.model.remove).toHaveBeenCalled(); expect(this.rosterview.model.remove).toHaveBeenCalled();
// The element must now be detached from the DOM. expect(converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')").length).toEqual(0);
expect(view.$el.closest('html').length).toBeFalsy();
expect(converse.emit).toHaveBeenCalledWith('rosterViewUpdated');
}, converse)); }, converse));
it("will lose their own heading once the last one has been removed", $.proxy(function () { it("do not have a header if there aren't any", $.proxy(function () {
var view; var name = mock.pend_names[0];
_clearContacts();
spyOn(window, 'confirm').andReturn(true);
this.roster.create({
jid: name.replace(/ /g,'.').toLowerCase() + '@localhost',
subscription: 'none',
ask: 'subscribe',
fullname: name
});
expect(this.rosterview.get('Pending contacts').$el.is(':visible')).toEqual(true);
converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')")
.siblings('.remove-xmpp-contact').click();
expect(window.confirm).toHaveBeenCalled();
expect(this.rosterview.get('Pending contacts').$el.is(':visible')).toEqual(false);
}, converse));
it("will lose their own header once the last one has been removed", $.proxy(function () {
_addContacts();
var name;
spyOn(window, 'confirm').andReturn(true); spyOn(window, 'confirm').andReturn(true);
for (i=0; i<mock.pend_names.length; i++) { for (i=0; i<mock.pend_names.length; i++) {
view = this.rosterview.get(mock.pend_names[i].replace(/ /g,'.').toLowerCase() + '@localhost'); name = mock.pend_names[i];
view.$el.find('.remove-xmpp-contact').click(); converse.rosterview.$el.find(".pending-contact-name:contains('"+name+"')")
.siblings('.remove-xmpp-contact').click();
} }
expect(this.rosterview.$el.find('dt#pending-xmpp-contacts').is(':visible')).toBeFalsy(); expect(this.rosterview.$el.find('dt#pending-xmpp-contacts').is(':visible')).toBeFalsy();
}, converse)); }, converse));
it("can be added to the roster and they will be sorted alphabetically", $.proxy(function () { it("can be added to the roster and they will be sorted alphabetically", $.proxy(function () {
converse.rosterview.model.reset(); // We want to manually create users so that we can spy _clearContacts();
var i, t, is_last; var i, t;
spyOn(converse, 'emit'); spyOn(converse, 'emit');
spyOn(this.rosterview, 'render').andCallThrough(); spyOn(this.rosterview, 'update').andCallThrough();
for (i=0; i<mock.pend_names.length; i++) { for (i=0; i<mock.pend_names.length; i++) {
is_last = i===(mock.pend_names.length-1);
this.roster.create({ this.roster.create({
jid: mock.pend_names[i].replace(/ /g,'.').toLowerCase() + '@localhost', jid: mock.pend_names[i].replace(/ /g,'.').toLowerCase() + '@localhost',
subscription: 'none', subscription: 'none',
ask: 'subscribe', ask: 'subscribe',
fullname: mock.pend_names[i], fullname: mock.pend_names[i]
is_last: is_last
}); });
expect(this.rosterview.render).toHaveBeenCalled(); expect(this.rosterview.update).toHaveBeenCalled();
expect(converse.emit).toHaveBeenCalledWith('rosterViewUpdated');
// Check that they are sorted alphabetically
t = this.rosterview.$el.find('dt#pending-xmpp-contacts').siblings('dd.pending-xmpp-contact').find('span').text();
expect(t).toEqual(mock.pend_names.slice(0,i+1).sort().join(''));
} }
// Check that they are sorted alphabetically
t = this.rosterview.get('Pending contacts').$el.siblings('dd.pending-xmpp-contact').find('span').text();
expect(t).toEqual(mock.pend_names.slice(0,i+1).sort().join(''));
}, converse)); }, converse));
}, converse)); }, converse));
describe("Existing Contacts", $.proxy(function () { describe("Existing Contacts", $.proxy(function () {
beforeEach($.proxy(function () { function _clearContacts () {
runs(function () { utils.clearBrowserStorage();
converse.rosterview.model.reset();
utils.createContacts().openControlBox();
});
waits(50);
runs(function () {
utils.openContactsPanel();
});
}, converse));
it("do not have a heading if there aren't any", $.proxy(function () {
converse.rosterview.model.reset(); converse.rosterview.model.reset();
expect(this.rosterview.$el.find('dt#xmpp-contacts').css('display')).toEqual('none'); }
var _addContacts = function () {
_clearContacts();
utils.createContacts().openControlBox().openContactsPanel();
};
it("can be collapsed under their own header", $.proxy(function () {
_addContacts();
checkHeaderToggling.apply(this, [this.rosterview.$el.find('dt.roster-group')]);
}, converse));
it("will be hidden when appearing under a collapsed group", $.proxy(function () {
_addContacts();
this.rosterview.$el.find('dt.roster-group').find('a.group-toggle').click();
var name = "Max Mustermann";
var jid = name.replace(/ /g,'.').toLowerCase() + '@localhost';
converse.roster.create({
ask: null,
fullname: name,
jid: jid,
requesting: false,
subscription: 'both'
});
var view = this.rosterview.get('My contacts').get(jid);
expect(view.$el.is(':visible')).toBe(false);
}, converse)); }, converse));
it("can be added to the roster and they will be sorted alphabetically", $.proxy(function () { it("can be added to the roster and they will be sorted alphabetically", $.proxy(function () {
_clearContacts();
var i, t; var i, t;
converse.rosterview.model.reset();
spyOn(converse, 'emit'); spyOn(converse, 'emit');
spyOn(this.rosterview, 'render').andCallThrough(); spyOn(this.rosterview, 'update').andCallThrough();
for (i=0; i<mock.cur_names.length; i++) { for (i=0; i<mock.cur_names.length; i++) {
this.roster.create({ this.roster.create({
jid: mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost', jid: mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost',
subscription: 'both', subscription: 'both',
ask: null, ask: null,
fullname: mock.cur_names[i], fullname: mock.cur_names[i]
is_last: i===(mock.cur_names.length-1)
}); });
expect(this.rosterview.render).toHaveBeenCalled(); expect(this.rosterview.update).toHaveBeenCalled();
expect(converse.emit).toHaveBeenCalledWith('rosterViewUpdated');
// Check that they are sorted alphabetically
t = this.rosterview.$el.find('dt#xmpp-contacts').siblings('dd.current-xmpp-contact.offline').find('a.open-chat').text();
expect(t).toEqual(mock.cur_names.slice(0,i+1).sort().join(''));
} }
// 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(''));
}, converse));
it("can be removed by the user", $.proxy(function () {
_addContacts();
var name = mock.cur_names[0];
var jid = name.replace(/ /g,'.').toLowerCase() + '@localhost';
spyOn(window, 'confirm').andReturn(true);
spyOn(converse, 'emit');
spyOn(this.connection.roster, 'remove').andCallThrough();
spyOn(this.connection.roster, 'unauthorize');
spyOn(this.rosterview.model, 'remove').andCallThrough();
converse.rosterview.$el.find(".open-chat:contains('"+name+"')")
.siblings('.remove-xmpp-contact').click();
expect(window.confirm).toHaveBeenCalled();
expect(this.connection.roster.remove).toHaveBeenCalled();
expect(this.connection.roster.unauthorize).toHaveBeenCalled();
expect(this.rosterview.model.remove).toHaveBeenCalled();
expect(converse.rosterview.$el.find(".open-chat:contains('"+name+"')").length).toEqual(0);
}, converse)); }, converse));
it("will have their own heading once they have been added", $.proxy(function () {
expect(this.rosterview.$el.find('dt#xmpp-contacts').css('display')).toEqual('block'); it("do not have a header if there aren't any", $.proxy(function () {
var name = mock.cur_names[0];
_clearContacts();
spyOn(window, 'confirm').andReturn(true);
this.roster.create({
jid: name.replace(/ /g,'.').toLowerCase() + '@localhost',
subscription: 'both',
ask: null,
fullname: name
});
expect(this.rosterview.$el.find('dt.roster-group').css('display')).toEqual('block');
converse.rosterview.$el.find(".open-chat:contains('"+name+"')")
.siblings('.remove-xmpp-contact').click();
expect(window.confirm).toHaveBeenCalled();
expect(this.rosterview.$el.find('dt.roster-group').css('display')).toEqual('none');
}, converse)); }, converse));
it("can change their status to online and be sorted alphabetically", $.proxy(function () { it("can change their status to online and be sorted alphabetically", $.proxy(function () {
var item, view, jid, t; _addContacts();
var jid, t;
spyOn(converse, 'emit'); spyOn(converse, 'emit');
spyOn(this.rosterview, 'render').andCallThrough(); spyOn(this.rosterview, 'update').andCallThrough();
for (i=0; i<mock.cur_names.length; i++) { for (i=0; i<mock.cur_names.length; i++) {
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost'; jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
view = this.rosterview.get(jid); this.roster.get(jid).set('chat_status', 'online');
spyOn(view, 'render').andCallThrough(); expect(this.rosterview.update).toHaveBeenCalled();
item = view.model;
item.set('chat_status', 'online');
expect(view.render).toHaveBeenCalled();
expect(this.rosterview.render).toHaveBeenCalled();
expect(converse.emit).toHaveBeenCalledWith('rosterViewUpdated');
// Check that they are sorted alphabetically // Check that they are sorted alphabetically
t = this.rosterview.$el.find('dt#xmpp-contacts').siblings('dd.current-xmpp-contact.online').find('a.open-chat').text(); 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('')); expect(t).toEqual(mock.cur_names.slice(0,i+1).sort().join(''));
} }
}, converse)); }, converse));
it("can change their status to busy and be sorted alphabetically", $.proxy(function () { it("can change their status to busy and be sorted alphabetically", $.proxy(function () {
var item, view, jid, t; _addContacts();
var jid, t;
spyOn(converse, 'emit'); spyOn(converse, 'emit');
spyOn(this.rosterview, 'render').andCallThrough(); spyOn(this.rosterview, 'update').andCallThrough();
for (i=0; i<mock.cur_names.length; i++) { for (i=0; i<mock.cur_names.length; i++) {
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost'; jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
view = this.rosterview.get(jid); this.roster.get(jid).set('chat_status', 'dnd');
spyOn(view, 'render').andCallThrough(); expect(this.rosterview.update).toHaveBeenCalled();
item = view.model;
item.set('chat_status', 'dnd');
expect(view.render).toHaveBeenCalled();
expect(this.rosterview.render).toHaveBeenCalled();
expect(converse.emit).toHaveBeenCalledWith('rosterViewUpdated');
// Check that they are sorted alphabetically // Check that they are sorted alphabetically
t = this.rosterview.$el.find('dt#xmpp-contacts').siblings('dd.current-xmpp-contact.dnd').find('a.open-chat').text(); 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('')); expect(t).toEqual(mock.cur_names.slice(0,i+1).sort().join(''));
} }
}, converse)); }, converse));
it("can change their status to away and be sorted alphabetically", $.proxy(function () { it("can change their status to away and be sorted alphabetically", $.proxy(function () {
var item, view, jid, t; _addContacts();
var jid, t;
spyOn(converse, 'emit'); spyOn(converse, 'emit');
spyOn(this.rosterview, 'render').andCallThrough(); spyOn(this.rosterview, 'update').andCallThrough();
for (i=0; i<mock.cur_names.length; i++) { for (i=0; i<mock.cur_names.length; i++) {
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost'; jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
view = this.rosterview.get(jid); this.roster.get(jid).set('chat_status', 'away');
spyOn(view, 'render').andCallThrough(); expect(this.rosterview.update).toHaveBeenCalled();
item = view.model;
item.set('chat_status', 'away');
expect(view.render).toHaveBeenCalled();
expect(this.rosterview.render).toHaveBeenCalled();
expect(converse.emit).toHaveBeenCalledWith('rosterViewUpdated');
// Check that they are sorted alphabetically // Check that they are sorted alphabetically
t = this.rosterview.$el.find('dt#xmpp-contacts').siblings('dd.current-xmpp-contact.away').find('a.open-chat').text(); 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('')); expect(t).toEqual(mock.cur_names.slice(0,i+1).sort().join(''));
} }
}, converse)); }, converse));
it("can change their status to xa and be sorted alphabetically", $.proxy(function () { it("can change their status to xa and be sorted alphabetically", $.proxy(function () {
var item, view, jid, t; _addContacts();
var jid, t;
spyOn(converse, 'emit'); spyOn(converse, 'emit');
spyOn(this.rosterview, 'render').andCallThrough(); spyOn(this.rosterview, 'update').andCallThrough();
for (i=0; i<mock.cur_names.length; i++) { for (i=0; i<mock.cur_names.length; i++) {
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost'; jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
view = this.rosterview.get(jid); this.roster.get(jid).set('chat_status', 'xa');
spyOn(view, 'render').andCallThrough(); expect(this.rosterview.update).toHaveBeenCalled();
item = view.model;
item.set('chat_status', 'xa');
expect(view.render).toHaveBeenCalled();
expect(this.rosterview.render).toHaveBeenCalled();
expect(converse.emit).toHaveBeenCalledWith('rosterViewUpdated');
// Check that they are sorted alphabetically // Check that they are sorted alphabetically
t = this.rosterview.$el.find('dt#xmpp-contacts').siblings('dd.current-xmpp-contact.xa').find('a.open-chat').text(); 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('')); expect(t).toEqual(mock.cur_names.slice(0,i+1).sort().join(''));
} }
}, converse)); }, converse));
it("can change their status to unavailable and be sorted alphabetically", $.proxy(function () { it("can change their status to unavailable and be sorted alphabetically", $.proxy(function () {
var item, view, jid, t; _addContacts();
var jid, t;
spyOn(converse, 'emit'); spyOn(converse, 'emit');
spyOn(this.rosterview, 'render').andCallThrough(); spyOn(this.rosterview, 'update').andCallThrough();
for (i=0; i<mock.cur_names.length; i++) { for (i=0; i<mock.cur_names.length; i++) {
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost'; jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
view = this.rosterview.get(jid); this.roster.get(jid).set('chat_status', 'unavailable');
spyOn(view, 'render').andCallThrough(); expect(this.rosterview.update).toHaveBeenCalled();
item = view.model;
item.set('chat_status', 'unavailable');
expect(view.render).toHaveBeenCalled();
expect(this.rosterview.render).toHaveBeenCalled();
expect(converse.emit).toHaveBeenCalledWith('rosterViewUpdated');
// Check that they are sorted alphabetically // Check that they are sorted alphabetically
t = this.rosterview.$el.find('dt#xmpp-contacts').siblings('dd.current-xmpp-contact.unavailable').find('a.open-chat').text(); 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('')); expect(t).toEqual(mock.cur_names.slice(0, i+1).sort().join(''));
} }
}, converse)); }, converse));
it("are ordered according to status: online, busy, away, xa, unavailable, offline", $.proxy(function () { it("are ordered according to status: online, busy, away, xa, unavailable, offline", $.proxy(function () {
_addContacts();
var i; var i;
for (i=0; i<3; i++) { for (i=0; i<3; i++) {
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost'; jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
view = this.rosterview.get(jid); this.roster.get(jid).set('chat_status', 'online');
view.model.set('chat_status', 'online');
} }
for (i=3; i<6; i++) { for (i=3; i<6; i++) {
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost'; jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
view = this.rosterview.get(jid); this.roster.get(jid).set('chat_status', 'dnd');
view.model.set('chat_status', 'dnd');
} }
for (i=6; i<9; i++) { for (i=6; i<9; i++) {
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost'; jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
view = this.rosterview.get(jid); this.roster.get(jid).set('chat_status', 'away');
view.model.set('chat_status', 'away');
} }
for (i=9; i<12; i++) { for (i=9; i<12; i++) {
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost'; jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
view = this.rosterview.get(jid); this.roster.get(jid).set('chat_status', 'xa');
view.model.set('chat_status', 'xa');
} }
for (i=12; i<15; i++) { for (i=12; i<15; i++) {
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost'; jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
view = this.rosterview.get(jid); this.roster.get(jid).set('chat_status', 'unavailable');
view.model.set('chat_status', 'unavailable');
} }
var contacts = this.rosterview.$el.find('dd.current-xmpp-contact'); var contacts = this.rosterview.$el.find('dd.current-xmpp-contact');
...@@ -392,6 +561,7 @@ ...@@ -392,6 +561,7 @@
describe("Requesting Contacts", $.proxy(function () { describe("Requesting Contacts", $.proxy(function () {
beforeEach($.proxy(function () { beforeEach($.proxy(function () {
runs(function () { runs(function () {
utils.clearBrowserStorage();
converse.rosterview.model.reset(); converse.rosterview.model.reset();
utils.createContacts('requesting').openControlBox(); utils.createContacts('requesting').openControlBox();
}); });
...@@ -401,81 +571,89 @@ ...@@ -401,81 +571,89 @@
}); });
}, converse)); }, converse));
it("do not have a heading if there aren't any", $.proxy(function () {
// by default the dts are hidden from css class and only later they will be hidden
// by jQuery therefore for the first check we will see if visible instead of none
converse.rosterview.model.reset();
expect(this.rosterview.$el.find('dt#xmpp-contact-requests').is(':visible')).toEqual(false);
}, converse));
it("can be added to the roster and they will be sorted alphabetically", $.proxy(function () { it("can be added to the roster and they will be sorted alphabetically", $.proxy(function () {
converse.rosterview.model.reset(); // We want to manually create users so that we can spy converse.rosterview.model.reset(); // We want to manually create users so that we can spy
var i, children; var i, children;
var names = []; var names = [];
spyOn(converse, 'emit'); spyOn(converse, 'emit');
spyOn(this.rosterview, 'render').andCallThrough(); spyOn(this.rosterview, 'update').andCallThrough();
spyOn(this.controlboxtoggle, 'showControlBox').andCallThrough(); spyOn(this.controlboxtoggle, 'showControlBox').andCallThrough();
var addName = function (idx, item) {
if (!$(item).hasClass('request-actions')) {
names.push($(item).text().replace(/^\s+|\s+$/g, ''));
}
};
for (i=0; i<mock.req_names.length; i++) { for (i=0; i<mock.req_names.length; i++) {
this.roster.create({ this.roster.create({
jid: mock.req_names[i].replace(/ /g,'.').toLowerCase() + '@localhost', jid: mock.req_names[i].replace(/ /g,'.').toLowerCase() + '@localhost',
subscription: 'none', subscription: 'none',
ask: null, ask: null,
requesting: true, requesting: true,
fullname: mock.req_names[i], fullname: mock.req_names[i]
is_last: i===(mock.req_names.length-1)
}); });
expect(this.rosterview.render).toHaveBeenCalled(); expect(this.rosterview.update).toHaveBeenCalled();
// Check that they are sorted alphabetically
children = this.rosterview.$el.find('dt#xmpp-contact-requests').siblings('dd.requesting-xmpp-contact').children('span');
names = [];
children.each(function (idx, item) {
if (!$(item).hasClass('request-actions')) {
names.push($(item).text().replace(/^\s+|\s+$/g, ''));
}
});
expect(names.join('')).toEqual(mock.req_names.slice(0,i+1).sort().join(''));
// When a requesting contact is added, the controlbox must // When a requesting contact is added, the controlbox must
// be opened. // be opened.
expect(this.controlboxtoggle.showControlBox).toHaveBeenCalled(); expect(this.controlboxtoggle.showControlBox).toHaveBeenCalled();
expect(converse.emit).toHaveBeenCalledWith('rosterViewUpdated');
} }
// Check that they are sorted alphabetically
children = this.rosterview.get('Contact requests').$el.siblings('dd.requesting-xmpp-contact').children('span');
names = [];
children.each(addName);
expect(names.join('')).toEqual(mock.req_names.slice(0,i+1).sort().join(''));
}, converse));
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];
spyOn(window, 'confirm').andReturn(true);
this.roster.create({
jid: name.replace(/ /g,'.').toLowerCase() + '@localhost',
subscription: 'none',
ask: null,
requesting: true,
fullname: name
});
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);
}, converse)); }, converse));
it("will have their own heading once they have been added", $.proxy(function () { it("can be collapsed under their own header", $.proxy(function () {
expect(this.rosterview.$el.find('dt#xmpp-contact-requests').css('display')).toEqual('block'); checkHeaderToggling.apply(this, [this.rosterview.get('Contact requests').$el]);
}, converse)); }, converse));
it("can have their requests accepted by the user", $.proxy(function () { it("can have their requests accepted by the user", $.proxy(function () {
// TODO: Testing can be more thorough here, the user is // TODO: Testing can be more thorough here, the user is
// actually not accepted/authorized because of // actually not accepted/authorized because of
// mock_connection. // mock_connection.
var jid = mock.req_names.sort()[0].replace(/ /g,'.').toLowerCase() + '@localhost'; var name = mock.req_names.sort()[0];
var view = this.rosterview.get(jid); var jid = name.replace(/ /g,'.').toLowerCase() + '@localhost';
spyOn(this.connection.roster, 'authorize'); spyOn(this.connection.roster, 'authorize');
spyOn(view, 'acceptRequest').andCallThrough();
view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called converse.rosterview.$el.find(".req-contact-name:contains('"+name+"')")
var accept_button = view.$el.find('.accept-xmpp-request'); .siblings('.request-actions')
accept_button.click(); .find('.accept-xmpp-request').click();
expect(view.acceptRequest).toHaveBeenCalled();
expect(this.connection.roster.authorize).toHaveBeenCalled(); expect(this.connection.roster.authorize).toHaveBeenCalled();
}, converse)); }, converse));
it("can have their requests denied by the user", $.proxy(function () { it("can have their requests denied by the user", $.proxy(function () {
var jid = mock.req_names.sort()[1].replace(/ /g,'.').toLowerCase() + '@localhost'; this.rosterview.model.reset();
var view = this.rosterview.get(jid);
spyOn(converse, 'emit'); spyOn(converse, 'emit');
spyOn(this.connection.roster, 'unauthorize'); spyOn(this.connection.roster, 'unauthorize');
spyOn(this.rosterview, 'removeRosterItemView').andCallThrough();
spyOn(window, 'confirm').andReturn(true); spyOn(window, 'confirm').andReturn(true);
spyOn(view, 'declineRequest').andCallThrough(); utils.createContacts('requesting').openControlBox();
view.delegateEvents(); // We need to rebind all events otherwise our spy won't be called var name = mock.req_names.sort()[1];
var accept_button = view.$el.find('.decline-xmpp-request'); var jid = name.replace(/ /g,'.').toLowerCase() + '@localhost';
accept_button.click(); converse.rosterview.$el.find(".req-contact-name:contains('"+name+"')")
expect(view.declineRequest).toHaveBeenCalled(); .siblings('.request-actions')
.find('.decline-xmpp-request').click();
expect(window.confirm).toHaveBeenCalled(); expect(window.confirm).toHaveBeenCalled();
expect(this.rosterview.removeRosterItemView).toHaveBeenCalled();
expect(this.connection.roster.unauthorize).toHaveBeenCalled(); expect(this.connection.roster.unauthorize).toHaveBeenCalled();
expect(converse.emit).toHaveBeenCalledWith('rosterViewUpdated');
// There should now be one less contact // There should now be one less contact
expect(this.roster.length).toEqual(mock.req_names.length-1); expect(this.roster.length).toEqual(mock.req_names.length-1);
}, converse)); }, converse));
...@@ -483,28 +661,19 @@ ...@@ -483,28 +661,19 @@
describe("All Contacts", $.proxy(function () { describe("All Contacts", $.proxy(function () {
beforeEach($.proxy(function () { beforeEach($.proxy(function () {
runs(function () { utils.clearBrowserStorage();
utils.clearBrowserStorage(); converse.rosterview.model.reset();
converse.rosterview.model.reset(); utils.createContacts('all').openControlBox();
converse.rosterview.model.browserStorage._clear(); utils.openContactsPanel();
utils.createContacts('all').openControlBox();
});
waits(50);
runs(function () {
utils.openContactsPanel();
});
}, converse)); }, converse));
it("are saved to, and can be retrieved from, browserStorage", $.proxy(function () { 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, old_roster;
var num_contacts = this.roster.length; var num_contacts = this.roster.length;
new_roster = new this.RosterItems(); new_roster = new this.RosterContacts();
// Roster items are yet to be fetched from browserStorage // Roster items are yet to be fetched from browserStorage
expect(new_roster.length).toEqual(0); expect(new_roster.length).toEqual(0);
new_roster.browserStorage = this.roster.browserStorage;
new_roster.browserStorage = new Backbone.BrowserStorage.session(
b64_sha1('converse.rosteritems-dummy@localhost'));
new_roster.fetch(); new_roster.fetch();
expect(new_roster.length).toEqual(num_contacts); expect(new_roster.length).toEqual(num_contacts);
// Check that the roster items retrieved from browserStorage // Check that the roster items retrieved from browserStorage
...@@ -518,7 +687,6 @@ ...@@ -518,7 +687,6 @@
// comparison // comparison
expect(_.isEqual(new_attrs.sort(), old_attrs.sort())).toEqual(true); expect(_.isEqual(new_attrs.sort(), old_attrs.sort())).toEqual(true);
} }
this.rosterview.render();
}, converse)); }, converse));
afterEach($.proxy(function () { afterEach($.proxy(function () {
...@@ -528,8 +696,7 @@ ...@@ -528,8 +696,7 @@
// we make some online now // we make some online now
for (i=0; i<5; i++) { for (i=0; i<5; i++) {
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost'; jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
view = this.rosterview.get(jid); this.roster.get(jid).set('chat_status', 'online');
view.model.set('chat_status', 'online');
} }
}, converse)); }, converse));
}, converse)); }, converse));
......
...@@ -10,7 +10,6 @@ define("converse-templates", [ ...@@ -10,7 +10,6 @@ define("converse-templates", [
"tpl!src/templates/chatrooms_tab", "tpl!src/templates/chatrooms_tab",
"tpl!src/templates/chats_panel", "tpl!src/templates/chats_panel",
"tpl!src/templates/choose_status", "tpl!src/templates/choose_status",
"tpl!src/templates/contacts",
"tpl!src/templates/contacts_panel", "tpl!src/templates/contacts_panel",
"tpl!src/templates/contacts_tab", "tpl!src/templates/contacts_tab",
"tpl!src/templates/controlbox", "tpl!src/templates/controlbox",
...@@ -19,6 +18,7 @@ define("converse-templates", [ ...@@ -19,6 +18,7 @@ define("converse-templates", [
"tpl!src/templates/form_checkbox", "tpl!src/templates/form_checkbox",
"tpl!src/templates/form_input", "tpl!src/templates/form_input",
"tpl!src/templates/form_select", "tpl!src/templates/form_select",
"tpl!src/templates/group_header",
"tpl!src/templates/info", "tpl!src/templates/info",
"tpl!src/templates/login_panel", "tpl!src/templates/login_panel",
"tpl!src/templates/login_tab", "tpl!src/templates/login_tab",
...@@ -35,9 +35,9 @@ define("converse-templates", [ ...@@ -35,9 +35,9 @@ define("converse-templates", [
"tpl!src/templates/roster_item", "tpl!src/templates/roster_item",
"tpl!src/templates/select_option", "tpl!src/templates/select_option",
"tpl!src/templates/status_option", "tpl!src/templates/status_option",
"tpl!src/templates/toggle_chats",
"tpl!src/templates/toolbar", "tpl!src/templates/toolbar",
"tpl!src/templates/trimmed_chat", "tpl!src/templates/trimmed_chat"
"tpl!src/templates/toggle_chats"
], function () { ], function () {
return { return {
action: arguments[0], action: arguments[0],
...@@ -51,15 +51,15 @@ define("converse-templates", [ ...@@ -51,15 +51,15 @@ define("converse-templates", [
chatrooms_tab: arguments[8], chatrooms_tab: arguments[8],
chats_panel: arguments[9], chats_panel: arguments[9],
choose_status: arguments[10], choose_status: arguments[10],
contacts: arguments[11], contacts_panel: arguments[11],
contacts_panel: arguments[12], contacts_tab: arguments[12],
contacts_tab: arguments[13], controlbox: arguments[13],
controlbox: arguments[14], controlbox_toggle: arguments[14],
controlbox_toggle: arguments[15], field: arguments[15],
field: arguments[16], form_checkbox: arguments[16],
form_checkbox: arguments[17], form_input: arguments[17],
form_input: arguments[18], form_select: arguments[18],
form_select: arguments[19], group_header: arguments[19],
info: arguments[20], info: arguments[20],
login_panel: arguments[21], login_panel: arguments[21],
login_tab: arguments[22], login_tab: arguments[22],
...@@ -76,8 +76,8 @@ define("converse-templates", [ ...@@ -76,8 +76,8 @@ define("converse-templates", [
roster_item: arguments[33], roster_item: arguments[33],
select_option: arguments[34], select_option: arguments[34],
status_option: arguments[35], status_option: arguments[35],
toolbar: arguments[36], toggle_chats: arguments[36],
trimmed_chat: arguments[37], toolbar: arguments[37],
toggle_chats: arguments[38] trimmed_chat: arguments[38]
}; };
}); });
<dt id="xmpp-contacts">{{label_contacts}}</dt>
<a href="#" class="group-toggle icon-{{toggle_state}}" title="{{desc_group_toggle}}">{{label_group}}</a>
<span>{{fullname}}</span> <a class="remove-xmpp-contact icon-remove" title="{{desc_remove}}" href="#"></a> <span class="pending-contact-name">{{fullname}}</span> <a class="remove-xmpp-contact icon-remove" title="{{desc_remove}}" href="#"></a>
<dt id="pending-xmpp-contacts">{{label_pending_contacts}}</dt> <dt id="pending-xmpp-contacts"><a href="#" class="group-toggle icon-{{toggle_state}}" title="{{desc_group_toggle}}">{{label_pending_contacts}}</a></dt>
<span>{{fullname}}</span> <span class="req-contact-name">{{fullname}}</span>
<span class="request-actions"> <span class="request-actions">
<a class="accept-xmpp-request icon-checkmark" title="{{desc_accept}}" href="#"></a> <a class="accept-xmpp-request icon-checkmark" title="{{desc_accept}}" href="#"></a>
<a class="decline-xmpp-request icon-close" title="{{desc_decline}}" href="#"></a> <a class="decline-xmpp-request icon-close" title="{{desc_decline}}" href="#"></a>
......
<dt id="xmpp-contact-requests">{{label_contact_requests}}</dt> <dt id="xmpp-contact-requests"><a href="#" class="group-toggle icon-{{toggle_state}}" title="{{desc_group_toggle}}">{{label_contact_requests}}</a></dt>
...@@ -80,13 +80,21 @@ ...@@ -80,13 +80,21 @@
var i = 0, jid, views = []; var i = 0, jid, views = [];
for (i; i<amount; i++) { for (i; i<amount; i++) {
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost'; jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@localhost';
views[i] = converse.rosterview.get(jid).openChat(mock.event); views[i] = converse.roster.get(jid).trigger("open");
} }
return views; return views;
}; };
utils.openChatBoxFor = function (jid) { utils.openChatBoxFor = function (jid) {
return converse.rosterview.get(jid).openChat(mock.event); return converse.roster.get(jid).trigger("open");
};
utils.removeRosterContacts = function () {
var model;
while (converse.rosterview.model.length) {
model = converse.rosterview.model.pop();
converse.rosterview.model.remove(model);
}
}; };
utils.clearBrowserStorage = function () { utils.clearBrowserStorage = function () {
...@@ -129,7 +137,6 @@ ...@@ -129,7 +137,6 @@
converse.roster.create({ converse.roster.create({
ask: ask, ask: ask,
fullname: names[i], fullname: names[i],
is_last: i===(names.length-1),
jid: names[i].replace(/ /g,'.').toLowerCase() + '@localhost', jid: names[i].replace(/ /g,'.').toLowerCase() + '@localhost',
requesting: requesting, requesting: requesting,
subscription: subscription subscription: subscription
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment