我已经尝试过发布的这段代码,但我无法让它按我需要的方式工作。我可以让它创建两个字段,但我不能让它们看起来与第一个字段的格式相同。如何添加整个部分并使其看起来相同?并控制插入的活动的最大数量。
TIA-
这就是我试图使复杂化的原因
const addActivity = document.getElementById("add");
var i = 0;
const activityDiv = document.getElementById("Activity");
addActivity.addEventListener("click", function() {
i++;
const newspan = document.createElement('div');
newspan.className = "activityGroup";
const removeButton = document.createElement('button');
removeButton.addEventListener('click', function(e) {
e.target.closest(".activityGroup").remove();
});
removeButton.className = "delbtn";
removeButton.innerHTML = "X";
//
const txtfield = document.createElement('input');
const txtarea = document.createElement('textarea');
//
txtfield.id = 'activity_' + i;
txtfield.placeholder = "Activity " + i;
newspan.appendChild(txtfield);
//
newspan.appendChild(txtarea);
txtarea.id = 'activity_description_' + i;
txtarea.placeholder = "Activity Description " + i;
newspan.appendChild(removeButton);
activityDiv.appendChild(newspan);
});
.delbtn{color:red;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="Activity">
<div class="activityGroup">
<input placeHolder="Type your activity" />
<br>
<br>
<textarea rows="5" cols="50" placeHolder="Type your descvription"></textarea>
<button class="delbtn">X</button>
</div>
<!-- Remove button -->
</div>
<button id="add">Add Activity</button>
首先,问题:
我可以让它创建两个字段,但我不能让它们看起来与第一个字段的格式相同。。。
这可能是因为在原始.activityGroup
中,在<input>
和<textarea>
元素之间有许多<br>
元素,它们被错误地用于尚未插入副本的间距。
此外,原始<textarea>
的两个属性(rows="5"
和cols="50"
(从您在函数中创建的属性中被省略,更不用说换行符和其他空白了。
这可以通过简单地创建和附加其他元素来纠正:
// first, some utility functions to simplify life:
const D = document,
get = (sel, ctx = D) => ctx.querySelector(sel),
getAll = (sel, ctx = D) => [...ctx.querySelectorAll(sel)],
create = (tag, props) => Object.assign(D.createElement(tag), props),
// renamed variables for consistency between JavaScript
// and the HTML upon which it acts:
addBtn = get("#addBtn"),
activity = get("#activity"),
// creating a generator function to use as a counter;
// fundamentally this is little different from the
// original i = 0 and then incrementing in the function
// body, but the generator can't be affected by an
// accidental decrement:
iterator = function*() {
// initial value:
let count = 1;
// a deliberate infinite loop, but the
// generator function exits/pauses at
// every yield so while this is an 'infinite
// function' it doesn't cause any blocking:
while (true) {
// yields value and then increments it:
yield count++
}
},
// getting a reference to the generator function:
counter = iterator(),
remove = (e) => e.currentTarget.closest('div').remove();
addBtn.addEventListener("click", function() {
// getting the current count of all elements matching
// the selector within the document:
const currentCount = getAll('.activityGroup').length,
// retrieving the next value from the
// generator function:
i = counter.next().value;
// if the currentCount is greater than 4 (again, using
// a Yoda condition):
if (4 < currentCount) {
// exit the function:
return false;
}
// creating a new <div>:
const activityGroup = create('div', {
// assigning the class-name of 'activityGroup':
className: 'activityGroup'
}),
// creating a new <button>:
removeButton = create('button', {
// assigning the class-name of 'delBtn',
className: 'delBtn',
// and the text-content of 'X':
textContent: 'X'
}),
input = create('input', {
type: 'text',
id: `activity_${i}`,
placeholder: `Activity ${i}`
}),
textarea = create('textarea', {
id: `activity_description_${i}`,
placeholder: `Activity description ${i}`
});
// binding the remove() function as the'click' event-handler
// on the removeButton:
removeButton.addEventListener('click', remove);
// using the HTMLElement.dataset API to set the
// custom data-count attribute to the current
// value of the i variable (for use in the CSS):
activityGroup.dataset.count = i;
// using Element.append() to append multiple elements
// in one call:
activityGroup.append(input, textarea, removeButton);
activity.appendChild(activityGroup);
});
/* caching common values (useful for theming and
maintenance): */
:root {
--bg-primary: hsl(0 0% 0% / 0.3);
--columns: 2;
--fs: 16px;
--spacing: 0.5em;
}
/* a simple CSS reset to remove default
margins and padding, and to have all
elements sized in a way that includes
their padding and border-widths in the
assigned size: */
*,::before,::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-size: var(--fs);
}
#activity {
/* using CSS Grid for layout: */
display: grid;
/* setting a space - held in the custom
property - between adjacent elements: */
gap: var(--spacing);
/* creating a number of columns (equal to the value held
in the --columns property) of equal width, each of one
fraction of the remaining space) */
grid-template-columns: repeat(var(--columns), 1fr);
padding: var(--spacing);
}
.activityGroup {
/* aligning an element in the grid to the start of that
grid (alignment is on the cross-axis of the inline-
axis, the inline-axis being the writing direction
of the language of the user's browser): */
align-self: start;
border: 0.2em solid var(--bg-primary);
display: grid;
gap: inherit;
padding: var(--spacing);
}
.activityGroup::before {
background-color: var(--bg-primary);
/* setting the content of the ::before pseudo element to the
string of 'Activity ' concatenated with the attribute-value
of the data-count attribute: */
content: "Activity " attr(data-count);
display: block;
/* spanning all three grid-columns: */
grid-column: span 3;
/* applying padding to the start of the inline axis: */
padding-inline-start: var(--spacing);
/* moving the element outwards with negative margins,
to place the content against the outer edges of the
element, despite the spacing on that element: */
margin-block-start: calc(-1 * var(--spacing));
margin-inline: calc(-1 * var(--spacing));
}
input,
textarea {
grid-column: span 3;
padding: 0.5em;
}
textarea {
min-block-size: 5em;
resize: vertical;
}
.delBtn {
color: red;
grid-column: 3;
}
/* using a simple media query to modify the values of the CSS Custom
properties as required to improve the experience on different
devices: */
@media screen and (max-width: 700px) {
:root {
--columns: 1;
--fs: 18px;
}
}
<!-- we don't appear to be using jQuery, so I removed that <script> element -->
<!-- switching id and classes to use camelCase rather than
having arbitrary mixed-case format; choose a style you
prefer, but remember that consistency matters more than
the choice you make: -->
<div id="activity">
<div class="activityGroup">
<input placeHolder="Type your activity" />
<!-- removed the <br> elements, as well as the "rows" and "cols"
attributes from the <textarea>: -->
<textarea placeHolder="Type your description"></textarea>
<button class="delBtn">X</button>
</div>
<!-- Remove button -->
</div>
<!-- changed the id from "add" to "addBtn," purely for consistency
but, again, make your own choice on that: -->
<button id="addBtn">Add Activity</button>
关于你的问题:
我如何[添加]整个部分。。。控制插入的活动的最大数量[?]
控制页面上总活动/部分的数量相对容易,只需在添加新部分之前检查现有部分的数量:
const addActivity = document.getElementById("add");
var i = 0;
const activityDiv = document.getElementById("Activity");
addActivity.addEventListener("click", function() {
// using document.querySelectorAll() to retrieve a NodeList of all
// elements matching the supplied CSS selector, and then retrieving
// the length of that NodeList:
let currentCount = document.querySelectorAll('.activityGroup').length;
// using a "Yoda condition" to see if the currentCount is greater than
// 4 (this approach guards against the most likely error of an assessment,
// that of accidentally assigning a value instead of comparing); if it is:
if (4 < currentCount) {
// we exit the function here:
return false;
}
i++;
const newspan = document.createElement('div');
newspan.className = "activityGroup";
// creating a <br> element:
const br = document.createElement('br');
const removeButton = document.createElement('button');
removeButton.addEventListener('click', function(e) {
e.target.closest(".activityGroup").remove();
});
removeButton.className = "delbtn";
removeButton.innerHTML = "X";
//
const txtfield = document.createElement('input');
const txtarea = document.createElement('textarea');
//
txtfield.id = 'activity_' + i;
txtfield.placeholder = "Activity " + i;
newspan.appendChild(txtfield);
// appending a clone of the <br> element:
newspan.appendChild(br.cloneNode());
// appending the <br> element:
newspan.appendChild(br);
//
newspan.appendChild(txtarea);
txtarea.id = 'activity_description_' + i;
txtarea.placeholder = "Activity Description " + i;
// setting the rows and cols attributes:
txtarea.setAttribute('rows', 5);
txtarea.setAttribute('cols', 50);
// appending white-space (approximating what's in the HTML):
newspan.append(document.createTextNode('n '));
newspan.appendChild(removeButton);
activityDiv.appendChild(newspan);
});
.delbtn {
color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="Activity">
<div class="activityGroup">
<input placeHolder="Type your activity" />
<br>
<br>
<textarea rows="5" cols="50" placeHolder="Type your descvription"></textarea>
<button class="delbtn">X</button>
</div>
<!-- Remove button -->
</div>
<button id="add">Add Activity</button>
现在,我想通过代码本身的解释性注释来改进上面的函数如下:
const addActivity = document.getElementById("add");
var i = 0;
const activityDiv = document.getElementById("Activity");
addActivity.addEventListener("click", function() {
// using document.querySelectorAll() to retrieve a NodeList of all
// elements matching the supplied CSS selector, and then retrieving
// the length of that NodeList:
let currentCount = document.querySelectorAll('.activityGroup').length;
// using a "Yoda condition" to see if the currentCount is greater than
// 4 (this approach guards against the most likely error of an assessment,
// that of accidentally assigning a value instead of comparing); if it is:
if (4 < currentCount) {
// we exit the function here:
return false;
}
i++;
const newspan = document.createElement('div');
newspan.className = "activityGroup";
// creating a <br> element:
const br = document.createElement('br');
const removeButton = document.createElement('button');
removeButton.addEventListener('click', function(e) {
e.target.closest(".activityGroup").remove();
});
removeButton.className = "delbtn";
removeButton.innerHTML = "X";
//
const txtfield = document.createElement('input');
const txtarea = document.createElement('textarea');
//
txtfield.id = 'activity_' + i;
txtfield.placeholder = "Activity " + i;
newspan.appendChild(txtfield);
// appending a clone of the <br> element:
newspan.appendChild(br.cloneNode());
// appending the <br> element:
newspan.appendChild(br);
//
newspan.appendChild(txtarea);
txtarea.id = 'activity_description_' + i;
txtarea.placeholder = "Activity Description " + i;
// setting the rows and cols attributes:
txtarea.setAttribute('rows', 5);
txtarea.setAttribute('cols', 50);
// appending white-space (approximating what's in the HTML):
newspan.append(document.createTextNode('n '));
newspan.appendChild(removeButton);
activityDiv.appendChild(newspan);
});
.delbtn {
color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="Activity">
<div class="activityGroup">
<input placeHolder="Type your activity" />
<br>
<br>
<textarea rows="5" cols="50" placeHolder="Type your descvription"></textarea>
<button class="delbtn">X</button>
</div>
<!-- Remove button -->
</div>
<button id="add">Add Activity</button>
JS Fiddle演示。
参考文献:
- CSS:
align-self
box-sizing
- CCD_ 10
- CSS自定义属性
- CSS逻辑属性
- CCD_ 11
gap
grid-column
grid-template-columns
grid-template-rows
- CCD_ 16
margin
- CCD_ 18
margin-inline
- CCD_ 20
padding
- CCD_ 22
padding-inline
repeat()
var()
- JavaScript:
document.createElement()
document.querySelector()
- CCD_ 28
- CCD_ 29
- CCD_ 30
Element.querySelectorAll()
Element.remove()
Event.target
- CCD_ 34
- CCD_ 35
- 发电机功能
- CCD_ 36
Node.appendChild()
- CCD_ 38
- CCD_ 39
你是说"如果我有"活动1、2、3、4、5"one_answers"删除3",我希望能够获得"活动1,2,4,5">
根据我收集的信息,您想要一个添加和删除活动的按钮,但您只希望它在前一个活动不为空时工作。
在javascript中,当您处理按钮时,单击事件检查前一个活动,如果它为空,返回,如果它不为空,执行添加/删除代码。