【问题标题】:Mimic Ctrl+A with JavaScript用 JavaScript 模拟 Ctrl+A
【发布时间】:2023-03-31 07:10:02
【问题描述】:

我想以编程方式选择页面上的所有文本,其结果与按下组合键 Ctrl+A 完全相同.

使用document.getSelection().selectAllChildren(body) 的问题在于,选择还将包括用户无法选择的文本节点,即<script> </script> 或在CSS 中定义了user-select:none 的节点:

<div style="-moz-user-select:none">将被选中</div>

在选择对象上有一个方法modify,可以像这样使用: selection.modify("extend", "forward", "documentboundary"); 将选择从文档的开头扩展到其结尾,这将忽略任何脚本或样式元素的内容和带有-moz-user-select:none 的元素 - 不幸的是,Firefox 不允许将documentboundary 作为 3. 参数和word 并没有多大帮助。

有没有快速的方法来完成这个? 只需要在 Firefox 中工作。

编辑(不太好的解决方案):选择第一个文本节点,然后重复使用selection.modify('extend', 'forward', 'line'),而selection.focusNode 不等于最后一个文本节点 - 但取决于长度这需要几秒钟的时间!

编辑: selection.selectAllChildren 将在 Chrome 中按预期工作,其中带有 user-select:none 的文本元素将不会被选择 - 不幸的是,FF 中有不同的行为。

编辑:这不是 this post 的重复,因为我既不处理 contenteditable 元素,也不关心它们;)

【问题讨论】:

  • 我没有 ff 要测试,这就是为什么这只是一个评论,而不是一个答案:基本上试试这个:hide-select-show。详细说明: 1. 为不可选择的元素使用一个类 2. $('unselectable').hide() 3. document.getSelection().selectAllChildren($('body').get(0) 4. $('unselectable ').show()
  • @ZPiDER 谢谢,但我不是 HTML+CSS 代码的作者(它用于 FF 扩展)。
  • 如果您没有使用类的选项,请使用过滤: $('*').filter(function() { return $(this).css('user-select') == 'none' }).hide() - 当然,您需要存储之前隐藏了哪些元素,因为您不想显示它们。
  • 好主意,但我在没有 jQuery 的情况下工作,如果其父节点之一使用 window.getComputedStyle(el).getPropertyValue('-moz-user-select') 检查每个文本节点是否有 -moz-user-select:none(另请参阅我在 Jake 的回答下的评论)可能需要更多时间使用selection.modify('extend', 'forward', 'line') 在从第一个文本节点到最后一个文本节点的循环中手动选择所有用户可选择的文本

标签: javascript selection textselection getselection


【解决方案1】:

请注意,我在这里使用了 jquery,尽管它是用 Javascript 询问的 - 我不确定这是否正是您要寻找的,但也许它可以为您指明正确的方向?如果您需要解释,请告诉我。

function slct(el) {
		    var d = document;
		    var t = d.getElementById(el);
        var selection;
		    var range;
    
		    if(d.body.createTextRange) {
		        range = d.body.createTextRange();
		        range.moveToElementText(t);
		        range.select();
		    } else if(window.getSelection) {
		        selection = window.getSelection();        
		        range = d.createRange();
		        range.selectNodeContents(t);
		        selection.removeAllRanges();
		        selection.addRange(range);
		    }
		}

		$(function() {
		    $('#myButton').click(function() {
		        slct('content');
		    });
		});
<script
		src="https://code.jquery.com/jquery-3.2.1.min.js"
		integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
		crossorigin="anonymous">
	</script>

<div id="content">
		<h4>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quam  necessitatibus assumenda nam obcaecati unde libero aspernatur neque ad vel enim tempora, qui consectetur corporis reiciendis, eum dolorum voluptas soluta voluptatibus!</h1>
		<h5>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eveniet asperiores, iste distinctio sint quidem ea aut voluptatem earum error similique, repudiandae consectetur labore esse. Aut quas repudiandae accusamus non iusto.</h2>
		<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. In rem blanditiis delectus placeat officia, iusto qui! Dicta laboriosam ea exercitationem, molestiae officiis! Asperiores quibusdam laborum in optio eum, similique vitae.</p>
</div>

<button id="myButton">select stuff</button>

【讨论】:

  • 感谢您的回答,但不幸的是它无济于事:使用selection.selectAllChildren(t) 可以更轻松地完成您在那里所做的事情,但无论哪种方式,都将选择带有user-select:none (CSS) 的元素的文本内容在 Firefox 中也是如此(在 Chrome 中不是这样,但需要它在 FF 中工作)
  • @user1521685 只是在这里吐口水,但是如果您将要赋予 user-select:none 的元素赋予类名,然后将 if 语句包装在 if(!$(t).hasClass( 'no-select')){ ... } 作为一种 FF 后备?
  • 我不是 HTML 代码的作者(它用于 FF 扩展)。在我的例子中,参数t 是body 元素,而-moz-user-select:none 很难用JS 捕捉到,因为使用CSS,你可以为具有-moz-text、@987654328 等一系列值的子元素反转它@ 等,因此我不仅要检查页面的每个元素,还要使用 window.getComputedStyle(el).getPropertyValue(x) 其中 x 可以是这些反转值之一
【解决方案2】:

我认为您可以为此使用document.execCommand('selectAll', false, null)

您可以在此here 上找到更多文档。

【讨论】:

  • 为此,您必须先切换文档的designMode,它还将选择所有文本内容——包括用户无法选择的文本(请参阅:-moz-user-select:none)。因此这种方法比selection.selectAllChildren(document.body)没有优势
  • 对不起,我困了,没有看到你的帖子。我不需要Point´s ......我在这里写只是为了好玩......
  • @Frank:嘿,抱歉,不想太苛刻-一切都好-周末愉快,感谢您的帮助! (在写最后一条评论时也很困;)
【解决方案3】:

在我看来,最有效的方法是将您想要选择的内容移动到它自己的可选 div 中,然后选择其中的 selectAllChildren。我在谷歌搜索、几个堆栈溢出问题和一些随机站点上试过这个。在每种情况下,结果都是即时的,并且完全相同具有ctrl+A

function selectAll() {
  var sel = window.getSelection();
  var body = document.querySelector("body");
  // Place the children in an array so that we can use the filter method
  var children = Array.prototype.slice.call(body.children);

  // Create the selectable div
  var selectable = document.createElement("div");

  // Style the selectable div so that it doesn't break the flow of a website.

  selectable.style.width = '100%';
  selectable.style.height = '100%';
  selectable.margin = 0;
  selectable.padding = 0;
  selectable.position = 'absolute';

  // Add the selectable element to the body
  body.appendChild(selectable);

  // Filter the children so that we only move what we want to select.
  children = children.filter(function(e) {
    var s = getComputedStyle(e);
    return s.getPropertyValue('user-select') != 'none' && e.tagName != 'SCRIPT'
  });
  // Add each child to the selectable div
  for (var i = 0; i < children.length; i++) {
        selectable.appendChild(children[i]);
  }

  // Select the children of the selectable div
  sel.selectAllChildren(selectable);

}

selectAll();

【讨论】:

  • 我不是 HTML+CSS 代码的作者(它是用于 FF 扩展的)。
  • 我已经更新了答案,对我来说似乎很有效
  • 就我而言,这并没有多大帮助,因为我认为我的帖子中的“不太好的解决方案”比遍历每个元素要快得多,然后将用户可选那些进入一个div等等。但我会选择你的答案作为获胜者,因为它充分回答了这个问题。谢谢
猜你喜欢
  • 2013-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-08
  • 1970-01-01
  • 1970-01-01
  • 2013-07-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多