Changeset View
Changeset View
Standalone View
Standalone View
webroot/rsrc/js/core/behavior-oncopy.js
| Show First 20 Lines • Show All 180 Lines • ▼ Show 20 Lines | if (!copy_mode) { | ||||
| return; | return; | ||||
| } | } | ||||
| var ranges = get_selected_ranges(); | var ranges = get_selected_ranges(); | ||||
| if (!ranges.length) { | if (!ranges.length) { | ||||
| return; | return; | ||||
| } | } | ||||
| var text_nodes = []; | var text = []; | ||||
| for (var ii = 0; ii < ranges.length; ii++) { | for (var ii = 0; ii < ranges.length; ii++) { | ||||
| var range = ranges[ii]; | var range = ranges[ii]; | ||||
| var fragment = range.cloneContents(); | var fragment = range.cloneContents(); | ||||
| if (!fragment.children.length) { | if (!fragment.childNodes.length) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| // In Chrome and Firefox, because we've already applied "user-select" | // In Chrome and Firefox, because we've already applied "user-select" | ||||
| // CSS to everything we don't intend to copy, the text in the selection | // CSS to everything we don't intend to copy, the text in the selection | ||||
| // range is correct, and the range will include only the correct text | // range is correct, and the range will include only the correct text | ||||
| // nodes. | // nodes. | ||||
| Show All 9 Lines | for (var ii = 0; ii < ranges.length; ii++) { | ||||
| // The nodes we get here can also start and end more or less anywhere. | // The nodes we get here can also start and end more or less anywhere. | ||||
| // One saving grace is that we use "content: attr(data-n);" to render | // One saving grace is that we use "content: attr(data-n);" to render | ||||
| // the line numbers and no browsers copy this content, so we don't have | // the line numbers and no browsers copy this content, so we don't have | ||||
| // to worry about figuring out when text is line numbers. | // to worry about figuring out when text is line numbers. | ||||
| for (var jj = 0; jj < fragment.childNodes.length; jj++) { | for (var jj = 0; jj < fragment.childNodes.length; jj++) { | ||||
| var node = fragment.childNodes[jj]; | var node = fragment.childNodes[jj]; | ||||
| text.push(extract_text(node)); | |||||
| } | |||||
| } | |||||
| text = flatten_list(text); | |||||
| text = text.join(''); | |||||
| var rawEvent = e.getRawEvent(); | |||||
| var data; | |||||
| if ('clipboardData' in rawEvent) { | |||||
| data = rawEvent.clipboardData; | |||||
| } else { | |||||
| data = window.clipboardData; | |||||
| } | |||||
| data.setData('Text', text); | |||||
| e.prevent(); | |||||
| } | |||||
| function extract_text(node) { | |||||
| var ii; | |||||
| var text = []; | |||||
| if (JX.DOM.isType(node, 'tr')) { | if (JX.DOM.isType(node, 'tr')) { | ||||
| // This is an inline comment row, so we never want to copy any | // This is an inline comment row, so we never want to copy any | ||||
| // content inside of it. | // content inside of it. | ||||
| if (JX.Stratcom.hasSigil(node, 'inline-row')) { | if (JX.Stratcom.hasSigil(node, 'inline-row')) { | ||||
| continue; | return null; | ||||
| } | |||||
| // This is a "Show More Context" row, so we never want to copy any | |||||
| // of the content inside. | |||||
| if (JX.Stratcom.hasSigil(node, 'context-target')) { | |||||
| return null; | |||||
| } | } | ||||
| // Assume anything else is a source code row. Keep only "<td>" cells | // Assume anything else is a source code row. Keep only "<td>" cells | ||||
| // with the correct mode. | // with the correct mode. | ||||
| for (var kk = 0; kk < node.childNodes.length; kk++) { | for (ii = 0; ii < node.childNodes.length; ii++) { | ||||
| var child = node.childNodes[kk]; | text.push(extract_text(node.childNodes[ii])); | ||||
| } | |||||
| var node_mode = child.getAttribute('data-copy-mode'); | return text; | ||||
| if (node_mode === copy_mode) { | |||||
| text_nodes.push(child); | |||||
| } | } | ||||
| if (JX.DOM.isType(node, 'td')) { | |||||
| var node_mode = node.getAttribute('data-copy-mode'); | |||||
| if (node_mode !== copy_mode) { | |||||
| return; | |||||
| } | } | ||||
| } else { | |||||
| // For anything else, assume this is a text fragment or part of | // Otherwise, fall through and extract this node's text normally. | ||||
| // a table cell or something and should be included in the selection | |||||
| // range. | |||||
| text_nodes.push(node); | |||||
| } | } | ||||
| if (!node.childNodes || !node.childNodes.length) { | |||||
| return node.textContent; | |||||
| } | } | ||||
| var text = []; | for (ii = 0; ii < node.childNodes.length; ii++) { | ||||
| for (ii = 0; ii < text_nodes.length; ii++) { | var child = node.childNodes[ii]; | ||||
| text.push(text_nodes[ii].textContent); | text.push(extract_text(child)); | ||||
| } | } | ||||
| text = text.join(''); | |||||
| var rawEvent = e.getRawEvent(); | return text; | ||||
| var data; | |||||
| if ('clipboardData' in rawEvent) { | |||||
| data = rawEvent.clipboardData; | |||||
| } else { | |||||
| data = window.clipboardData; | |||||
| } | } | ||||
| data.setData('Text', text); | |||||
| e.prevent(); | function flatten_list(list) { | ||||
| var stack = [list]; | |||||
| var result = []; | |||||
| while (stack.length) { | |||||
| var next = stack.pop(); | |||||
| if (JX.isArray(next)) { | |||||
| for (var ii = 0; ii < next.length; ii++) { | |||||
| stack.push(next[ii]); | |||||
| } | } | ||||
| } else if (next === null) { | |||||
| continue; | |||||
| } else if (next === undefined) { | |||||
| continue; | |||||
| } else { | |||||
| result.push(next); | |||||
| } | |||||
| } | |||||
| return result.reverse(); | |||||
| } | } | ||||
| JX.enableDispatch(document.body, 'copy'); | JX.enableDispatch(document.body, 'copy'); | ||||
| JX.enableDispatch(window, 'selectionchange'); | JX.enableDispatch(window, 'selectionchange'); | ||||
| JX.Stratcom.listen('mousedown', null, onstartselect); | JX.Stratcom.listen('mousedown', null, onstartselect); | ||||
| JX.Stratcom.listen('selectionchange', null, onchangeselect); | JX.Stratcom.listen('selectionchange', null, onchangeselect); | ||||
| JX.Stratcom.listen('mouseup', null, onendselect); | JX.Stratcom.listen('mouseup', null, onendselect); | ||||
| JX.Stratcom.listen('copy', null, oncopy); | JX.Stratcom.listen('copy', null, oncopy); | ||||
| }); | }); | ||||