mirror of https://github.com/zulip/zulip.git
Factor out compose typeahead into individual functions
(imported from commit 293c61d5793ced7792c57713210a34736d851ae8)
This commit is contained in:
parent
03fe84aa6a
commit
4f0f469a8e
|
@ -183,6 +183,127 @@ exports.split_at_cursor = function (query) {
|
|||
return [query.slice(0, cursor), query.slice(cursor)];
|
||||
};
|
||||
|
||||
exports.compose_content_begins_typeahead = function (query) {
|
||||
var q = exports.split_at_cursor(query)[0];
|
||||
|
||||
var strings = q.split(/[\s*(){}\[\]]/);
|
||||
if (strings.length < 1) {
|
||||
return false;
|
||||
}
|
||||
var current_token = strings[strings.length-1];
|
||||
|
||||
// Only start the emoji autocompleter if : is directly after one
|
||||
// of the whitespace or punctuation chars we split on.
|
||||
if (current_token[0] === ':') {
|
||||
// We don't want to match non-emoji emoticons such
|
||||
// as :P or :-p
|
||||
// Also, if the user has only typed a colon and nothing after,
|
||||
// no need to match yet.
|
||||
if (/^:-?.?$/.test(current_token)) {
|
||||
return false;
|
||||
}
|
||||
this.completing = 'emoji';
|
||||
this.token = current_token.substring(1);
|
||||
return emoji.emojis;
|
||||
}
|
||||
|
||||
// Don't autocomplete more than this many characters.
|
||||
var max_chars = 30;
|
||||
var last_at = q.lastIndexOf('@');
|
||||
if (last_at === -1 || last_at < q.length-1 - max_chars) {
|
||||
return false; // No '@', or too far back
|
||||
}
|
||||
|
||||
// Only match if the @ follows a space, various punctuation,
|
||||
// or is at the beginning of the string.
|
||||
if (last_at > 0 && "\n\t \"'(){}[]".indexOf(q[last_at-1]) === -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
current_token = q.substring(last_at + 1);
|
||||
if (current_token.length < 1 || current_token.lastIndexOf('*') !== -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.completing = 'mention';
|
||||
this.token = current_token.substring(current_token.indexOf("@")+1);
|
||||
var all_item = {
|
||||
special_item_text: "all (Notify everyone)",
|
||||
email: "all",
|
||||
// Always sort above, under the assumption that names will
|
||||
// be longer and only contain "all" as a substring.
|
||||
pm_recipient_count: Infinity,
|
||||
full_name: "all"
|
||||
};
|
||||
return page_params.people_list.concat([all_item]);
|
||||
};
|
||||
|
||||
exports.content_highlighter = function (item) {
|
||||
if (this.completing === 'emoji') {
|
||||
return "<img class='emoji' src='" + item.emoji_url + "' /> " + item.emoji_name;
|
||||
} else if (this.completing === 'mention') {
|
||||
var item_formatted = typeahead_helper.render_person(item);
|
||||
return typeahead_helper.highlight_with_escaping(this.token, item_formatted);
|
||||
}
|
||||
};
|
||||
|
||||
exports.content_typeahead_selected = function (item) {
|
||||
var pieces = exports.split_at_cursor(this.query);
|
||||
var beginning = pieces[0];
|
||||
var rest = pieces[1];
|
||||
|
||||
if (this.completing === 'emoji') {
|
||||
//leading and trailing spaces are required for emoji, except if it begins a message.
|
||||
if (beginning.lastIndexOf(":") === 0 || beginning.charAt(beginning.lastIndexOf(":") - 1) === " ") {
|
||||
beginning = beginning.replace(/:\S+$/, "") + ":" + item.emoji_name + ": ";
|
||||
} else {
|
||||
beginning = beginning.replace(/:\S+$/, "") + " :" + item.emoji_name + ": ";
|
||||
}
|
||||
} else if (this.completing === 'mention') {
|
||||
beginning = (beginning.substring(0, beginning.length - this.token.length-1)
|
||||
+ '@**' + item.full_name + '** ');
|
||||
|
||||
// We insert a special `all` item to the autocompleter above
|
||||
// Don't consider it a user mention
|
||||
if (item.email !== 'all') {
|
||||
$(document).trigger('usermention_completed.zulip', {mentioned: item});
|
||||
}
|
||||
}
|
||||
|
||||
// Keep the cursor after the newly inserted text, as Bootstrap will call textbox.change() to overwrite the text
|
||||
// in the textbox.
|
||||
setTimeout(function () {
|
||||
$('#new_message_content').caret(beginning.length, beginning.length);
|
||||
}, 0);
|
||||
return beginning + rest;
|
||||
};
|
||||
|
||||
exports.initialize_compose_typeahead = function (selector) {
|
||||
$(selector).typeahead({
|
||||
items: 5,
|
||||
dropup: true,
|
||||
fixed: true,
|
||||
source: exports.compose_content_begins_typeahead,
|
||||
highlighter: exports.content_highlighter,
|
||||
matcher: function (item) {
|
||||
if (this.completing === 'emoji') {
|
||||
return query_matches_emoji(this.token, item);
|
||||
} else if (this.completing === 'mention') {
|
||||
return query_matches_person(this.token, item);
|
||||
}
|
||||
},
|
||||
sorter: function (matches) {
|
||||
if (this.completing === 'emoji') {
|
||||
return typeahead_helper.sort_emojis(matches, this.token);
|
||||
} else if (this.completing === 'mention') {
|
||||
return typeahead_helper.sort_recipients(matches, this.token);
|
||||
}
|
||||
},
|
||||
updater: exports.content_typeahead_selected,
|
||||
stopAdvance: true // Do not advance to the next field on a tab or enter
|
||||
});
|
||||
};
|
||||
|
||||
exports.initialize = function () {
|
||||
select_on_focus("stream");
|
||||
select_on_focus("subject");
|
||||
|
@ -286,118 +407,7 @@ exports.initialize = function () {
|
|||
stopAdvance: true // Do not advance to the next field on a tab or enter
|
||||
});
|
||||
|
||||
$( "#new_message_content" ).typeahead({
|
||||
source: function (query, process) {
|
||||
var q = exports.split_at_cursor(query)[0];
|
||||
|
||||
var strings = q.split(/[\s*(){}\[\]]/);
|
||||
if (strings.length < 1) {
|
||||
return false;
|
||||
}
|
||||
var current_token = strings[strings.length-1];
|
||||
|
||||
// Only start the emoji autocompleter if : is directly after one
|
||||
// of the whitespace or punctuation chars we split on.
|
||||
if (current_token[0] === ':') {
|
||||
// We don't want to match non-emoji emoticons such
|
||||
// as :P or :-p
|
||||
// Also, if the user has only typed a colon and nothing after,
|
||||
// no need to match yet.
|
||||
if (/^:-?.?$/.test(current_token)) {
|
||||
return false;
|
||||
}
|
||||
this.completing = 'emoji';
|
||||
this.token = current_token.substring(1);
|
||||
return emoji.emojis;
|
||||
}
|
||||
|
||||
// Don't autocomplete more than this many characters.
|
||||
var max_chars = 30;
|
||||
var last_at = q.lastIndexOf('@');
|
||||
if (last_at === -1 || last_at < q.length-1 - max_chars) {
|
||||
return false; // No '@', or too far back
|
||||
}
|
||||
|
||||
// Only match if the @ follows a space, various punctuation,
|
||||
// or is at the beginning of the string.
|
||||
if (last_at > 0 && "\n\t \"'(){}[]".indexOf(q[last_at-1]) === -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
current_token = q.substring(last_at + 1);
|
||||
if (current_token.length < 1 || current_token.lastIndexOf('*') !== -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.completing = 'mention';
|
||||
this.token = current_token.substring(current_token.indexOf("@")+1);
|
||||
var all_item = {
|
||||
special_item_text: "all (Notify everyone)",
|
||||
email: "all",
|
||||
// Always sort above, under the assumption that names will
|
||||
// be longer and only contain "all" as a substring.
|
||||
pm_recipient_count: Infinity,
|
||||
full_name: "all"
|
||||
};
|
||||
return page_params.people_list.concat([all_item]);
|
||||
},
|
||||
items: 5,
|
||||
highlighter: function (item) {
|
||||
if (this.completing === 'emoji') {
|
||||
return "<img class='emoji' src='" + item.emoji_url + "' /> " + item.emoji_name;
|
||||
} else if (this.completing === 'mention') {
|
||||
var item_formatted = typeahead_helper.render_person(item);
|
||||
return typeahead_helper.highlight_with_escaping(this.token, item_formatted);
|
||||
}
|
||||
},
|
||||
dropup: true,
|
||||
fixed: true,
|
||||
matcher: function (item) {
|
||||
if (this.completing === 'emoji') {
|
||||
return query_matches_emoji(this.token, item);
|
||||
} else if (this.completing === 'mention') {
|
||||
return query_matches_person(this.token, item);
|
||||
}
|
||||
},
|
||||
sorter: function (matches) {
|
||||
if (this.completing === 'emoji') {
|
||||
return typeahead_helper.sort_emojis(matches, this.token);
|
||||
} else if (this.completing === 'mention') {
|
||||
return typeahead_helper.sort_recipients(matches, this.token);
|
||||
}
|
||||
},
|
||||
updater: function (item) {
|
||||
var pieces = exports.split_at_cursor(this.query);
|
||||
var beginning = pieces[0];
|
||||
var rest = pieces[1];
|
||||
|
||||
if (this.completing === 'emoji') {
|
||||
//leading and trailing spaces are required for emoji, except if it begins a message.
|
||||
if (beginning.lastIndexOf(":") === 0 || beginning.charAt(beginning.lastIndexOf(":") - 1) === " ") {
|
||||
beginning = beginning.replace(/:\S+$/, "") + ":" + item.emoji_name + ": ";
|
||||
} else {
|
||||
beginning = beginning.replace(/:\S+$/, "") + " :" + item.emoji_name + ": ";
|
||||
}
|
||||
} else if (this.completing === 'mention') {
|
||||
beginning = (beginning.substring(0, beginning.length - this.token.length-1)
|
||||
+ '@**' + item.full_name + '** ');
|
||||
|
||||
// We insert a special `all` item to the autocompleter above
|
||||
// Don't consider it a user mention
|
||||
if (item.email !== 'all') {
|
||||
$(document).trigger('usermention_completed.zulip', {mentioned: item});
|
||||
}
|
||||
}
|
||||
|
||||
// Keep the cursor after the newly inserted text, as Bootstrap will call textbox.change() to overwrite the text
|
||||
// in the textbox.
|
||||
setTimeout(function () {
|
||||
$('#new_message_content').caret(beginning.length, beginning.length);
|
||||
}, 0);
|
||||
return beginning + rest;
|
||||
},
|
||||
stopAdvance: true // Do not advance to the next field on a tab or enter
|
||||
});
|
||||
exports.initialize_compose_typeahead("#new_message_content");
|
||||
|
||||
$( "#private_message_recipient" ).blur(function (event) {
|
||||
var val = $(this).val();
|
||||
|
|
Loading…
Reference in New Issue