2012-10-18 21:37:07 +02:00
|
|
|
var subs = (function () {
|
|
|
|
|
|
|
|
var exports = {};
|
|
|
|
|
2013-01-07 23:30:21 +01:00
|
|
|
var stream_info = {}; // Maps lowercase stream name to stream properties object
|
2013-01-04 20:42:39 +01:00
|
|
|
var removed_streams = {};
|
2012-12-01 04:37:52 +01:00
|
|
|
// We fetch the stream colors asynchronous while the message feed is
|
|
|
|
// getting constructed, so we may need to go back and color streams
|
|
|
|
// that have already been rendered.
|
|
|
|
var initial_color_fetch = true;
|
2012-10-18 21:37:07 +02:00
|
|
|
|
2013-01-04 21:05:18 +01:00
|
|
|
var default_color = "#c2c2c2";
|
2013-01-04 20:42:39 +01:00
|
|
|
var next_sub_id = 0;
|
2013-01-04 18:02:01 +01:00
|
|
|
|
2013-01-07 22:18:47 +01:00
|
|
|
function render_subscribers() {
|
|
|
|
return domain !== 'mit.edu';
|
|
|
|
}
|
|
|
|
|
2012-10-18 21:37:07 +02:00
|
|
|
function case_insensitive_subscription_index(stream_name) {
|
|
|
|
var i;
|
|
|
|
var name = stream_name.toLowerCase();
|
|
|
|
|
|
|
|
for (i = 1; i < stream_list.length; i++) {
|
|
|
|
if (name === stream_list[i].toLowerCase()) {
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-12-01 04:37:52 +01:00
|
|
|
function update_table_stream_color(table, stream_name, color) {
|
|
|
|
$.each(table.find(".stream_label"), function () {
|
|
|
|
if ($(this).text() === stream_name) {
|
|
|
|
var parent_label = $(this).parent("td");
|
|
|
|
parent_label.css("background-color", color);
|
|
|
|
parent_label.prev("td").css("background-color", color);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function update_historical_message_color(stream_name, color) {
|
|
|
|
update_table_stream_color($(".focused_table"), stream_name, color);
|
|
|
|
if ($(".focused_table").attr("id") !== "#zhome") {
|
|
|
|
update_table_stream_color($("#zhome"), stream_name, color);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-12 07:43:58 +01:00
|
|
|
var colorpicker_options = {
|
|
|
|
clickoutFiresChange: true,
|
|
|
|
showPalette: true,
|
|
|
|
palette: [
|
|
|
|
['a47462', 'c2726a', 'e4523d', 'e7664d', 'ee7e4a', 'f4ae55'],
|
|
|
|
['76ce90', '53a063', '94c849', 'bfd56f', 'fae589', 'f5ce6e'],
|
|
|
|
['a6dcbf', 'addfe5', 'a6c7e5', '4f8de4', '95a5fd', 'b0a5fd'],
|
|
|
|
['c2c2c2', 'c8bebf', 'c6a8ad', 'e79ab5', 'bd86e5', '9987e1']
|
|
|
|
],
|
|
|
|
change: function (color) {
|
|
|
|
// TODO: Kind of a hack.
|
2013-01-04 21:05:18 +01:00
|
|
|
var sub_row = $(this).closest('.subscription_row');
|
|
|
|
var stream_name = sub_row.find('.subscription_name').text();
|
2012-12-12 07:43:58 +01:00
|
|
|
var hex_color = color.toHexString();
|
2013-01-07 23:20:19 +01:00
|
|
|
stream_info[stream_name.toLowerCase()].color = hex_color;
|
2013-01-04 21:05:18 +01:00
|
|
|
sub_row.find('.color_swatch').css('background-color', hex_color);
|
2012-12-12 07:43:58 +01:00
|
|
|
update_historical_message_color(stream_name, hex_color);
|
|
|
|
|
|
|
|
$.ajax({
|
|
|
|
type: 'POST',
|
|
|
|
url: '/json/subscriptions/property',
|
|
|
|
dataType: 'json',
|
|
|
|
data: {
|
|
|
|
"property": "stream_colors",
|
|
|
|
"stream_name": stream_name,
|
|
|
|
"color": hex_color
|
|
|
|
},
|
|
|
|
timeout: 10*1000
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-10-18 21:37:07 +02:00
|
|
|
function add_to_stream_list(stream_name) {
|
2012-11-07 23:25:04 +01:00
|
|
|
var stream_sub_row;
|
2013-01-04 20:42:39 +01:00
|
|
|
var sub;
|
|
|
|
|
|
|
|
if (exports.have(stream_name)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
var lstream_name = stream_name.toLowerCase();
|
|
|
|
|
|
|
|
stream_list.push(stream_name);
|
2012-11-07 23:25:04 +01:00
|
|
|
|
2013-01-04 20:42:39 +01:00
|
|
|
if (removed_streams[lstream_name] !== undefined) {
|
|
|
|
sub = removed_streams[lstream_name];
|
|
|
|
delete removed_streams[lstream_name];
|
|
|
|
stream_info[lstream_name] = sub;
|
|
|
|
} else {
|
2013-01-07 22:18:47 +01:00
|
|
|
sub = {name: stream_name, id: next_sub_id++, color: default_color,
|
|
|
|
render_subscribers: render_subscribers()};
|
2013-01-04 20:42:39 +01:00
|
|
|
stream_info[lstream_name] = sub;
|
|
|
|
|
|
|
|
$('#subscriptions_table').prepend(templates.subscription({subscriptions: [sub]}));
|
2012-10-18 21:37:07 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function remove_from_stream_list(stream_name) {
|
2013-01-04 20:42:39 +01:00
|
|
|
var lstream_name = stream_name.toLowerCase();
|
|
|
|
removed_streams[lstream_name] = stream_info[lstream_name];
|
|
|
|
delete stream_info[lstream_name];
|
2012-10-18 21:37:07 +02:00
|
|
|
var removal_index = case_insensitive_subscription_index(stream_name);
|
|
|
|
if (removal_index !== -1) {
|
|
|
|
stream_list.splice(removal_index, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-01 04:37:52 +01:00
|
|
|
exports.get_color = function (stream_name) {
|
2013-01-07 23:30:21 +01:00
|
|
|
var lstream_name = stream_name.toLowerCase();
|
|
|
|
if (stream_info[lstream_name] === undefined) {
|
2013-01-04 18:02:01 +01:00
|
|
|
return default_color;
|
|
|
|
}
|
2013-01-07 23:30:21 +01:00
|
|
|
return stream_info[lstream_name].color;
|
2012-12-01 04:37:52 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
exports.fetch_colors = function () {
|
|
|
|
$.ajax({
|
2012-12-02 22:58:00 +01:00
|
|
|
type: 'GET',
|
|
|
|
url: '/json/subscriptions/property',
|
2012-12-01 04:37:52 +01:00
|
|
|
dataType: 'json',
|
2012-12-02 22:58:00 +01:00
|
|
|
data: {"property": "stream_colors"},
|
2012-12-01 04:37:52 +01:00
|
|
|
timeout: 10*1000,
|
|
|
|
success: function (data) {
|
|
|
|
if (data) {
|
|
|
|
$.each(data.stream_colors, function (index, data) {
|
|
|
|
var stream_name = data[0];
|
|
|
|
var color = data[1];
|
2013-01-07 23:30:21 +01:00
|
|
|
stream_info[stream_name.toLowerCase()].color = color;
|
2012-12-01 04:37:52 +01:00
|
|
|
if (initial_color_fetch) {
|
|
|
|
update_historical_message_color(stream_name, color);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
initial_color_fetch = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2013-01-10 20:30:15 +01:00
|
|
|
exports.setup_page = function () {
|
2013-01-16 21:26:55 +01:00
|
|
|
util.make_loading_indicator($('#subs_page_loading_indicator'));
|
2012-10-03 22:24:17 +02:00
|
|
|
$.ajax({
|
2012-10-16 22:50:46 +02:00
|
|
|
type: 'POST',
|
2012-10-31 23:30:32 +01:00
|
|
|
url: '/json/subscriptions/list',
|
2012-10-03 22:24:17 +02:00
|
|
|
dataType: 'json',
|
|
|
|
timeout: 10*1000,
|
|
|
|
success: function (data) {
|
2013-01-16 21:26:55 +01:00
|
|
|
util.destroy_loading_indicator($('#subs_page_loading_indicator'));
|
2012-10-03 22:24:17 +02:00
|
|
|
$('#subscriptions_table tr').remove();
|
2013-01-07 19:46:52 +01:00
|
|
|
removed_streams = {};
|
2012-10-03 22:24:17 +02:00
|
|
|
if (data) {
|
2012-12-12 07:09:25 +01:00
|
|
|
var subscriptions = [];
|
2012-12-01 04:37:52 +01:00
|
|
|
$.each(data.subscriptions, function (index, data) {
|
|
|
|
var stream_name = data[0];
|
2013-01-07 22:18:47 +01:00
|
|
|
var sub = {name: stream_name, id: next_sub_id++,
|
|
|
|
color: data[1], render_subscribers: render_subscribers()};
|
2013-01-07 23:30:21 +01:00
|
|
|
stream_info[stream_name.toLowerCase()] = sub;
|
2013-01-04 20:42:39 +01:00
|
|
|
subscriptions.push(sub);
|
2012-12-12 07:09:25 +01:00
|
|
|
});
|
|
|
|
$('#subscriptions_table').append(templates.subscription({subscriptions: subscriptions}));
|
2012-10-03 22:24:17 +02:00
|
|
|
}
|
2012-10-31 23:10:18 +01:00
|
|
|
$('#streams').focus().select();
|
2012-10-03 22:24:17 +02:00
|
|
|
},
|
|
|
|
error: function (xhr) {
|
2013-01-16 21:26:55 +01:00
|
|
|
util.destroy_loading_indicator($('#subs_page_loading_indicator'));
|
2012-11-16 16:45:39 +01:00
|
|
|
ui.report_error("Error listing subscriptions", xhr, $("#subscriptions-status"));
|
2012-10-03 22:24:17 +02:00
|
|
|
}
|
|
|
|
});
|
2012-10-18 21:37:07 +02:00
|
|
|
};
|
2012-10-03 22:24:17 +02:00
|
|
|
|
2012-10-31 23:15:27 +01:00
|
|
|
exports.subscribe_for_send = function (stream, prompt_button) {
|
2012-10-03 22:24:17 +02:00
|
|
|
$.ajax({
|
|
|
|
type: 'POST',
|
|
|
|
url: '/json/subscriptions/add',
|
2012-11-16 19:43:27 +01:00
|
|
|
data: {"subscriptions": JSON.stringify([stream]) },
|
2012-10-03 22:24:17 +02:00
|
|
|
dataType: 'json',
|
|
|
|
timeout: 10*60*1000, // 10 minutes in ms
|
2012-10-09 21:01:41 +02:00
|
|
|
success: function (response) {
|
2012-10-31 18:36:08 +01:00
|
|
|
add_to_stream_list(stream);
|
|
|
|
compose.finish();
|
2013-01-16 20:03:33 +01:00
|
|
|
if (prompt_button !== undefined)
|
|
|
|
prompt_button.stop(true).fadeOut(500);
|
2012-10-03 22:24:17 +02:00
|
|
|
},
|
|
|
|
error: function (xhr, error_type, exn) {
|
2012-11-16 16:45:39 +01:00
|
|
|
ui.report_error("Unable to subscribe", xhr, $("#home-error"));
|
2012-10-03 22:24:17 +02:00
|
|
|
}
|
|
|
|
});
|
2012-10-18 21:37:07 +02:00
|
|
|
};
|
2012-10-09 21:01:41 +02:00
|
|
|
|
2012-10-18 21:37:07 +02:00
|
|
|
exports.have = function (stream_name) {
|
2013-01-04 18:02:01 +01:00
|
|
|
return (stream_info[stream_name.toLowerCase()] !== undefined);
|
2012-10-18 21:37:07 +02:00
|
|
|
};
|
2012-10-09 21:01:41 +02:00
|
|
|
|
2013-01-10 22:15:55 +01:00
|
|
|
function ajaxSubscribe(stream, button) {
|
2012-11-07 23:25:04 +01:00
|
|
|
$.ajax({
|
|
|
|
type: "POST",
|
|
|
|
url: "/json/subscriptions/add",
|
|
|
|
dataType: 'json', // This seems to be ignored. We still get back an xhr.
|
2012-11-16 19:43:27 +01:00
|
|
|
data: {"subscriptions": JSON.stringify([stream]) },
|
2012-11-07 23:25:04 +01:00
|
|
|
success: function (resp, statusText, xhr, form) {
|
2012-11-09 22:56:05 +01:00
|
|
|
if ($("#streams").val() === stream) {
|
2012-11-07 23:25:04 +01:00
|
|
|
$("#streams").val("");
|
|
|
|
}
|
|
|
|
var name, res = $.parseJSON(xhr.responseText);
|
|
|
|
if (res.subscribed.length === 0) {
|
|
|
|
name = res.already_subscribed[0];
|
2012-11-16 16:45:39 +01:00
|
|
|
ui.report_success("Already subscribed to " + name, $("#subscriptions-status"));
|
2012-11-07 23:25:04 +01:00
|
|
|
} else {
|
|
|
|
name = res.subscribed[0];
|
2012-11-16 16:45:39 +01:00
|
|
|
ui.report_success("Successfully added subscription to " + name,
|
2012-11-07 23:25:04 +01:00
|
|
|
$("#subscriptions-status"));
|
|
|
|
}
|
|
|
|
add_to_stream_list(name);
|
2013-01-10 22:15:55 +01:00
|
|
|
if (button !== undefined) {
|
|
|
|
button.text("Unsubscribe").removeClass("btn-primary");
|
|
|
|
}
|
|
|
|
typeahead_helper.update_autocomplete();
|
2012-11-07 23:25:04 +01:00
|
|
|
},
|
|
|
|
error: function (xhr) {
|
2012-11-16 16:45:39 +01:00
|
|
|
ui.report_error("Error adding subscription", xhr, $("#subscriptions-status"));
|
2012-11-07 23:25:04 +01:00
|
|
|
$("#streams").focus();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2012-10-09 21:01:41 +02:00
|
|
|
|
2013-01-10 22:15:55 +01:00
|
|
|
function ajaxUnsubscribe(stream, button) {
|
2012-11-16 20:11:08 +01:00
|
|
|
$.ajax({
|
|
|
|
type: "POST",
|
|
|
|
url: "/json/subscriptions/remove",
|
2012-10-03 22:24:17 +02:00
|
|
|
dataType: 'json', // This seems to be ignored. We still get back an xhr.
|
2012-11-16 20:11:08 +01:00
|
|
|
data: {"subscriptions": JSON.stringify([stream]) },
|
2012-10-03 22:24:17 +02:00
|
|
|
success: function (resp, statusText, xhr, form) {
|
2012-11-16 20:11:08 +01:00
|
|
|
var name, res = $.parseJSON(xhr.responseText);
|
|
|
|
if (res.removed.length === 0) {
|
|
|
|
name = res.not_subscribed[0];
|
2012-11-16 16:45:39 +01:00
|
|
|
ui.report_success("Already not subscribed to " + name,
|
2012-11-16 20:11:08 +01:00
|
|
|
$("#subscriptions-status"));
|
|
|
|
} else {
|
|
|
|
name = res.removed[0];
|
2012-11-16 16:45:39 +01:00
|
|
|
ui.report_success("Successfully removed subscription to " + name,
|
2012-11-16 20:11:08 +01:00
|
|
|
$("#subscriptions-status"));
|
|
|
|
}
|
2012-10-10 23:26:01 +02:00
|
|
|
remove_from_stream_list(name);
|
2013-01-10 22:15:55 +01:00
|
|
|
button.text("Subscribe").addClass("btn-primary");
|
2012-11-19 01:09:40 +01:00
|
|
|
typeahead_helper.update_autocomplete();
|
2012-10-03 22:24:17 +02:00
|
|
|
},
|
|
|
|
error: function (xhr) {
|
2012-11-16 16:45:39 +01:00
|
|
|
ui.report_error("Error removing subscription", xhr, $("#subscriptions-status"));
|
2012-11-16 20:11:08 +01:00
|
|
|
$("#streams").focus();
|
2012-10-03 22:24:17 +02:00
|
|
|
}
|
|
|
|
});
|
2013-01-10 22:15:55 +01:00
|
|
|
}
|
2012-11-16 20:11:08 +01:00
|
|
|
|
|
|
|
$(function () {
|
|
|
|
var i;
|
2013-01-04 18:02:01 +01:00
|
|
|
// Populate stream_info with data handed over to client-side template.
|
2012-11-16 20:11:08 +01:00
|
|
|
for (i = 0; i < stream_list.length; i++) {
|
2013-01-04 18:02:01 +01:00
|
|
|
stream_info[stream_list[i].toLowerCase()] = {color: default_color};
|
2012-11-16 20:11:08 +01:00
|
|
|
}
|
2012-10-03 22:24:17 +02:00
|
|
|
|
2012-10-31 18:36:08 +01:00
|
|
|
$("#add_new_subscription").on("submit", function (e) {
|
|
|
|
e.preventDefault();
|
2012-11-07 23:25:04 +01:00
|
|
|
ajaxSubscribe($("#streams").val());
|
2012-10-03 22:24:17 +02:00
|
|
|
});
|
2013-01-07 22:09:33 +01:00
|
|
|
|
2013-01-10 22:15:55 +01:00
|
|
|
$("#subscriptions_table").on("click", ".sub_unsub_button", function (e) {
|
|
|
|
e.preventDefault();
|
|
|
|
e.stopPropagation();
|
|
|
|
var sub_row = $(e.target).closest('.subscription_row');
|
|
|
|
var stream_name = sub_row.find('.subscription_name').text();
|
|
|
|
var sub = stream_info[stream_name.toLowerCase()];
|
|
|
|
|
|
|
|
if (sub) {
|
|
|
|
ajaxUnsubscribe(stream_name, $(e.target));
|
|
|
|
} else {
|
|
|
|
ajaxSubscribe(stream_name, $(e.target));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2013-01-16 20:16:28 +01:00
|
|
|
$("#subscriptions_table").on("show", ".subscription_settings", function (e) {
|
|
|
|
var colorpicker = $(e.target).closest('.subscription_row').find('.colorpicker');
|
|
|
|
colorpicker.spectrum(colorpicker_options);
|
|
|
|
});
|
|
|
|
|
|
|
|
if (! render_subscribers()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-01-10 19:33:56 +01:00
|
|
|
// From here down is only stuff that happens when we're rendering
|
|
|
|
// the subscriber settings
|
|
|
|
|
|
|
|
$("#subscriptions_table").on("submit", ".subscriber_list_add form", function (e) {
|
|
|
|
e.preventDefault();
|
|
|
|
var sub_row = $(e.target).closest('.subscription_row');
|
|
|
|
var stream = sub_row.find('.subscription_name').text();
|
|
|
|
var text_box = sub_row.find('input[name="principal"]');
|
2013-01-10 20:10:06 +01:00
|
|
|
var principal = $.trim(text_box.val());
|
2013-01-10 19:33:56 +01:00
|
|
|
// TODO: clean up this error handling
|
|
|
|
var error_elem = sub_row.find('.subscriber_list_container .alert-error');
|
|
|
|
var warning_elem = sub_row.find('.subscriber_list_container .alert-warning');
|
|
|
|
var list = sub_row.find('.subscriber_list_container ul');
|
|
|
|
|
|
|
|
$.ajax({
|
|
|
|
type: "POST",
|
|
|
|
url: "/json/subscriptions/add",
|
|
|
|
dataType: 'json',
|
|
|
|
data: {"subscriptions": JSON.stringify([stream]),
|
|
|
|
"principal": principal},
|
|
|
|
success: function (data) {
|
|
|
|
text_box.val('');
|
|
|
|
if (data.subscribed.length) {
|
|
|
|
error_elem.addClass("hide");
|
|
|
|
warning_elem.addClass("hide");
|
2013-01-14 22:19:13 +01:00
|
|
|
var subscriber = people_dict[principal].full_name + ' <' + principal + '>';
|
|
|
|
$('<li>').prependTo(list).text(subscriber);
|
2013-01-10 19:33:56 +01:00
|
|
|
} else {
|
|
|
|
error_elem.addClass("hide");
|
|
|
|
warning_elem.removeClass("hide").text("User already subscribed");
|
|
|
|
}
|
|
|
|
},
|
|
|
|
error: function (xhr) {
|
|
|
|
warning_elem.addClass("hide");
|
|
|
|
error_elem.removeClass("hide").text("Could not add user to this stream");
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
2013-01-07 22:09:33 +01:00
|
|
|
|
|
|
|
$("#subscriptions_table").on("show", ".subscription_settings", function (e) {
|
|
|
|
var sub_row = $(e.target).closest('.subscription_row');
|
|
|
|
var stream = sub_row.find('.subscription_name').text();
|
2013-01-10 19:33:56 +01:00
|
|
|
var error_elem = sub_row.find('.subscriber_list_container .alert-error');
|
2013-01-07 22:09:33 +01:00
|
|
|
var list = sub_row.find('.subscriber_list_container ul');
|
2013-01-10 20:22:25 +01:00
|
|
|
|
2013-01-07 22:09:33 +01:00
|
|
|
error_elem.addClass('hide');
|
|
|
|
list.empty();
|
|
|
|
|
|
|
|
// TODO: Show a spinner while the list is loading
|
|
|
|
$.ajax({
|
|
|
|
type: "POST",
|
|
|
|
url: "/json/get_subscribers",
|
|
|
|
dataType: 'json', // This seems to be ignored. We still get back an xhr.
|
|
|
|
data: {stream: stream},
|
|
|
|
success: function (data) {
|
2013-01-14 22:19:13 +01:00
|
|
|
var subscribers = $.map(data.subscribers, function (elem) {
|
2013-01-15 23:28:58 +01:00
|
|
|
var person = people_dict[elem];
|
|
|
|
if (person === undefined) {
|
|
|
|
return elem;
|
|
|
|
}
|
2013-01-14 22:19:13 +01:00
|
|
|
return people_dict[elem].full_name + ' <' + elem + '>';
|
|
|
|
});
|
|
|
|
$.each(subscribers.sort(), function (idx, elem) {
|
2013-01-14 22:15:10 +01:00
|
|
|
$('<li>').appendTo(list).text(elem);
|
2013-01-07 22:09:33 +01:00
|
|
|
});
|
|
|
|
},
|
|
|
|
error: function (xhr) {
|
|
|
|
error_elem.removeClass("hide").text("Could not fetch subscriber list");
|
|
|
|
}
|
|
|
|
});
|
2013-01-10 19:57:34 +01:00
|
|
|
|
|
|
|
sub_row.find('input[name="principal"]').typeahead({
|
|
|
|
source: typeahead_helper.private_message_typeahead_list,
|
|
|
|
items: 4,
|
|
|
|
highlighter: function (item) {
|
|
|
|
var query = this.query;
|
|
|
|
return typeahead_helper.highlight_with_escaping(query, item);
|
|
|
|
},
|
2013-01-10 20:10:06 +01:00
|
|
|
matcher: function (item) {
|
|
|
|
var query = $.trim(this.query);
|
|
|
|
if (query === '') {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
// Case-insensitive.
|
|
|
|
return (item.toLowerCase().indexOf(query.toLowerCase()) !== -1);
|
|
|
|
},
|
2013-01-10 19:57:34 +01:00
|
|
|
updater: function (item) {
|
|
|
|
return typeahead_helper.private_message_mapped[item].email;
|
|
|
|
}
|
|
|
|
});
|
2013-01-07 22:09:33 +01:00
|
|
|
});
|
2012-10-03 22:24:17 +02:00
|
|
|
});
|
2012-10-18 21:37:07 +02:00
|
|
|
|
|
|
|
return exports;
|
|
|
|
|
|
|
|
}());
|