Skip to content

Commit

Permalink
bugy#258 added a button to copy script output to a clipboard
Browse files Browse the repository at this point in the history
  • Loading branch information
bugy authored and antonellocaroli committed Aug 1, 2020
1 parent 122bb14 commit f9013c0
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 2 deletions.
72 changes: 71 additions & 1 deletion web-src/js/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export function hasClass(element, clazz) {
if (isNull(element.classList)) {
return false;
}

return element.classList.contains(clazz);
}

Expand Down Expand Up @@ -541,4 +541,74 @@ export function toMap(elements, keyExtractor, valueExtractor) {

export function deepCloneObject(obj) {
return JSON.parse(JSON.stringify(obj));
}

// Reads the text, which user sees
// Default innerText doesn't work (on Chrome/Firefox), because <br/> is treated as double new-line
// So the idea is just select text and copy it
function readUserVisibleText(elem) {
const selection = window.getSelection();
const range = document.createRange();
range.selectNodeContents(elem);
selection.removeAllRanges();
selection.addRange(range);
const selectionString = selection.toString();
selection.removeAllRanges();
return selectionString;
}

export function copyToClipboard(elem) {
// if new Clipboard API is available, just use it
if (navigator.clipboard) {
const selectionString = readUserVisibleText(elem);
navigator.clipboard.writeText(selectionString);
return;
}

const targetId = '_hiddenCopyText_';
const isInput = elem.tagName === 'INPUT' || elem.tagName === 'TEXTAREA';

let origSelectionStart, origSelectionEnd;
let target;
if (isInput) {
target = elem;
origSelectionStart = elem.selectionStart;
origSelectionEnd = elem.selectionEnd;
} else {
target = document.getElementById(targetId);
if (!target) {
target = document.createElement('textarea');
target.style.position = 'absolute';
target.style.left = '9999px';
target.style.top = '0';
target.id = targetId;
document.body.appendChild(target);
}
target.value = readUserVisibleText(elem);
}

const currentFocus = document.activeElement;
target.focus();
target.setSelectionRange(0, target.value.length);

try {
document.execCommand('copy');
} catch (e) {
console.error(e);
}

if (currentFocus && typeof currentFocus.focus === 'function') {
currentFocus.focus();
}

if (isInput) {
elem.setSelectionRange(origSelectionStart, origSelectionEnd);
} else {
target.textContent = '';
}

document.body.removeChild(target);

// for mobiles, we need to scroll down to make URL bar disappear
elem.scrollIntoView();
}
19 changes: 18 additions & 1 deletion web-src/js/components/log_panel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@
'shadow-bottom': atTop && !atBottom,
'shadow-top-bottom': !atTop && !atBottom}">
</div>
<a class="copy-text-button btn-flat waves-effect btn-floating" @click="copyLogToClipboard">
<i class="material-icons">content_copy</i>
</a>
</div>
</template>

<script>
import {isNull} from '../common';
import {copyToClipboard, isNull} from '../common';
import {TerminalModel} from './terminal/terminal_model';
import {Terminal} from './terminal/terminal_view';
Expand Down Expand Up @@ -115,6 +118,10 @@
setInlineImage: function (output_path, download_url) {
this.terminalModel.setInlineImage(output_path, download_url);
},
copyLogToClipboard: function () {
copyToClipboard(this.terminal.element);
}
},
Expand Down Expand Up @@ -174,4 +181,14 @@
max-width: 100%
}
.log-panel .copy-text-button {
position: absolute;
right: 12px;
bottom: 8px;
}
.log-panel .copy-text-button i {
color: #00000030;
}
</style>

0 comments on commit f9013c0

Please sign in to comment.