Как я могу использовать JavaScript для выделения текста в предварительном узле / блоке? - PullRequest
4 голосов
/ 05 ноября 2011

Я понимаю причины безопасности, стоящие за запретом JS копировать произвольный текст в буфер обмена, но есть ли способ, с помощью которого нажатие кнопки позволяет выделить текст в предварительном узле, аналогично тому, как функция select () работает на входе?

Я не ищу плагин jQuery, который копирует в буфер обмена.Я просто хочу, чтобы текст в предварительном блоке был выделен, чтобы пользователь мог ctrl-c скопировать.

Кажется, я нахожу присед.

Ответы [ 6 ]

6 голосов
/ 24 апреля 2014

Это то, что вам нужно:

var clip = function(el) {
  var range = document.createRange();
  range.selectNodeContents(el);
  var sel = window.getSelection();
  sel.removeAllRanges();
  sel.addRange(range);
};

И HTML:

<code><pre onclick="clip(this);" id="copy_paste">

Или, если вы хотите программно сделать это:

clip(document.getElementById("copy_paste"));

Или в jquery:

clip($("#copy_paste")[0]);

Вы не можете передать элемент jquery clip () в качестве аргумента el.Это даст «TypeError: Аргумент 1 Range.selectNodeContents не реализует интерфейсный узел».

4 голосов
/ 06 ноября 2011

Это не так уж сложно. Вам нужны отдельные ветки для IE <9 и всех других браузеров. Вот функция выбора содержимого элемента: </p>

Демо: http://jsfiddle.net/yQa2w/

Код:

function selectElementContents(el) {
    if (window.getSelection && document.createRange) {
        // IE 9 and non-IE
        var range = document.createRange();
        range.selectNodeContents(el);
        var sel = window.getSelection();
        sel.removeAllRanges();
        sel.addRange(range);
    } else if (document.body.createTextRange) {
        // IE < 9
        var textRange = document.body.createTextRange();
        textRange.moveToElementText(el);
        textRange.select();
    }
}
2 голосов
/ 05 ноября 2011

Возможно, вы могли бы изменить тег pre на тег textarea, когда пользователь щелкнет по нему:

jsFiddle: http://jsfiddle.net/WzBQf/

<code><button id="btnSelect">Select!</button>
<button id="btnDeselect">Deselect!</button>
<hr />
<div id="text">
    <pre id="txt1">Test
1 голос
/ 05 ноября 2011

взгляните на

https://developer.mozilla.org/it/DOM/window.getSelection

он не совместим со всеми браузерами мэров, первая реализация IE в версии 9

но в более старых IE есть несколько альтернативных API в document.selection, которые кажутся эквивалентными

http://msdn.microsoft.com/en-us/library/ms535869%28v=vs.85%29.aspx

удачи!

0 голосов
/ 06 ноября 2011

ОК - это то, что я делаю, основываясь на предложении jsFiddle, и оно работает. Единственная проблема заключается в том, что у меня нет Windows, а в IE, где у меня есть копия в буфер обмена, очевидно, разрывы строк нарушены, но это не тот вопрос (и я подозреваю, что .replace () может это исправить - мне просто нужен доступ к Windows, чтобы играть с IE):

function lineBreakCount(str){
// http://snippets.dzone.com/posts/show/5770
/* counts \n */
try {
    return((str.match(/[^\n]*\n[^\n]*/gi).length));
    } catch(e) {
    return 0;
    }
}

function nodeToCopy($node) {
// For Code Snippets - [AW]
$pre = $node.find('pre:first');
var string = $pre.text();
if (window.clipboardData && clipboardData.setData) {
    clipboardData.setData('text', string);
    } else {
    var n = 1 + lineBreakCount(string);
    $pre.attr('class','nodisplay');
    $pre.after('<textarea readonly="readonly" rows="' + n + '" class="dbg-copycode">' + string.replace(/</g,'&lt;').replace(/>/,'&gt;') + '</textarea>');
    $node.find('textarea:first').focus();
    $node.find('textarea:first').select();
    $node.find('div:last').find('button').replaceWith('<button class="dbg-copycode" type="button" title="Restore syntax highlight">Restore</button>');
    $node.find('div:last').find('button').click(function() {restorePreFromText($(this).parent().parent())});
    }
}

function restorePreFromText($node) {
// For Code Snippets - [AW]
$node.find('pre:first').removeAttr('class');
$node.find('textarea').remove();
$node.find('div:last').find('button').replaceWith('<button class="dbg-copycode" type="button" title="Select code example for copying">Select Code</button>');
$node.find('div:last').find('button').click(function() {nodeToCopy($(this).parent().parent())});
}

$(document).ready(function() {
// For Code Snippets - [AW]
var copybutton = 'Select Code';
var copytitle  = 'Select code example for copying';
if (window.clipboardData && clipboardData.setData) {
    copybutton = 'Copy Code';
    copytitle  = 'Copy code example to clipboard';
    }
$('pre[data-code]').after('<div class="dbg-rbutton"><button class="dbg-copycode" type="button" title="' + copytitle + '">' + copybutton + '</button></div>');
$('.dbg-copycode').click(function() {nodeToCopy($(this).parent().parent())});
});

Причина, по которой я не использую .hide (), где скрываю предварительный блок, заключается в том, что .hide () добавляет атрибут стиля, который запрещен политикой Mozilla CSP, которую использует сервер, поэтому я должен установить атрибут класса вместо этого.

0 голосов
/ 05 ноября 2011

Насколько я знаю, нельзя выбирать текст за пределами <input> или <textarea>.Кстати, зачем тебе это?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...