diff --git a/bower.json b/bower.json
index f58991d20..09d0394b3 100644
--- a/bower.json
+++ b/bower.json
@@ -3,7 +3,9 @@
"version": "0.7.2",
"devDependencies": {
"jasmine": "https://github.com/jcbrand/jasmine.git#1_3_x",
- "otr": "0.2.7"
+ "otr": "0.2.7",
+ "requirejs-text": "~2.0.10",
+ "requirejs-tpl-jfparadis": "*"
},
"dependencies": {
"requirejs": "2.1.8",
@@ -20,7 +22,9 @@
"strophe.muc": "https://raw.github.com/strophe/strophejs-plugins/02310ad1b8da2962cd05b0f4bceaecca134efed4/muc/strophe.muc.js",
"otr": "0.2.7",
"crypto-js": "~3.1.2",
- "almond": "~0.2.6"
+ "almond": "~0.2.6",
+ "requirejs-text": "~2.0.10",
+ "requirejs-tpl-jfparadis": "*"
},
"exportsOverride": {}
}
diff --git a/converse.js b/converse.js
index 3a87d609c..6eb38ed6e 100644
--- a/converse.js
+++ b/converse.js
@@ -12,27 +12,26 @@
console = { log: function () {}, error: function () {} };
}
if (typeof define === 'function' && define.amd) {
- define("converse", ["converse-dependencies"], function(otr) {
- // Use Mustache style syntax for variable interpolation
- _.templateSettings = {
- evaluate : /\{\[([\s\S]+?)\]\}/g,
- interpolate : /\{\{([\s\S]+?)\}\}/g
- };
- if (typeof otr !== "undefined") {
- return factory(jQuery, _, otr.OTR, otr.DSA, console);
- } else {
- return factory(jQuery, _, undefined, undefined, console);
+ define("converse",
+ ["converse-dependencies", "converse-templates"],
+ function(otr, templates) {
+ if (typeof otr !== "undefined") {
+ return factory(jQuery, _, otr.OTR, otr.DSA, console, templates);
+ } else {
+ return factory(jQuery, _, undefined, undefined, console, templates);
+ }
}
- });
+ );
} else {
// Browser globals
+ // FIXME
_.templateSettings = {
evaluate : /\{\[([\s\S]+?)\]\}/g,
interpolate : /\{\{([\s\S]+?)\}\}/g
};
root.converse = factory(jQuery, _, OTR, DSA, console || {log: function(){}});
}
-}(this, function ($, _, OTR, DSA, console) {
+}(this, function ($, _, OTR, DSA, console, templates) {
$.fn.addHyperlinks = function() {
if (this.length > 0) {
this.each(function(i, obj) {
@@ -86,6 +85,7 @@
};
var converse = {
+ templates: templates,
emit: function(evt, data) {
$(this).trigger(evt, data);
},
@@ -731,99 +731,6 @@
'click .toggle-call': 'toggleCall'
},
- template: _.template(
- '
' +
- '' +
- ''
- ),
-
-
- toolbar_template: _.template(
- '{[ if (show_emoticons) { ]}' +
- '' +
- '' +
- ' '+
- ' '+
- ' '+
- ' '+
- ' '+
- ' '+
- ' '+
- ' '+
- ' '+
- ' '+
- ' '+
- ' '+
- ' '+
- '
' +
- '' +
- '{[ } ]}' +
- '{[ if (' + converse.show_call_button + ') { ]}' +
- '' +
- '{[ } ]}' +
- '{[ if (allow_otr) { ]}' +
- ''+
- '{{otr_translated_status}}'+
- '{[ if (otr_status == "'+UNENCRYPTED+'") { ]}' +
- ''+
- '{[ } ]}' +
- '{[ if (otr_status == "'+UNVERIFIED+'") { ]}' +
- ''+
- '{[ } ]}' +
- '{[ if (otr_status == "'+VERIFIED+'") { ]}' +
- ''+
- '{[ } ]}' +
- '{[ if (otr_status == "'+FINISHED+'") { ]}' +
- ''+
- '{[ } ]}' +
- ''+
- ''+
- '{[ } ]}'
- ),
-
- message_template: _.template(
- ''),
-
- action_template: _.template(
- ''),
-
- new_day_template: _.template(
- ''
- ),
-
initialize: function (){
this.model.messages.on('add', this.onMessageAdded, this);
this.model.on('show', this.show, this);
@@ -849,7 +756,17 @@
render: function () {
this.$el.attr('id', this.model.get('box_id'))
- .html(this.template(this.model.toJSON()));
+ .html(
+ converse.templates.chatbox(
+ _.extend(
+ this.model.toJSON(),
+ {
+ show_toolbar: converse.show_toolbar,
+ label_personal_message: __('Personal message')
+ }
+ )
+ )
+ );
this.renderToolbar().renderAvatar();
return this;
},
@@ -861,35 +778,6 @@
this.scrollDown();
},
- renderEmoticons: function (text) {
- if (converse.show_emoticons) {
- text = text.replace(/:\)/g, '');
- text = text.replace(/:\-\)/g, '');
- text = text.replace(/;\)/g, '');
- text = text.replace(/;\-\)/g, '');
- text = text.replace(/:D/g, '');
- text = text.replace(/:\-D/g, '');
- text = text.replace(/:P/g, '');
- text = text.replace(/:\-P/g, '');
- text = text.replace(/:p/g, '');
- text = text.replace(/:\-p/g, '');
- text = text.replace(/8\)/g, '');
- text = text.replace(/>:\)/g, '');
- text = text.replace(/:S/g, '');
- text = text.replace(/:\\/g, '');
- text = text.replace(/:\//g, '');
- text = text.replace(/>:\(/g, '');
- text = text.replace(/:\(/g, '');
- text = text.replace(/:\-\(/g, '');
- text = text.replace(/:O/g, '');
- text = text.replace(/:\-O/g, '');
- text = text.replace(/\=\-O/g, '');
- text = text.replace(/\(\^.\^\)b/g, '');
- text = text.replace(/<3/g, '');
- }
- return text;
- },
-
showMessage: function ($el, msg_dict) {
var this_date = converse.parseISO8601(msg_dict.time),
text = msg_dict.message,
@@ -899,10 +787,10 @@
if ((match) && (match[1] === 'me')) {
text = text.replace(/^\/me/, '');
- template = this.action_template;
+ template = converse.templates.action_template;
username = msg_dict.fullname;
} else {
- template = this.message_template;
+ template = converse.templates.message;
username = sender === 'me' && __('me') || msg_dict.fullname;
}
$el.find('div.chat-event').remove();
@@ -925,7 +813,7 @@
var $el = this.$el.find('.chat-content');
$el.find('div.chat-event').remove();
$el.append(
- this.message_template({
+ converse.templates.message({
'sender': sender,
'time': (new Date()).toTimeString().substring(0,5),
'message': text,
@@ -961,7 +849,7 @@
isodate.setUTCHours(0,0,0,0);
isodate = converse.toISOString(isodate);
if (this.isDifferentDay(prev_date, this_date)) {
- $chat_content.append(this.new_day_template({
+ $chat_content.append(converse.templates.new_day({
isodate: isodate,
datestring: this_date.toString().substring(0,15)
}));
@@ -1268,11 +1156,27 @@
} else if (data.otr_status == FINISHED){
data.otr_tooltip = __('Your buddy has closed their end of the private session, you should do the same');
}
- data.allow_otr = converse.allow_otr && !this.is_chatroom;
- data.show_emoticons = converse.show_emoticons;
- data.otr_translated_status = OTR_TRANSLATED_MAPPING[data.otr_status];
- data.otr_status_class = OTR_CLASS_MAPPING[data.otr_status];
- this.$el.find('.chat-toolbar').html(this.toolbar_template(data));
+ this.$el.find('.chat-toolbar').html(
+ converse.templates.toolbar(
+ _.extend(data, {
+ FINISHED: FINISHED,
+ UNENCRYPTED: UNENCRYPTED,
+ UNVERIFIED: UNVERIFIED,
+ VERIFIED: VERIFIED,
+ allow_otr: converse.allow_otr && !this.is_chatroom,
+ label_end_encrypted_conversation: __('End encrypted conversation'),
+ label_refresh_encrypted_conversation: __('Refresh encrypted conversation'),
+ label_start_encrypted_conversation: __('Start encrypted conversation'),
+ label_verify_with_fingerprints: __('Verify with fingerprints'),
+ label_verify_with_smp: __('Verify with SMP'),
+ label_whats_this: __("What\'s this?"),
+ otr_status_class: OTR_CLASS_MAPPING[data.otr_status],
+ otr_translated_status: OTR_TRANSLATED_MAPPING[data.otr_status],
+ show_call_button: converse.show_call_button,
+ show_emoticons: converse.show_emoticons
+ })
+ )
+ );
}
return this;
},
@@ -1351,49 +1255,6 @@
'click a.subscribe-to-user': 'addContactFromList'
},
- tab_template: _.template(''+__('Contacts')+''),
- template: _.template(
- ''
- ),
-
- add_contact_dropdown_template: _.template(
- '' +
- '- ' +
- ''+
- ''+__('Add a contact')+'' +
- '
' +
- '' +
- '
'
- ),
-
- add_contact_form_template: _.template(
- ''+
- ''+
- ''
- ),
-
- search_contact_template: _.template(
- ''+
- ''+
- ''
- ),
-
initialize: function (cfg) {
cfg.$parent.append(this.$el);
this.$tabs = cfg.$parent.parent().find('#controlbox-tabs');
@@ -1401,17 +1262,30 @@
render: function () {
var markup;
- var widgets = this.template();
-
- this.$tabs.append(this.tab_template());
+ var widgets = converse.templates.contacts_panel({
+ label_online: __('Online'),
+ label_busy: __('Busy'),
+ label_away: __('Away'),
+ label_offline: __('Offline')
+ });
+ this.$tabs.append(converse.templates.contacts_tab({label_contacts: __('Contacts')}));
if (converse.xhr_user_search) {
- markup = this.search_contact_template();
+ markup = converse.templates.search_contact({
+ label_contact_name: __('Contact name'),
+ label_search: __('Search')
+ });
} else {
- markup = this.add_contact_form_template();
- }
+ markup = converse.templates.add_contact_form({
+ label_contact_username: __('Contact username'),
+ label_add: __('Add')
+ });
+ }
if (converse.allow_contact_requests) {
- widgets += this.add_contact_dropdown_template();
+ widgets += converse.templates.add_contact_dropdown({
+ label_click_to_chat: __('Click to add new chat contacts'),
+ label_add_contact: __('Add a contact')
+ });
}
this.$el.html(widgets);
@@ -1492,74 +1366,17 @@
'click a.open-room': 'createChatRoom',
'click a.room-info': 'showRoomInfo'
},
- room_template: _.template(
- ''+
- '{{name}}'+
- ' '+
- ''),
-
- // FIXME: check markup in mockup
- room_description_template: _.template(
- ''+
- '
'+__('Description:')+' {{desc}}
' +
- '
'+__('Occupants:')+' {{occ}}
' +
- '
'+__('Features:')+'
'+
- '{[ if (passwordprotected) { ]}' +
- '- '+__('Requires authentication')+'
' +
- '{[ } ]}' +
- '{[ if (hidden) { ]}' +
- '- '+__('Hidden')+'
' +
- '{[ } ]}' +
- '{[ if (membersonly) { ]}' +
- '- '+__('Requires an invitation')+'
' +
- '{[ } ]}' +
- '{[ if (moderated) { ]}' +
- '- '+__('Moderated')+'
' +
- '{[ } ]}' +
- '{[ if (nonanonymous) { ]}' +
- '- '+__('Non-anonymous')+'
' +
- '{[ } ]}' +
- '{[ if (open) { ]}' +
- '- '+__('Open room')+'
' +
- '{[ } ]}' +
- '{[ if (persistent) { ]}' +
- '- '+__('Permanent room')+'
' +
- '{[ } ]}' +
- '{[ if (publicroom) { ]}' +
- '- '+__('Public')+'
' +
- '{[ } ]}' +
- '{[ if (semianonymous) { ]}' +
- '- '+__('Semi-anonymous')+'
' +
- '{[ } ]}' +
- '{[ if (temporary) { ]}' +
- '- '+__('Temporary room')+'
' +
- '{[ } ]}' +
- '{[ if (unmoderated) { ]}' +
- '- '+__('Unmoderated')+'
' +
- '{[ } ]}' +
- '' +
- '
'
- ),
-
- tab_template: _.template(''+__('Rooms')+''),
-
- template: _.template(
- ''+
- '
'),
initialize: function (cfg) {
cfg.$parent.append(
this.$el.html(
- this.template({
- server_input_type: converse.hide_muc_server && 'hidden' || 'text'
+ converse.templates.room_panel({
+ 'server_input_type': converse.hide_muc_server && 'hidden' || 'text',
+ 'label_room_name': __('Room name'),
+ 'label_nickname': __('Nickname'),
+ 'label_server': __('Server'),
+ 'label_join': __('Join'),
+ 'label_show_rooms': __('Show rooms')
})
).hide());
this.$tabs = cfg.$parent.parent().find('#controlbox-tabs');
@@ -1579,7 +1396,7 @@
},
render: function () {
- this.$tabs.append(this.tab_template());
+ this.$tabs.append(converse.templates.chatrooms_tab({label_rooms: __('Rooms')}));
return this;
},
@@ -1606,10 +1423,14 @@
for (i=0; i'+
- ''+
- ''+
- ''+
- ''
- ),
-
switchTab: function (ev) {
ev.preventDefault();
var $tab = $(ev.target),
@@ -1801,11 +1628,11 @@
render: function () {
if ((!converse.prebind) && (!converse.connection)) {
// Add login panel if the user still has to authenticate
- this.$el.html(this.template(this.model.toJSON()));
+ this.$el.html(converse.templates.controlbox(this.model.toJSON()));
this.loginpanel = new converse.LoginPanel({'$parent': this.$el.find('.controlbox-panes'), 'model': this});
this.loginpanel.render();
} else if (!this.contactspanel) {
- this.$el.html(this.template(this.model.toJSON()));
+ this.$el.html(converse.templates.controlbox(this.model.toJSON()));
this.contactspanel = new converse.ContactsPanel({'$parent': this.$el.find('.controlbox-panes')});
this.contactspanel.render();
converse.xmppstatusview = new converse.XMPPStatusView({'model': converse.xmppstatus});
@@ -1830,7 +1657,6 @@
'click .toggle-smiley ul li': 'insertEmoticon',
'keypress textarea.chat-textarea': 'keyPressed'
},
- info_template: _.template('{{message}}
'),
is_chatroom: true,
sendChatRoomMessage: function (body) {
@@ -1876,42 +1702,20 @@
}
},
- template: _.template(
- '' +
- '
' +
- '
' +
- '
{{ name }}
' +
- '
' +
- '
' +
- '' +
- '' +
- '
'),
-
- chatarea_template: _.template(
- '' +
- '
' +
- '
' +
- '
' +
- ''
- ),
-
render: function () {
this.$el.attr('id', this.model.get('box_id'))
- .html(this.template(this.model.toJSON()));
+ .html(converse.templates.chatroom(this.model.toJSON()));
return this;
},
renderChatArea: function () {
if (!this.$el.find('.chat-area').length) {
- this.$el.find('.chat-body').empty().append(this.chatarea_template());
+ this.$el.find('.chat-body').empty().append(
+ converse.templates.chatarea({
+ 'show_toolbar': converse.show_toolbar,
+ 'label_message': __('Message')
+ })
+ );
this.renderToolbar();
}
return this;
@@ -1954,11 +1758,6 @@
this.model.set('connected', false);
},
- form_input_template: _.template(''),
- select_option_template: _.template(''),
- form_select_template: _.template(''),
- form_checkbox_template: _.template(''),
-
renderConfigurationForm: function (stanza) {
var $form= this.$el.find('form.chatroom-form'),
$stanza = $(stanza),
@@ -1984,7 +1783,7 @@
options = [];
$options = $field.find('option');
for (j=0; j<$options.length; j++) {
- options.push(this.select_option_template({
+ options.push(converse.templates.select_option({
value: $($options[j]).find('value').text(),
label: $($options[j]).attr('label')
}));
@@ -1995,14 +1794,14 @@
options: options.join('')
}));
} else if ($field.attr('type') == 'boolean') {
- $form.append(this.form_checkbox_template({
+ $form.append(converse.templates.form_checkbox({
name: $field.attr('var'),
type: input_types[$field.attr('type')],
label: $field.attr('label') || '',
checked: $field.find('value').text() === "1" && 'checked="1"' || ''
}));
} else {
- $form.append(this.form_input_template({
+ $form.append(converse.templates.form_input({
name: $field.attr('var'),
type: input_types[$field.attr('type')],
label: $field.attr('label') || '',
@@ -2016,8 +1815,6 @@
$form.find('input[type=button]').on('click', $.proxy(this.cancelConfiguration, this));
},
- field_template: _.template('{{value}}'),
-
saveConfiguration: function (ev) {
ev.preventDefault();
var that = this;
@@ -2031,7 +1828,7 @@
} else {
value = $input.val();
}
- var cnode = $(that.field_template({
+ var cnode = $(converse.templates.field({
name: $input.attr('name'),
value: value
}))[0];
@@ -2193,10 +1990,10 @@
}
this.renderChatArea();
for (i=0; i{{nick}}'
- ),
-
onChatRoomRoster: function (roster, room) {
this.renderChatArea();
var controlboxview = converse.chatboxesview.views.controlbox,
@@ -2347,9 +2130,12 @@
this.$el.find('.participant-list').empty();
for (i=0; i'+
- '{{ fullname }}'+
- '' +
- ''),
-
- pending_template: _.template(
- '{{ fullname }}' +
- ''),
-
- request_template: _.template('{{ fullname }}
' +
- '' +
- '' +
- ''),
-
render: function () {
var item = this.model,
ask = item.get('ask'),
@@ -2598,15 +2367,28 @@
if (ask === 'subscribe') {
this.$el.addClass('pending-xmpp-contact');
- this.$el.html(this.pending_template(item.toJSON()));
+ this.$el.html(converse.templates.pending_contact(
+ _.extend(item.toJSON(), {
+ 'desc_remove': __('Click to remove this contact')
+ })
+ ));
} else if (requesting === true) {
this.$el.addClass('requesting-xmpp-contact');
- this.$el.html(this.request_template(item.toJSON()));
+ this.$el.html(converse.templates.requesting_contact(
+ _.extend(item.toJSON(), {
+ 'label_accept': __('Accept'),
+ 'label_decline': __('Decline')
+ })
+ ));
converse.controlboxtoggle.showControlBox();
} else if (subscription === 'both' || subscription === 'to') {
this.$el.addClass('current-xmpp-contact');
- this.$el.html(this.template(
- _.extend(item.toJSON(), {'status_desc': STATUSES[item.get('chat_status')||'offline']})
+ this.$el.html(converse.templates.roster_item(
+ _.extend(item.toJSON(), {
+ 'desc_status': STATUSES[item.get('chat_status')||'offline'],
+ 'desc_chat': __('Click to chat with this contact'),
+ 'desc_remove': __('Click to remove this contact')
+ })
));
}
return this;
@@ -2915,15 +2697,6 @@
id: 'converse-roster',
rosteritemviews: {},
- requesting_contacts_template: _.template(
- ''+__('Contact requests')+''),
-
- contacts_template: _.template(
- ''+__('My contacts')+''),
-
- pending_contacts_template: _.template(
- ''+__('Pending contacts')+''),
-
initialize: function () {
this.model.on("add", function (item) {
this.addRosterItemView(item).render(item);
@@ -2944,9 +2717,18 @@
this.model.on("remove", function (item) { this.removeRosterItemView(item); }, this);
this.model.on("destroy", function (item) { this.removeRosterItemView(item); }, this);
- var roster_markup = this.contacts_template();
+ var roster_markup = converse.templates.contacts({
+ 'label_contacts': __('My contacts')
+ });
if (converse.allow_contact_requests) {
- roster_markup = this.requesting_contacts_template() + roster_markup + this.pending_contacts_template();
+ roster_markup =
+ converse.templates.requesting_contacts({
+ 'label_contact_requests': __('Contact requests')
+ }) +
+ roster_markup +
+ converse.templates.pending_contacts({
+ 'label_pending_contacts': __('Pending contacts')
+ });
}
this.$el.hide().html(roster_markup);
@@ -3161,26 +2943,14 @@
$(ev.target).parent().parent().siblings('dd').find('ul').toggle('fast');
},
- change_status_message_template: _.template(
- ''),
-
- status_template: _.template(
- ''),
-
renderStatusChangeForm: function (ev) {
ev.preventDefault();
var status_message = this.model.get('status') || 'offline';
- var input = this.change_status_message_template({'status_message': status_message});
+ var input = converse.templates.change_status_message({
+ 'status_message': status_message,
+ 'label_custom_status': __('Custom status'),
+ 'label_save': __('Save')
+ });
this.$el.find('.xmpp-status').replaceWith(input);
this.$el.find('.custom-xmpp-status').focus().focus();
},
@@ -3225,26 +2995,14 @@
// # Example, I am online
var status_message = model.get('status_message') || __("I am %1$s", this.getPrettyStatus(stat));
this.$el.find('#fancy-xmpp-status-select').html(
- this.status_template({
+ converse.templates.chat_status({
'chat_status': stat,
- 'status_message': status_message
+ 'status_message': status_message,
+ 'desc_custom_status': __('Click here to write a custom status message'),
+ 'desc_change_status': __('Click to change your chat status')
}));
},
- choose_template: _.template(
- '' +
- '' +
- '' +
- '
'),
-
- option_template: _.template(
- '' +
- ''+
- ''+
- '{{ text }}'+
- '' +
- ''),
-
initialize: function () {
this.model.on("change", this.updateStatusUI, this);
},
@@ -3257,17 +3015,20 @@
$options_target,
options_list = [],
that = this;
- this.$el.html(this.choose_template());
+ this.$el.html(converse.templates.choose_status());
this.$el.find('#fancy-xmpp-status-select')
- .html(this.status_template({
+ .html(converse.templates.chat_status({
'status_message': this.model.get('status_message') || __("I am %1$s", this.getPrettyStatus(chat_status)),
- 'chat_status': chat_status
+ 'chat_status': chat_status,
+ 'desc_custom_status': __('Click here to write a custom status message'),
+ 'desc_change_status': __('Click to change your chat status')
}));
// iterate through all the