Пользовательская функция выбора с копией в буфер обмена JS

В текущем коде добавлена ​​кнопка для быстрого выбора кода в теге <pre>. То, что я хочу добавить, - это возможность скопировать этот контент в буфер обмена и изменить текст кнопки на "скопированный".

Как я могу достичь этого, изменив действующий рабочий код ниже? Я бы не прочь использовать clipboard.js, jQuery биты или только родную поддержку JS, поскольку она была введена с Chrome 43. Я просто не знаю, как продолжить здесь, добавляя то, что мне нужно.

function selectPre(e) {
    if (window.getSelection) {
        var s = window.getSelection();
        if (s.setBaseAndExtent) {
            s.setBaseAndExtent(e, 0, e, e.innerText.length - 1);
        }
        else {
            var r = document.createRange();
            r.setStart(e.firstChild, 0);
            r.setEnd(e.lastChild, e.lastChild.textContent.length);
            s.removeAllRanges();
            s.addRange(r);
        }
    }
    else if (document.getSelection) {
        var s = document.getSelection();
        var r = document.createRange();
        r.selectNodeContents(e);
        s.removeAllRanges();
        s.addRange(r);
    }
    else if (document.selection) {
        var r = document.body.createTextRange();
        r.moveToElementText(e);
        r.select();
    }
}
var diff = document.getElementById('diff_table').getElementsByTagName('tr');
var difflen = diff.length;
for(i=0; i<difflen; i++) {
    var newdiff = diff[i].childNodes[1];
    if (newdiff.className && (newdiff.className == 'added' || newdiff.className == 'modified')) {
        newdiff.className += ' diff-select';
        newdiff.innerHTML = '<div class="btnbox"><button class="btn btn-default btn-xs" onclick="selectPre(this.parentNode.nextSibling)">Select</button></div>' + newdiff.innerHTML;
    }
} 

Ответ 1

По какой-то причине ваша функция selectPre не найдена при воспроизведении дела на jsfiddle. Jsfiddle может избавиться от того, что он считает мертвым кодом, или переименовать его ради минимизации.

Но если это то, что нужно выбрать содержимое тега <pre>, clipboard.js библиотека (которую вы готовы использовать ) может сделать это уже самостоятельно.

Итак, вы в конечном итоге требуете правильной настройки объекта Clipboard. С помощью этого:

new Clipboard('.btn', {
    // The targeting to the correct content is done here.
    target: function(trigger) {
        return trigger.parentNode.nextSibling;
    }
    // clipboard.js will take the entire inner content of the <pre>,
    // I think this is what you are trying to do in your "selectPre"
    // function, but I am not sure.
});

он имитирует ваш selectPre(this.parentNode.nextSibling), который вам больше не нужно прикреплять к атрибуту onclick вашей кнопки.

Демо: http://jsfiddle.net/5k60nm1y/

Обратите внимание, что я должен был угадать, какова ваша структура таблицы. Это может отличаться от вашей фактической таблицы, поэтому вам может потребоваться тонкая настройка того, как newdiff присваивается правильной ячейке.

Если вам нужно что-то более сложное, чем только внутреннее содержимое тега <pre>, вы можете точно настроить поведение объекта Clipboard, передав пользовательскую функцию в свойство text параметра конструктора Clipboard, вместо этого использования свойства target. Проверьте домашнюю страницу буфера обмена, это совершенно понятно.

Как уже упоминалось Zac, вы бы упростили задачу людей (и вы, вероятно, получили бы решение намного быстрее), если бы вы могли поделиться своей таблицей HTML. Мне не нужно было угадывать и создавать поддельные. Кроме того, код, который я бы предоставил вам, был бы непосредственно применим к вашей реальной таблице, тогда как теперь он может по-прежнему нуждаться в настройке. Надеюсь, я догадался, что это правильно, и мой стол близок к твоему.

Ответ 2

Я применил часть кода из этого ресурса, Как скопировать в буфер обмена в JavaScript?, в ваш код, чтобы вы могли легко увидеть, как это можно сделать сделайте.

Я также изменил ваш onclick="selectPre(...)" на этот onclick="selectPre(this)" и добавил пару переменных в функцию "selectPre".

Здесь также демонстрация скрипта

function selectPre(b) {
    var s;                               // added - selection variable
    var e = b.parentNode.nextSibling;    // added - parent sibling element
    if (window.getSelection) {
        var s = window.getSelection();
        if (s.setBaseAndExtent) {
            s.setBaseAndExtent(e, 0, e, e.innerText.length - 1);
        }
        else {
            var r = document.createRange();
            r.setStart(e.firstChild, 0);
            r.setEnd(e.lastChild, e.lastChild.textContent.length);
            s.removeAllRanges();
            s.addRange(r);
        }
    }
    else if (document.getSelection) {
        var s = document.getSelection();
        var r = document.createRange();
        r.selectNodeContents(e);
        s.removeAllRanges();
        s.addRange(r);
    }
    else if (document.selection) {
        var s = document.body.createTextRange();
        s.moveToElementText(e);
        s.select();
    }

    // added - copy and change button text
    if (s) {
        try {
            var successful = document.execCommand('copy');
            // var msg = successful ? 'successful' : 'unsuccessful';
            // console.log('Copying text command was ' + msg);
            if (successful) {
                b.innerHTML = "Copied";
            }
        } catch (err) {
            // console.log('Oops, unable to copy');
        }
    }
}
var diff = document.getElementById('diff_table').getElementsByTagName('tr');
var difflen = diff.length;
for(i=0; i<difflen; i++) {
    var newdiff = diff[i].childNodes[1];
    if (newdiff.className && (newdiff.className == 'added' || newdiff.className == 'modified')) {
        newdiff.className += ' diff-select';

        // altered - onclick handler
        newdiff.innerHTML = '<div class="btnbox"><button class="btn btn-default btn-xs" onclick="selectPre(this)">Select</button></div>' + newdiff.innerHTML;
    }
}