尝试在单击按钮时从两个不同的文本区域复制文本
Posted
技术标签:
【中文标题】尝试在单击按钮时从两个不同的文本区域复制文本【英文标题】:Trying to copy text from two different text areas on button click 【发布时间】:2021-08-17 01:58:50 【问题描述】:我是 JS 新手,所以如果这是一个简单的答案,我提前道歉。
当按下按钮时,我试图从两个不同的文本区域框中选择和复制文本。我只能弄清楚如何使用 getElementbyID 一次复制一个文本区域。我试过使用 querySelectorAll("").select();没有运气。我错过了什么?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Test</title>
</head>
<body class="bg-gray-100">
<div class="container font-sans bg-white mx-auto px-4 py-4 rounded shadow-md">
<form action="" method="" class="form grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4">
<div class="text-lg w-full underline font-bold col-span-1 sm:col-span-2 md:col-span-3 lg:col-span-4">
<h1>Notification Information</h1>
</div>
<div class="inline-flex w-full text-lg underline font-bold mt-4 col-span-1 sm:col-span-2 md:col-span-3 lg:col-span-4">
<h1 class="mx-2">Media Script</h1>
<div><button type="button" id="plusScript" onclick="addText()" class="text-sm border border-transpartent border-2 border-blue-300 bg-trasparent px-1 p-1 rounded shadow text-blue-400 mx-2 font-bold">New Script</button></div>
<div><button type="button" onclick="copyAll()" class="text-sm border border-transpartent border-2 border-blue-300 bg-trasparent px-1 p-1 rounded shadow text-blue-400 mx-2 font-bold">Copy Script</button></div>
</div>
<div class="Media Script Header space-y-4">
<label for="Media Script Header"></label>
<textarea name="Media Script" rows="1" cols="70" id="script" placeholder="Media Script Header" class="copyScript resize-none text-sm col-span-1 sm:col-span-2 md:col-span-3 focus:outline-none focus:ring-2 focus:ring-blue-300 focus:border-transparent rounded shadow-sm focus:ring-opacity-75 mx-2">
</textarea>
<label for="Media Script"></label>
<textarea name="Media Script" rows="5" cols="70" id="scriptNarrative" placeholder="Media Script Narrative" class="copyScript no-wrap resize-none text-sm col-span-1 sm:col-span-2 md:col-span-3 focus:outline-none focus:ring-2 focus:ring-blue-300 focus:border-transparent rounded shadow-sm focus:ring-opacity-75 mx-2">
</textarea>
</div>
</div>
</body>
function copyAll()
document.querySelectorAll("copyScript").select()
document.execCommand("copy");
【问题讨论】:
您需要复制框 1 中的所有文本以替换框 2 文本吗? 您的表单元素应该有唯一的名称 - 没有空格或特殊字符。你有“非法”的文本区域名称。 @BeshambherChaukhwan 我需要将文本从两个文本区域复制到剪贴板。 您知道一次只能将一个 textarea 文本复制到剪贴板 【参考方案1】:当您尝试使用 querySelectorAll 按类选择时,您需要添加 '.'在类名之前。
在你的情况下:
document.querySelectorAll(".copyScript")
请注意,您得到的是一个数组而不是单个元素
【讨论】:
【参考方案2】:我不确定我是否理解正确,但是 querySelectorAll 创建“类似”类的同名数组,因此您可以通过输入位置来访问它,如果您有两个以上的文本区域,则可以使用循环
function copyAll()
let x;
x =document.querySelectorAll(".copyScript")
console.log( x[0].value )
console.log( x[1].value )
【讨论】:
【参考方案3】:下面是一种方法,尽管这很可能是不完美的,因为我不太确定您想对获得的结果做什么。
// I personally don't like using inline event-handlers, though that's obviously the form
// that frameworks such as React and Angular take; if you're writing the
// script manually then I prefer to use bind event-handlers in the javascript:
const userFunctions =
// these function-names are retrieved from the elements, so
// it's still technically obtrusive JavaScript but I don't
// quite know how you're working, so I came to this compromise.
// Here the event Object is passed in to the functions (declared
// using Arrow function syntax):
// this specific function was in your posted code, without any detail
// so I left it, and just logged my lack of knowledge of your intent
// to the console:
addText: (e) => console.log("Not a clue, unfortunately"),
// this function-name is - again - found in the HTML custom data-*
// attribute, and again the event Object is passed in:
copyAll: (e) =>
// we retrieve the element to which the event-handler was bound:
const target = e.currentTarget,
// we retrieve the <form> associated with that element:
form = target.form,
// we search within that <form> using Element.querySelectorAll()
// to recover the textarea elements, passing that to an Array-
// literal along with the spread syntax which forms an Array from
// the iterable NodeList from Element.querySelectorAll():
textareas = [...form.querySelectorAll('textarea')],
// we then iterate over that Array, using Array.prototype.map()
// which returns a new Array based on the contents of the
// Array to which it was chained:
contents = textareas.map(
// here we return a two-part Array, composed of the
// current element's id as the first entry, and
// the value of that element as the second entry
// (having trimmed the leading/trailing white-space):
(elem) => [elem.id,elem.value.trim()]
);
// we then use Object.prototype.fromEntries() to take that
// Array and from its contents create an Object, from each
// two-part Array the first array-element is the Object
// property key, and the second is the property-value; this
// Object is returned to the calling context (though I'm unsure
// as to what your specific intent is, but this should give
// you enough information to do as you wish):
return Object.fromEntries(contents);
// this returns an Object of the form:
//
// <textarea id>: <script header contents>
// <textarea id>: <script narrative contents>
//
,
// this function is the event-handler for the button-click events;
// again using Arrow syntax, passing in the event Object:
ascribeFunction = (e) =>
// here we use bracket-notation to call the function that
// ultimately handles the event:
userFunctions[
// here we retrieve the event-target (e.target),
// we use the HTMLOrForeignElement.dataset API to
// access the value of the 'data-function'
// attribute (getAttribute('data-function') would
// also work, and then the event Object is
// passed into the function:
e.target.dataset.function](e);
;
// here we use document.querySelectorAll(), along with NodeList.prototype.forEach
// to iterate over all <button> elements that have a 'data-function' attribute:
document.querySelectorAll('button[data-function]').forEach(
// we pass the current element into the Arrow function, and
// bind the ascribeFunction() as the 'click' event-handler:
(elem) => elem.addEventListener('click', ascribeFunction)
);
/*
None of the CSS is necessary, adjust to your own taste and disregard
any, or all, of it; I wrote this because I think it looks somewhat
useable, but adjust to taste. This first part is simply a simple
CSS reset to ensure all elements are appropriately sized from the
same baseline:
*/
*,
::before,
::after
box-sizing: border-box;
font-family: "Roboto", "Ubuntu", Calibri, Helvetica, sans-serif;
font-size: 1rem;
line-height: 1.5;
margin: 0;
padding: 0;
form
width: 80vw;
margin: 0 auto;
fieldset
border: 0 none transparent;
margin-top: 1em;
display: flex;
justify-content: start;
gap: 0.5em 2em;
padding-top: 0.5em;
#scriptDetails
flex-direction: column;
row-gap: 0;
legend
border-bottom: 1px solid currentColor;
font-size: 120%;
width: 100%;
legend::after
content: ': ';
label
margin-top: 0.5em;
label::after
content: ':';
textarea
outline-offset: 0;
outline: 3px solid transparent;
transition: all 0.5s ease-in-out;
textarea:is(:focus, :active)
outline-offset: 0.1em;
outline: 5px solid #f909;
#script
height: 1.5rem;
resize: none;
#scriptNarrative
height: 15rem;
<div>
<form action="#">
<div>
<h1>Notification Information</h1>
</div>
<!-- I've made a few changes to your HTML, stripping out the redundant
classes (since no CSS was included with your code), I've used
fieldsets to group related form-elements together and used a
<legend> element to 'label' each of those groups of elements;
incidentally no page should have more than one <h1>, if more
headings must be used then they should be <h2>,<h3> and so on -->
<fieldset id="controls">
<legend>Media Script</legend>
<div>
<button type="button" id="plusScript" data-function="addText">New Script</button>
</div>
<div>
<button type="button" data-function="copyAll">Copy Script</button>
</div>
</fieldset>
<fieldset id="scriptDetails">
<legend>Scripts</legend>
<!-- an empty <label> element serves no purpose at all, so populate it
with text to provide relevant instruction to the user, and to increase
accessibility (particularly in the case of check-box and radio <input>
elements because it increases the touch area for users with touch
screens), the "for" attribute must be the the same as the "id" of the
element to which it's associated (unless that element is nested within
the <label> in which case the association is implicit), otherwise
the <label> is not associated with that element and serves no purpose
except for littering your (unnecessarily inaccessible) HTML -->
<label for="script">Media Script Header</label>
<textarea name="Media Script" id="script" placeholder="Media Script Header">
</textarea>
<label for="scriptNarrative">Media Script</label>
<textarea name="Media Script" id="scriptNarrative" placeholder="Media Script Narrative">
</textarea>
</fieldset>
</form>
</div>
JS Fiddle demo.
参考资料:
CSS::active
。
border
。
box-sizing
。
content
。
display
。
font-family
。
flex-direction
。
:focus
。
font-size
。
gap
。
height
。
:is()
。
line-height
。
margin
。
outline
。
outline-offset
。
padding
.
resize
。
row-gap
。
transition
。
width
。
HTML:
<button>
。
data-*
attributes.
<fieldset>
。
<form>
.
<label>
.
<legend>
.
<textarea>
。
JavaScript:
Array literals。
Array.prototype.map()
。
Arrow functions。
Bracket notation。
document.querySelectorAll()
。
Element.querySelectorAll()
.
Event.currentTarget
.
EventTarget.addEventListener()
。
HTMLOrForeignElement.dataset
API.
NodeList.prototype.forEach()
。
Object.fromEntries()
。
Spread syntax。
String.prototype.trim()
。
【讨论】:
以上是关于尝试在单击按钮时从两个不同的文本区域复制文本的主要内容,如果未能解决你的问题,请参考以下文章
Javascript / jQuery 获取我正在输入的文本区域的 id [重复]