Initial support for external HTMl templates. Updates #77

This commit is contained in:
JC Brand 2013-12-30 21:27:57 +02:00
parent f97217cfd7
commit 55b9a4e568
20 changed files with 275 additions and 296 deletions

View File

@ -4,7 +4,8 @@
"devDependencies": { "devDependencies": {
"jasmine": "https://github.com/jcbrand/jasmine.git#1_3_x", "jasmine": "https://github.com/jcbrand/jasmine.git#1_3_x",
"otr": "0.2.7", "otr": "0.2.7",
"requirejs-text": "~2.0.10" "requirejs-text": "~2.0.10",
"requirejs-tpl-jfparadis": "*"
}, },
"dependencies": { "dependencies": {
"requirejs": "2.1.8", "requirejs": "2.1.8",
@ -22,7 +23,8 @@
"otr": "0.2.7", "otr": "0.2.7",
"crypto-js": "~3.1.2", "crypto-js": "~3.1.2",
"almond": "~0.2.6", "almond": "~0.2.6",
"requirejs-text": "~2.0.10" "requirejs-text": "~2.0.10",
"requirejs-tpl-jfparadis": "*"
}, },
"exportsOverride": {} "exportsOverride": {}
} }

View File

@ -12,27 +12,26 @@
console = { log: function () {}, error: function () {} }; console = { log: function () {}, error: function () {} };
} }
if (typeof define === 'function' && define.amd) { if (typeof define === 'function' && define.amd) {
define("converse", ["converse-dependencies"], function(otr) { define("converse",
// Use Mustache style syntax for variable interpolation ["converse-dependencies", "converse-templates"],
_.templateSettings = { function(otr, templates) {
evaluate : /\{\[([\s\S]+?)\]\}/g, if (typeof otr !== "undefined") {
interpolate : /\{\{([\s\S]+?)\}\}/g return factory(jQuery, _, otr.OTR, otr.DSA, console, templates);
}; } else {
if (typeof otr !== "undefined") { return factory(jQuery, _, undefined, undefined, console, templates);
return factory(jQuery, _, otr.OTR, otr.DSA, console); }
} else {
return factory(jQuery, _, undefined, undefined, console);
} }
}); );
} else { } else {
// Browser globals // Browser globals
// FIXME
_.templateSettings = { _.templateSettings = {
evaluate : /\{\[([\s\S]+?)\]\}/g, evaluate : /\{\[([\s\S]+?)\]\}/g,
interpolate : /\{\{([\s\S]+?)\}\}/g interpolate : /\{\{([\s\S]+?)\}\}/g
}; };
root.converse = factory(jQuery, _, OTR, DSA, console || {log: function(){}}); root.converse = factory(jQuery, _, OTR, DSA, console || {log: function(){}});
} }
}(this, function ($, _, OTR, DSA, console) { }(this, function ($, _, OTR, DSA, console, templates) {
$.fn.addHyperlinks = function() { $.fn.addHyperlinks = function() {
if (this.length > 0) { if (this.length > 0) {
this.each(function(i, obj) { this.each(function(i, obj) {
@ -86,6 +85,7 @@
}; };
var converse = { var converse = {
templates: templates,
emit: function(evt, data) { emit: function(evt, data) {
$(this).trigger(evt, data); $(this).trigger(evt, data);
}, },
@ -731,99 +731,6 @@
'click .toggle-call': 'toggleCall' 'click .toggle-call': 'toggleCall'
}, },
template: _.template(
'<div class="chat-head chat-head-chatbox">' +
'<a class="close-chatbox-button icon-close"></a>' +
'<a href="{{url}}" target="_blank" class="user">' +
'<div class="chat-title"> {{ fullname }} </div>' +
'</a>' +
'<p class="user-custom-message"><p/>' +
'</div>' +
'<div class="chat-content"></div>' +
'<form class="sendXMPPMessage" action="" method="post">' +
'{[ if ('+converse.show_toolbar+') { ]}' +
'<ul class="chat-toolbar no-text-select"></ul>'+
'{[ } ]}' +
'<textarea ' +
'type="text" ' +
'class="chat-textarea" ' +
'placeholder="'+__('Personal message')+'"/>'+
'</form>'
),
toolbar_template: _.template(
'{[ if (show_emoticons) { ]}' +
'<li class="toggle-smiley icon-happy" title="Insert a smilery">' +
'<ul>' +
'<li><a class="icon-smiley" href="#" data-emoticon=":)"></a></li>'+
'<li><a class="icon-wink" href="#" data-emoticon=";)"></a></li>'+
'<li><a class="icon-grin" href="#" data-emoticon=":D"></a></li>'+
'<li><a class="icon-tongue" href="#" data-emoticon=":P"></a></li>'+
'<li><a class="icon-cool" href="#" data-emoticon="8)"></a></li>'+
'<li><a class="icon-evil" href="#" data-emoticon=">:)"></a></li>'+
'<li><a class="icon-confused" href="#" data-emoticon=":S"></a></li>'+
'<li><a class="icon-wondering" href="#" data-emoticon=":\\"></a></li>'+
'<li><a class="icon-angry" href="#" data-emoticon=">:("></a></li>'+
'<li><a class="icon-sad" href="#" data-emoticon=":("></a></li>'+
'<li><a class="icon-shocked" href="#" data-emoticon=":O"></a></li>'+
'<li><a class="icon-thumbs-up" href="#" data-emoticon="(^.^)b"></a></li>'+
'<li><a class="icon-heart" href="#" data-emoticon="<3"></a></li>'+
'</ul>' +
'</li>' +
'{[ } ]}' +
'{[ if (' + converse.show_call_button + ') { ]}' +
'<li><a class="toggle-call icon-phone" title="Start a call"></a></li>' +
'{[ } ]}' +
'{[ if (allow_otr) { ]}' +
'<li class="toggle-otr {{otr_status_class}}" title="{{otr_tooltip}}">'+
'<span class="chat-toolbar-text">{{otr_translated_status}}</span>'+
'{[ if (otr_status == "'+UNENCRYPTED+'") { ]}' +
'<span class="icon-unlocked"></span>'+
'{[ } ]}' +
'{[ if (otr_status == "'+UNVERIFIED+'") { ]}' +
'<span class="icon-lock"></span>'+
'{[ } ]}' +
'{[ if (otr_status == "'+VERIFIED+'") { ]}' +
'<span class="icon-lock"></span>'+
'{[ } ]}' +
'{[ if (otr_status == "'+FINISHED+'") { ]}' +
'<span class="icon-unlocked"></span>'+
'{[ } ]}' +
'<ul>'+
'{[ if (otr_status == "'+UNENCRYPTED+'") { ]}' +
'<li><a class="start-otr" href="#">'+__('Start encrypted conversation')+'</a></li>'+
'{[ } ]}' +
'{[ if (otr_status != "'+UNENCRYPTED+'") { ]}' +
'<li><a class="start-otr" href="#">'+__('Refresh encrypted conversation')+'</a></li>'+
'<li><a class="end-otr" href="#">'+__('End encrypted conversation')+'</a></li>'+
'<li><a class="auth-otr" data-scheme="smp" href="#">'+__('Verify with SMP')+'</a></li>'+
'{[ } ]}' +
'{[ if (otr_status == "'+UNVERIFIED+'") { ]}' +
'<li><a class="auth-otr" data-scheme="fingerprint" href="#">'+__('Verify with fingerprints')+'</a></li>'+
'{[ } ]}' +
'<li><a href="http://www.cypherpunks.ca/otr/help/3.2.0/levels.php" target="_blank">'+__("What\'s this?")+'</a></li>'+
'</ul>'+
'</li>'+
'{[ } ]}'
),
message_template: _.template(
'<div class="chat-message {{extra_classes}}">' +
'<span class="chat-message-{{sender}}">{{time}} {{username}}:&nbsp;</span>' +
'<span class="chat-message-content">{{message}}</span>' +
'</div>'),
action_template: _.template(
'<div class="chat-message {{extra_classes}}">' +
'<span class="chat-message-{{sender}}">{{time}} **{{username}} </span>' +
'<span class="chat-message-content">{{message}}</span>' +
'</div>'),
new_day_template: _.template(
'<time class="chat-date" datetime="{{isodate}}">{{datestring}}</time>'
),
initialize: function (){ initialize: function (){
this.model.messages.on('add', this.onMessageAdded, this); this.model.messages.on('add', this.onMessageAdded, this);
this.model.on('show', this.show, this); this.model.on('show', this.show, this);
@ -849,7 +756,17 @@
render: function () { render: function () {
this.$el.attr('id', this.model.get('box_id')) 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(); this.renderToolbar().renderAvatar();
return this; return this;
}, },
@ -861,35 +778,6 @@
this.scrollDown(); this.scrollDown();
}, },
renderEmoticons: function (text) {
if (converse.show_emoticons) {
text = text.replace(/:\)/g, '<span class="emoticon icon-smiley"></span>');
text = text.replace(/:\-\)/g, '<span class="emoticon icon-smiley"></span>');
text = text.replace(/;\)/g, '<span class="emoticon icon-wink"></span>');
text = text.replace(/;\-\)/g, '<span class="emoticon icon-wink"></span>');
text = text.replace(/:D/g, '<span class="emoticon icon-grin"></span>');
text = text.replace(/:\-D/g, '<span class="emoticon icon-grin"></span>');
text = text.replace(/:P/g, '<span class="emoticon icon-tongue"></span>');
text = text.replace(/:\-P/g, '<span class="emoticon icon-tongue"></span>');
text = text.replace(/:p/g, '<span class="emoticon icon-tongue"></span>');
text = text.replace(/:\-p/g, '<span class="emoticon icon-tongue"></span>');
text = text.replace(/8\)/g, '<span class="emoticon icon-cool"></span>');
text = text.replace(/>:\)/g, '<span class="emoticon icon-evil"></span>');
text = text.replace(/:S/g, '<span class="emoticon icon-confused"></span>');
text = text.replace(/:\\/g, '<span class="emoticon icon-wondering"></span>');
text = text.replace(/:\//g, '<span class="emoticon icon-wondering"></span>');
text = text.replace(/>:\(/g, '<span class="emoticon icon-angry"></span>');
text = text.replace(/:\(/g, '<span class="emoticon icon-sad"></span>');
text = text.replace(/:\-\(/g, '<span class="emoticon icon-sad"></span>');
text = text.replace(/:O/g, '<span class="emoticon icon-shocked"></span>');
text = text.replace(/:\-O/g, '<span class="emoticon icon-shocked"></span>');
text = text.replace(/\=\-O/g, '<span class="emoticon icon-shocked"></span>');
text = text.replace(/\(\^.\^\)b/g, '<span class="emoticon icon-thumbs-up"></span>');
text = text.replace(/<3/g, '<span class="emoticon icon-heart"></span>');
}
return text;
},
showMessage: function ($el, msg_dict) { showMessage: function ($el, msg_dict) {
var this_date = converse.parseISO8601(msg_dict.time), var this_date = converse.parseISO8601(msg_dict.time),
text = msg_dict.message, text = msg_dict.message,
@ -899,10 +787,10 @@
if ((match) && (match[1] === 'me')) { if ((match) && (match[1] === 'me')) {
text = text.replace(/^\/me/, ''); text = text.replace(/^\/me/, '');
template = this.action_template; template = converse.templates.action_template;
username = msg_dict.fullname; username = msg_dict.fullname;
} else { } else {
template = this.message_template; template = converse.templates.message;
username = sender === 'me' && __('me') || msg_dict.fullname; username = sender === 'me' && __('me') || msg_dict.fullname;
} }
$el.find('div.chat-event').remove(); $el.find('div.chat-event').remove();
@ -925,7 +813,7 @@
var $el = this.$el.find('.chat-content'); var $el = this.$el.find('.chat-content');
$el.find('div.chat-event').remove(); $el.find('div.chat-event').remove();
$el.append( $el.append(
this.message_template({ converse.templates.message({
'sender': sender, 'sender': sender,
'time': (new Date()).toTimeString().substring(0,5), 'time': (new Date()).toTimeString().substring(0,5),
'message': text, 'message': text,
@ -961,7 +849,7 @@
isodate.setUTCHours(0,0,0,0); isodate.setUTCHours(0,0,0,0);
isodate = converse.toISOString(isodate); isodate = converse.toISOString(isodate);
if (this.isDifferentDay(prev_date, this_date)) { if (this.isDifferentDay(prev_date, this_date)) {
$chat_content.append(this.new_day_template({ $chat_content.append(converse.templates.new_day({
isodate: isodate, isodate: isodate,
datestring: this_date.toString().substring(0,15) datestring: this_date.toString().substring(0,15)
})); }));
@ -1268,11 +1156,27 @@
} else if (data.otr_status == FINISHED){ } 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.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; this.$el.find('.chat-toolbar').html(
data.show_emoticons = converse.show_emoticons; converse.templates.toolbar(
data.otr_translated_status = OTR_TRANSLATED_MAPPING[data.otr_status]; _.extend(data, {
data.otr_status_class = OTR_CLASS_MAPPING[data.otr_status]; FINISHED: FINISHED,
this.$el.find('.chat-toolbar').html(this.toolbar_template(data)); 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; return this;
}, },
@ -1351,49 +1255,6 @@
'click a.subscribe-to-user': 'addContactFromList' 'click a.subscribe-to-user': 'addContactFromList'
}, },
tab_template: _.template('<li><a class="s current" href="#users">'+__('Contacts')+'</a></li>'),
template: _.template(
'<form class="set-xmpp-status" action="" method="post">'+
'<span id="xmpp-status-holder">'+
'<select id="select-xmpp-status" style="display:none">'+
'<option value="online">'+__('Online')+'</option>'+
'<option value="dnd">'+__('Busy')+'</option>'+
'<option value="away">'+__('Away')+'</option>'+
'<option value="offline">'+__('Offline')+'</option>'+
'</select>'+
'</span>'+
'</form>'
),
add_contact_dropdown_template: _.template(
'<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></ul></dd>' +
'</dl>'
),
add_contact_form_template: _.template(
'<li>'+
'<form class="add-xmpp-contact">' +
'<input type="text" name="identifier" class="username" placeholder="'+__('Contact username')+'"/>' +
'<button type="submit">'+__('Add')+'</button>' +
'</form>'+
'<li>'
),
search_contact_template: _.template(
'<li>'+
'<form class="search-xmpp-contact">' +
'<input type="text" name="identifier" class="username" placeholder="'+__('Contact name')+'"/>' +
'<button type="submit">'+__('Search')+'</button>' +
'</form>'+
'<li>'
),
initialize: function (cfg) { initialize: function (cfg) {
cfg.$parent.append(this.$el); cfg.$parent.append(this.$el);
this.$tabs = cfg.$parent.parent().find('#controlbox-tabs'); this.$tabs = cfg.$parent.parent().find('#controlbox-tabs');
@ -1401,17 +1262,30 @@
render: function () { render: function () {
var markup; var markup;
var widgets = this.template(); var widgets = converse.templates.contacts_panel({
label_online: __('Online'),
this.$tabs.append(this.tab_template()); label_busy: __('Busy'),
label_away: __('Away'),
label_offline: __('Offline')
});
this.$tabs.append(converse.templates.contacts_tab({label_contacts: __('Contacts')}));
if (converse.xhr_user_search) { if (converse.xhr_user_search) {
markup = this.search_contact_template(); markup = converse.templates.search_contact({
label_contact_name: __('Contact name'),
label_search: __('Search')
});
} else { } 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) { 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); this.$el.html(widgets);
@ -1543,8 +1417,6 @@
'</div>' '</div>'
), ),
tab_template: _.template('<li><a class="s" href="#chatrooms">'+__('Rooms')+'</a></li>'),
template: _.template( template: _.template(
'<form class="add-chatroom" action="" method="post">'+ '<form class="add-chatroom" action="" method="post">'+
'<input type="text" name="chatroom" class="new-chatroom-name" placeholder="'+__('Room name')+'"/>'+ '<input type="text" name="chatroom" class="new-chatroom-name" placeholder="'+__('Room name')+'"/>'+
@ -1579,7 +1451,7 @@
}, },
render: function () { render: function () {
this.$tabs.append(this.tab_template()); this.$tabs.append(converse.templates.chatrooms_tab({label_rooms: __('Rooms')}));
return this; return this;
}, },
@ -1770,14 +1642,6 @@
} }
}, },
template: _.template(
'<div class="chat-head oc-chat-head">'+
'<ul id="controlbox-tabs"></ul>'+
'<a class="close-chatbox-button icon-close"></a>'+
'</div>'+
'<div class="controlbox-panes"></div>'
),
switchTab: function (ev) { switchTab: function (ev) {
ev.preventDefault(); ev.preventDefault();
var $tab = $(ev.target), var $tab = $(ev.target),
@ -1801,11 +1665,11 @@
render: function () { render: function () {
if ((!converse.prebind) && (!converse.connection)) { if ((!converse.prebind) && (!converse.connection)) {
// Add login panel if the user still has to authenticate // 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 = new converse.LoginPanel({'$parent': this.$el.find('.controlbox-panes'), 'model': this});
this.loginpanel.render(); this.loginpanel.render();
} else if (!this.contactspanel) { } 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 = new converse.ContactsPanel({'$parent': this.$el.find('.controlbox-panes')});
this.contactspanel.render(); this.contactspanel.render();
converse.xmppstatusview = new converse.XMPPStatusView({'model': converse.xmppstatus}); converse.xmppstatusview = new converse.XMPPStatusView({'model': converse.xmppstatus});
@ -1830,7 +1694,6 @@
'click .toggle-smiley ul li': 'insertEmoticon', 'click .toggle-smiley ul li': 'insertEmoticon',
'keypress textarea.chat-textarea': 'keyPressed' 'keypress textarea.chat-textarea': 'keyPressed'
}, },
info_template: _.template('<div class="chat-info">{{message}}</div>'),
is_chatroom: true, is_chatroom: true,
sendChatRoomMessage: function (body) { sendChatRoomMessage: function (body) {
@ -2193,10 +2056,10 @@
} }
this.renderChatArea(); this.renderChatArea();
for (i=0; i<info_msgs.length; i++) { for (i=0; i<info_msgs.length; i++) {
$chat_content.append(this.info_template({message: info_msgs[i]})); $chat_content.append(converse.templates.info({message: info_msgs[i]}));
} }
for (i=0; i<action_msgs.length; i++) { for (i=0; i<action_msgs.length; i++) {
$chat_content.append(this.info_template({message: action_msgs[i]})); $chat_content.append(converse.templates.info({message: action_msgs[i]}));
} }
return this.scrollDown(); return this.scrollDown();
}, },
@ -2294,7 +2157,7 @@
message_date.setUTCHours(0,0,0,0); message_date.setUTCHours(0,0,0,0);
isodate = converse.toISOString(message_date); isodate = converse.toISOString(message_date);
if (_.indexOf(dates, isodate) == -1) { if (_.indexOf(dates, isodate) == -1) {
$chat_content.append(this.new_day_template({ $chat_content.append(converse.templates.new_day({
isodate: isodate, isodate: isodate,
datestring: message_date.toString().substring(0,15) datestring: message_date.toString().substring(0,15)
})); }));
@ -2305,7 +2168,7 @@
// # For translators: the %1$s and %2$s parts will get replaced by the user and topic text respectively // # For translators: the %1$s and %2$s parts will get replaced by the user and topic text respectively
// # Example: Topic set by JC Brand to: Hello World! // # Example: Topic set by JC Brand to: Hello World!
$chat_content.append( $chat_content.append(
this.info_template({ converse.templates.info({
'message': __('Topic set by %1$s to: %2$s', sender, subject) 'message': __('Topic set by %1$s to: %2$s', sender, subject)
})); }));
} }
@ -3330,9 +3193,6 @@
events: { events: {
'submit form#converse-login': 'authenticate' 'submit form#converse-login': 'authenticate'
}, },
tab_template: _.template(
'<li><a class="current" href="#login">'+__('Sign in')+'</a></li>'
),
template: _.template( template: _.template(
'<form id="converse-login">' + '<form id="converse-login">' +
'<label>'+__('XMPP/Jabber Username:')+'</label>' + '<label>'+__('XMPP/Jabber Username:')+'</label>' +
@ -3371,7 +3231,7 @@
}, },
render: function () { render: function () {
this.$tabs.append(this.tab_template()); this.$tabs.append(converse.templates.login_tab({label_sign_in: __('Sign in')}));
this.$el.find('input#jid').focus(); this.$el.find('input#jid').focus();
return this; return this;
}, },

24
main.js
View File

@ -1,4 +1,4 @@
require.config({ config = {
paths: { paths: {
"jquery": "components/jquery/jquery", "jquery": "components/jquery/jquery",
"locales": "locale/locales", "locales": "locale/locales",
@ -6,6 +6,9 @@ require.config({
"underscore": "components/underscore/underscore", "underscore": "components/underscore/underscore",
"backbone": "components/backbone/backbone", "backbone": "components/backbone/backbone",
"backbone.localStorage": "components/backbone.localStorage/backbone.localStorage", "backbone.localStorage": "components/backbone.localStorage/backbone.localStorage",
"text": 'components/requirejs-text/text',
"tpl": 'components/requirejs-tpl-jfparadis/tpl',
"converse-templates": "src/templates",
"strophe": "components/strophe/strophe", "strophe": "components/strophe/strophe",
"strophe.muc": "components/strophe.muc/index", "strophe.muc": "components/strophe.muc/index",
"strophe.roster": "components/strophe.roster/index", "strophe.roster": "components/strophe.roster/index",
@ -30,6 +33,14 @@ require.config({
"converse-dependencies": "src/deps-full" "converse-dependencies": "src/deps-full"
}, },
tpl: {
// Use Mustache style syntax for variable interpolation
templateSettings: {
evaluate : /\{\[([\s\S]+?)\]\}/g,
interpolate : /\{\{([\s\S]+?)\}\}/g
}
},
// define module dependencies for modules not using define // define module dependencies for modules not using define
shim: { shim: {
'backbone': { 'backbone': {
@ -51,8 +62,11 @@ require.config({
'strophe.vcard': { deps: ['strophe'] }, 'strophe.vcard': { deps: ['strophe'] },
'strophe.disco': { deps: ['strophe'] } 'strophe.disco': { deps: ['strophe'] }
} }
}); };
require(["jquery", "converse"], function(require, $, converse) { if (typeof(require) !== 'undefined') {
window.converse = converse; require.config(config);
}); require(["jquery", "converse"], function(require, $, converse) {
window.converse = converse;
});
}

31
src/templates.js Normal file
View File

@ -0,0 +1,31 @@
define("converse-templates", [
"tpl!src/templates/action",
"tpl!src/templates/message",
"tpl!src/templates/new_day",
"tpl!src/templates/info",
"tpl!src/templates/controlbox",
"tpl!src/templates/chatbox",
"tpl!src/templates/toolbar",
"tpl!src/templates/contacts_tab",
"tpl!src/templates/contacts_panel",
"tpl!src/templates/chatrooms_tab",
"tpl!src/templates/login_tab",
"tpl!src/templates/add_contact_dropdown",
"tpl!src/templates/add_contact_form"
], function () {
return {
action: arguments[0],
message: arguments[1],
new_day: arguments[2],
info: arguments[3],
controlbox: arguments[4],
chatbox: arguments[5],
toolbar: arguments[6],
contacts_tab: arguments[7],
contacts_panel: arguments[8],
chatrooms_tab: arguments[9],
login_tab: arguments[10],
add_contact_dropdown: arguments[11],
add_contact_form: arguments[12]
};
});

View File

@ -0,0 +1,4 @@
<div class="chat-message {{extra_classes}}">
<span class="chat-message-{{sender}}">{{time}} **{{username}} </span>
<span class="chat-message-content">{{message}}</span>
</div>

View File

@ -0,0 +1,8 @@
<dl class="add-converse-contact dropdown">
<dt id="xmpp-contact-search" class="fancy-dropdown">
<a class="toggle-xmpp-contact-form" href="#"
title="{{label_click_to_chat}}">
<span class="icon-plus"></span>{{label_add_contact}}</a>
</dt>
<dd class="search-xmpp" style="display:none"><ul></ul></dd>
</dl>

View File

@ -0,0 +1,9 @@
<li>
<form class="add-xmpp-contact">
<input type="text"
name="identifier"
class="username"
placeholder="{{label_contact_username}}"/>
<button type="submit">{{label_add}}</button>
</form>
<li>

View File

@ -0,0 +1,17 @@
<div class="chat-head chat-head-chatbox">
<a class="close-chatbox-button icon-close"></a>
<a href="{{url}}" target="_blank" class="user">
<div class="chat-title"> {{ fullname }} </div>
</a>
<p class="user-custom-message"><p/>
</div>
<div class="chat-content"></div>
<form class="sendXMPPMessage" action="" method="post">
{[ if (show_toolbar) { ]}
<ul class="chat-toolbar no-text-select"></ul>
{[ } ]}
<textarea
type="text"
class="chat-textarea"
placeholder="{{label_personal_message}}"/>
</form>

View File

@ -0,0 +1 @@
<li><a class="s" href="#chatrooms">{{label_rooms}}</a></li>

View File

@ -0,0 +1,10 @@
<form class="set-xmpp-status" action="" method="post">
<span id="xmpp-status-holder">
<select id="select-xmpp-status" style="display:none">
<option value="online">{{label_online}}</option>
<option value="dnd">{{label_busy}}</option>
<option value="away">{{label_away}}</option>
<option value="offline">{{label_offline}}</option>
</select>
</span>
</form>

View File

@ -0,0 +1 @@
<li><a class="s current" href="#users">{{label_contacts}}</a></li>

View File

@ -0,0 +1,5 @@
<div class="chat-head oc-chat-head">
<ul id="controlbox-tabs"></ul>
<a class="close-chatbox-button icon-close"></a>
</div>
<div class="controlbox-panes"></div>

1
src/templates/info.html Normal file
View File

@ -0,0 +1 @@
<div class="chat-info">{{message}}</div>

View File

@ -0,0 +1 @@
<li><a class="current" href="#login">{{label_sign_in}}</a></li>

View File

@ -0,0 +1,4 @@
<div class="chat-message {{extra_classes}}">
<span class="chat-message-{{sender}}">{{time}} {{username}}:&nbsp;</span>
<span class="chat-message-content">{{message}}</span>
</div>

View File

@ -0,0 +1 @@
<time class="chat-date" datetime="{{isodate}}">{{datestring}}</time>

View File

@ -0,0 +1,9 @@
<li>
<form class="search-xmpp-contact">
<input type="text"
name="identifier"
class="username"
placeholder="{{label_contact_name}}"/>
<button type="submit">{{label_search}}</button>
</form>
<li>

View File

@ -0,0 +1,53 @@
{[ if (show_emoticons) { ]}
<li class="toggle-smiley icon-happy" title="Insert a smilery">
<ul>
<li><a class="icon-smiley" href="#" data-emoticon=":)"></a></li>
<li><a class="icon-wink" href="#" data-emoticon=";)"></a></li>
<li><a class="icon-grin" href="#" data-emoticon=":D"></a></li>
<li><a class="icon-tongue" href="#" data-emoticon=":P"></a></li>
<li><a class="icon-cool" href="#" data-emoticon="8)"></a></li>
<li><a class="icon-evil" href="#" data-emoticon=">:)"></a></li>
<li><a class="icon-confused" href="#" data-emoticon=":S"></a></li>
<li><a class="icon-wondering" href="#" data-emoticon=":\"></a></li>
<li><a class="icon-angry" href="#" data-emoticon=">:("></a></li>
<li><a class="icon-sad" href="#" data-emoticon=":("></a></li>
<li><a class="icon-shocked" href="#" data-emoticon=":O"></a></li>
<li><a class="icon-thumbs-up" href="#" data-emoticon="(^.^)b"></a></li>
<li><a class="icon-heart" href="#" data-emoticon="<3"></a></li>
</ul>
</li>
{[ } ]}
{[ if (show_call_button) { ]}
<li><a class="toggle-call icon-phone" title="Start a call"></a></li>
{[ } ]}
{[ if (allow_otr) { ]}
<li class="toggle-otr {{otr_status_class}}" title="{{otr_tooltip}}">
<span class="chat-toolbar-text">{{otr_translated_status}}</span>
{[ if (otr_status == UNENCRYPTED) { ]}
<span class="icon-unlocked"></span>
{[ } ]}
{[ if (otr_status == UNVERIFIED) { ]}
<span class="icon-lock"></span>
{[ } ]}
{[ if (otr_status == VERIFIED) { ]}
<span class="icon-lock"></span>
{[ } ]}
{[ if (otr_status == FINISHED) { ]}
<span class="icon-unlocked"></span>
{[ } ]}
<ul>
{[ if (otr_status == UNENCRYPTED) { ]}
<li><a class="start-otr" href="#">{{label_start_encrypted_conversation}}</a></li>
{[ } ]}
{[ if (otr_status != UNENCRYPTED) { ]}
<li><a class="start-otr" href="#">{{label_start_encrypted_conversation}}</a></li>
<li><a class="end-otr" href="#">{{label_end_encrypted_conversation}}</a></li>
<li><a class="auth-otr" data-scheme="smp" href="#">{{label_verify_with_smp}}</a></li>
{[ } ]}
{[ if (otr_status == UNVERIFIED) { ]}
<li><a class="auth-otr" data-scheme="fingerprint" href="#">{{label_verify_with_fingerprints}}</a></li>
{[ } ]}
<li><a href="http://www.cypherpunks.ca/otr/help/3.2.0/levels.php" target="_blank">{{label_whats_this}}</a></li>
</ul>
</li>
{[ } ]}

View File

@ -8,6 +8,7 @@
<link rel="stylesheet" type="text/css" href="components/jasmine/src/html/jasmine.css"> <link rel="stylesheet" type="text/css" href="components/jasmine/src/html/jasmine.css">
<link rel="stylesheet" type="text/css" media="screen" href="stylesheets/stylesheet.css"> <link rel="stylesheet" type="text/css" media="screen" href="stylesheets/stylesheet.css">
<link rel="stylesheet" type="text/css" media="screen" href="converse.css"> <link rel="stylesheet" type="text/css" media="screen" href="converse.css">
<script src="main.js"></script>
<script data-main="tests_main" src="components/requirejs/require.js"></script> <script data-main="tests_main" src="components/requirejs/require.js"></script>
</head> </head>

View File

@ -1,77 +1,24 @@
require.config({ // Extra test dependencies
paths: { config.paths.mock = "tests/mock";
"jquery": "components/jquery/jquery", config.paths.utils = "tests/utils";
"locales": "locale/locales", config.paths.jasmine = "components/jasmine/lib/jasmine-core/jasmine";
"jquery.tinysort": "components/tinysort/src/jquery.tinysort", config.paths["jasmine-html"] = "components/jasmine/lib/jasmine-core/jasmine-html";
"underscore": "components/underscore/underscore", config.paths["jasmine-console-reporter"] = "node_modules/jasmine-reporters/src/jasmine.console_reporter";
"backbone": "components/backbone/backbone", config.paths["jasmine-junit-reporter"] = "node_modules/jasmine-reporters/src/jasmine.junit_reporter";
"backbone.localStorage": "components/backbone.localStorage/backbone.localStorage",
"strophe": "components/strophe/strophe",
"strophe.muc": "components/strophe.muc/index",
"strophe.roster": "components/strophe.roster/index",
"strophe.vcard": "components/strophe.vcard/index",
"strophe.disco": "components/strophe.disco/index",
"salsa20": "components/otr/build/dep/salsa20",
"bigint": "src/bigint",
"crypto.core": "components/otr/vendor/cryptojs/core",
"crypto.enc-base64": "components/otr/vendor/cryptojs/enc-base64",
"crypto.md5": "components/crypto-js/src/md5",
"crypto.evpkdf": "components/crypto-js/src/evpkdf",
"crypto.cipher-core": "components/otr/vendor/cryptojs/cipher-core",
"crypto.aes": "components/otr/vendor/cryptojs/aes",
"crypto.sha1": "components/otr/vendor/cryptojs/sha1",
"crypto.sha256": "components/otr/vendor/cryptojs/sha256",
"crypto.hmac": "components/otr/vendor/cryptojs/hmac",
"crypto.pad-nopadding": "components/otr/vendor/cryptojs/pad-nopadding",
"crypto.mode-ctr": "components/otr/vendor/cryptojs/mode-ctr",
"crypto": "src/crypto",
"eventemitter": "components/otr/build/dep/eventemitter",
"otr": "components/otr/build/otr",
"converse-dependencies": "src/deps-full",
// Extra test dependencies
"mock": "tests/mock",
"utils": "tests/utils",
"jasmine": "components/jasmine/lib/jasmine-core/jasmine",
"jasmine-html": "components/jasmine/lib/jasmine-core/jasmine-html",
"jasmine-console-reporter": "node_modules/jasmine-reporters/src/jasmine.console_reporter",
"jasmine-junit-reporter": "node_modules/jasmine-reporters/src/jasmine.junit_reporter"
},
// define module dependencies for modules not using define config.shim['jasmine-html'] = {
shim: { deps: ['jasmine'],
'backbone': { exports: 'jasmine'
//These script dependencies should be loaded before loading };
//backbone.js config.shim['jasmine-console-reporter'] = {
deps: [ deps: ['jasmine-html'],
'underscore', exports: 'jasmine'
'jquery' };
], config.shim['jasmine-junit-reporter'] = {
//Once loaded, use the global 'Backbone' as the deps: ['jasmine-html'],
//module value. exports: 'jasmine'
exports: 'Backbone' };
}, require.config(config);
'jquery.tinysort': { deps: ['jquery'] },
'strophe': { deps: ['jquery'] },
'underscore': { exports: '_' },
'strophe.muc': { deps: ['strophe', 'jquery'] },
'strophe.roster': { deps: ['strophe'] },
'strophe.vcard': { deps: ['strophe'] },
'strophe.disco': { deps: ['strophe'] },
// Extra test dependencies
'jasmine-html': {
deps: ['jasmine'],
exports: 'jasmine'
},
'jasmine-console-reporter': {
deps: ['jasmine-html'],
exports: 'jasmine'
},
'jasmine-junit-reporter': {
deps: ['jasmine-html'],
exports: 'jasmine'
}
}
});
// Polyfill 'bind' which is not available in phantomjs < 2.0 // Polyfill 'bind' which is not available in phantomjs < 2.0
if (!Function.prototype.bind) { if (!Function.prototype.bind) {