var copy_and_paste = (function () { var exports = {}; function find_boundary_tr(initial_tr, iterate_row) { var j; var skip_same_td_check = false; var tr = initial_tr; // If the selection boundary is somewhere that does not have a // parent tr, we should let the browser handle the copy-paste // entirely on its own if (tr.length === 0) { return undefined; } // If the selection boundary is on a table row that does not have an // associated message id (because the user clicked between messages), // then scan downwards until we hit a table row with a message id. // To ensure we can't enter an infinite loop, bail out (and let the // browser handle the copy-paste on its own) if we don't hit what we // are looking for within 10 rows. for (j = 0; (!tr.is('.message_row')) && j < 10; j += 1) { tr = iterate_row(tr); } if (j === 10) { return undefined; } else if (j !== 0) { // If we updated tr, then we are not dealing with a selection // that is entirely within one td, and we can skip the same td // check (In fact, we need to because it won't work correctly // in this case) skip_same_td_check = true; } return [rows.id(tr), skip_same_td_check]; } function copy_handler() { var selection = window.getSelection(); var i; var range; var ranges = []; var startc; var endc; var initial_end_tr; var start_id; var end_id; var row; var message; var start_data; var end_data; var skip_same_td_check = false; var div = $('
').append($('').text(content.text()))); } message = current_msg_list.get(rows.id(row)); var message_firstp = $(message.content).slice(0, 1); message_firstp.prepend(message.sender_full_name + ": "); div.append(message_firstp); div.append($(message.content).slice(1)); } } if (window.bridge !== undefined) { // If the user is running the desktop app, // convert emoji images to plain text for // copy-paste purposes. ui.replace_emoji_with_text(div); } // Select div so that the browser will copy it // instead of copying the original selection div.css({position: 'absolute', left: '-99999px'}) .attr('id', 'copytempdiv'); $('body').append(div); selection.selectAllChildren(div[0]); // After the copy has happened, delete the div and // change the selection back to the original selection window.setTimeout(function () { selection = window.getSelection(); selection.removeAllRanges(); _.each(ranges, function (range) { selection.addRange(range); }); $('#copytempdiv').remove(); },0); } exports.paste_handler_converter = function (paste_html) { var converters = { converters: [ { filter: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'], replacement: function (content) { return content; }, }, { filter: ['em', 'i'], replacement: function (content) { return '*' + content + '*'; }, }, ], }; var markdown_html = toMarkdown(paste_html, converters); // Now that we've done the main conversion, we want to remove // any HTML tags that weren't converted to markdown-style // text, since Bugdown doesn't support those. var div = document.createElement("div"); div.innerHTML = markdown_html; // Using textContent for modern browsers, innerText works for Internet Explorer return div.textContent || div.innerText || ""; }; exports.paste_handler = function (event) { var clipboardData = event.originalEvent.clipboardData; var paste_html = clipboardData.getData('text/html'); if (paste_html && page_params.development) { event.preventDefault(); var text = exports.paste_handler_converter(paste_html); compose_ui.insert_syntax_and_focus(text); } }; $(function () { $(document).on('copy', copy_handler); $("#compose-textarea").bind('paste', exports.paste_handler); }); return exports; }()); if (typeof module !== 'undefined') { module.exports = copy_and_paste; }