mirror of
https://github.com/zulip/zulip.git
synced 2025-11-11 17:36:27 +00:00
copy_and_paste: Extract analyze_selection function.
This is the part where the whole selection is analyzed to get the `start_id` and `end_id` of the messages that are selected (the loop part of the copy handler). This is extracted and exported as well.
This commit is contained in:
@@ -88,83 +88,15 @@ function copy_handler() {
|
|||||||
//
|
//
|
||||||
// * Otherwise, we want to copy the bodies of all messages that
|
// * Otherwise, we want to copy the bodies of all messages that
|
||||||
// were partially covered by the selection.
|
// were partially covered by the selection.
|
||||||
//
|
|
||||||
// Firefox and Chrome handle selection of multiple messages
|
|
||||||
// differently. Firefox typically creates multiple ranges for the
|
|
||||||
// selection, whereas Chrome typically creates just one.
|
|
||||||
//
|
|
||||||
// Our goal in the below loop is to compute and be prepared to
|
|
||||||
// analyze the combined range of the selections, and copy their
|
|
||||||
// full content.
|
|
||||||
|
|
||||||
var selection = window.getSelection();
|
var selection = window.getSelection();
|
||||||
var i;
|
var analysis = exports.analyze_selection(selection);
|
||||||
var range;
|
var ranges = analysis.ranges;
|
||||||
var ranges = [];
|
var start_id = analysis.start_id;
|
||||||
var startc;
|
var end_id = analysis.end_id;
|
||||||
var endc;
|
var skip_same_td_check = analysis.skip_same_td_check;
|
||||||
var initial_end_tr;
|
|
||||||
var start_id;
|
|
||||||
var end_id;
|
|
||||||
var start_data;
|
|
||||||
var end_data;
|
|
||||||
// skip_same_td_check is true whenever we know for a fact that the
|
|
||||||
// selection covers multiple messages (and thus we should no
|
|
||||||
// longer consider letting the browser handle the copy event).
|
|
||||||
var skip_same_td_check = false;
|
|
||||||
var div = $('<div>');
|
var div = $('<div>');
|
||||||
|
|
||||||
for (i = 0; i < selection.rangeCount; i += 1) {
|
|
||||||
range = selection.getRangeAt(i);
|
|
||||||
ranges.push(range);
|
|
||||||
|
|
||||||
startc = $(range.startContainer);
|
|
||||||
start_data = find_boundary_tr($(startc.parents('.selectable_row, .message_header')[0]), function (row) {
|
|
||||||
return row.next();
|
|
||||||
});
|
|
||||||
if (start_data === undefined) {
|
|
||||||
// Skip any selection sections that don't intersect a message.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (start_id === undefined) {
|
|
||||||
// start_id is the Zulip message ID of the first message
|
|
||||||
// touched by the selection.
|
|
||||||
start_id = start_data[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
endc = $(range.endContainer);
|
|
||||||
// If the selection ends in the bottom whitespace, we should
|
|
||||||
// act as though the selection ends on the final message.
|
|
||||||
// This handles the issue that Chrome seems to like selecting
|
|
||||||
// the compose_close button when you go off the end of the
|
|
||||||
// last message
|
|
||||||
if (endc.attr('id') === "bottom_whitespace" || endc.attr('id') === "compose_close") {
|
|
||||||
initial_end_tr = $(".message_row:last");
|
|
||||||
// The selection goes off the end of the message feed, so
|
|
||||||
// this is a multi-message selection.
|
|
||||||
skip_same_td_check = true;
|
|
||||||
} else {
|
|
||||||
initial_end_tr = $(endc.parents('.selectable_row')[0]);
|
|
||||||
}
|
|
||||||
end_data = find_boundary_tr(initial_end_tr, function (row) {
|
|
||||||
return row.prev();
|
|
||||||
});
|
|
||||||
|
|
||||||
if (end_data === undefined) {
|
|
||||||
// Skip any selection sections that don't intersect a message.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (end_data[0] !== undefined) {
|
|
||||||
end_id = end_data[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (start_data[1] || end_data[1]) {
|
|
||||||
// If the find_boundary_tr call for either the first or
|
|
||||||
// the last message covered by the selection
|
|
||||||
skip_same_td_check = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (start_id === undefined || end_id === undefined) {
|
if (start_id === undefined || end_id === undefined) {
|
||||||
// In this case either the starting message or the ending
|
// In this case either the starting message or the ending
|
||||||
// message is not defined, so this is definitely not a
|
// message is not defined, so this is definitely not a
|
||||||
@@ -236,6 +168,92 @@ function copy_handler() {
|
|||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.analyze_selection = function (selection) {
|
||||||
|
// Here we analyze our selection to determine if part of a message
|
||||||
|
// or multiple messages are selected.
|
||||||
|
//
|
||||||
|
// Firefox and Chrome handle selection of multiple messages
|
||||||
|
// differently. Firefox typically creates multiple ranges for the
|
||||||
|
// selection, whereas Chrome typically creates just one.
|
||||||
|
//
|
||||||
|
// Our goal in the below loop is to compute and be prepared to
|
||||||
|
// analyze the combined range of the selections, and copy their
|
||||||
|
// full content.
|
||||||
|
|
||||||
|
var i;
|
||||||
|
var range;
|
||||||
|
var ranges = [];
|
||||||
|
var startc;
|
||||||
|
var endc;
|
||||||
|
var initial_end_tr;
|
||||||
|
var start_id;
|
||||||
|
var end_id;
|
||||||
|
var start_data;
|
||||||
|
var end_data;
|
||||||
|
// skip_same_td_check is true whenever we know for a fact that the
|
||||||
|
// selection covers multiple messages (and thus we should no
|
||||||
|
// longer consider letting the browser handle the copy event).
|
||||||
|
var skip_same_td_check = false;
|
||||||
|
|
||||||
|
for (i = 0; i < selection.rangeCount; i += 1) {
|
||||||
|
range = selection.getRangeAt(i);
|
||||||
|
ranges.push(range);
|
||||||
|
|
||||||
|
startc = $(range.startContainer);
|
||||||
|
start_data = find_boundary_tr($(startc.parents('.selectable_row, .message_header')[0]), function (row) {
|
||||||
|
return row.next();
|
||||||
|
});
|
||||||
|
if (start_data === undefined) {
|
||||||
|
// Skip any selection sections that don't intersect a message.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (start_id === undefined) {
|
||||||
|
// start_id is the Zulip message ID of the first message
|
||||||
|
// touched by the selection.
|
||||||
|
start_id = start_data[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
endc = $(range.endContainer);
|
||||||
|
// If the selection ends in the bottom whitespace, we should
|
||||||
|
// act as though the selection ends on the final message.
|
||||||
|
// This handles the issue that Chrome seems to like selecting
|
||||||
|
// the compose_close button when you go off the end of the
|
||||||
|
// last message
|
||||||
|
if (endc.attr('id') === "bottom_whitespace" || endc.attr('id') === "compose_close") {
|
||||||
|
initial_end_tr = $(".message_row:last");
|
||||||
|
// The selection goes off the end of the message feed, so
|
||||||
|
// this is a multi-message selection.
|
||||||
|
skip_same_td_check = true;
|
||||||
|
} else {
|
||||||
|
initial_end_tr = $(endc.parents('.selectable_row')[0]);
|
||||||
|
}
|
||||||
|
end_data = find_boundary_tr(initial_end_tr, function (row) {
|
||||||
|
return row.prev();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (end_data === undefined) {
|
||||||
|
// Skip any selection sections that don't intersect a message.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (end_data[0] !== undefined) {
|
||||||
|
end_id = end_data[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start_data[1] || end_data[1]) {
|
||||||
|
// If the find_boundary_tr call for either the first or
|
||||||
|
// the last message covered by the selection
|
||||||
|
skip_same_td_check = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
ranges: ranges,
|
||||||
|
start_id: start_id,
|
||||||
|
end_id: end_id,
|
||||||
|
skip_same_td_check: skip_same_td_check,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
exports.paste_handler_converter = function (paste_html) {
|
exports.paste_handler_converter = function (paste_html) {
|
||||||
var converters = {
|
var converters = {
|
||||||
converters: [
|
converters: [
|
||||||
|
|||||||
Reference in New Issue
Block a user