javascript - 是否可以使用 CSS 隐藏空行?我刚开始学习 JavaScript 和 HTML5 的基础知识。我正在尝试创建一个食谱应用程序,用户可以在其中添加食谱。这些配方存储在一个数组中,并通过一个带有 for 循环的表循环。用户还可以编辑表格。主要功能之一应该是当表格的一行为空时,它会自动被删除。我尝试display: none
与 CSS 一起使用,但它不起作用。这是我的表格 CSS:
问题描述
我刚开始学习 JavaScript 和 HTML5 的基础知识。我正在尝试创建一个食谱应用程序,用户可以在其中添加食谱。这些配方存储在一个数组中,并通过一个带有 for 循环的表循环。用户还可以编辑表格。主要功能之一应该是当表格的一行为空时,它会自动被删除。我尝试display: none
与 CSS 一起使用,但它不起作用。这是我的表格 CSS:
form.addEventListener("submit", function (event) {
let titleRow = table.insertRow();
let stepsRow = table.insertRow();
let titleCell = titleRow.insertCell();
let stepsCell = stepsRow.insertCell();
titleCell.innerHTML = inputTitle.value;
stepsCell.innerHTML = inputSteps.value;
titleCell.contentEditable = true;
stepsCell.contentEditable = true;
inputTitle.value = inputTitle.defaultValue;
inputSteps.value = inputSteps.defaultValue;
}, false);
td: empty {
display: none;
}
tr: empty {
display: none;
}
<form id="form">
<label>Insert Recipe: </label>
<textarea id = "inputTitle" rows="1" cols="50" placeholder="Recipe Title"></textarea>
<textarea id = "inputSteps" rows = "5" cols = "50" placeholder="Recipe Steps"></textarea>
<button type="submit">Add Recipe</button>
</form>
<table id = "table"></table>
该table
元素指的是 HTML5 表格,inputTitle
指的是一个textarea
,并inputSteps
指的是不同的textarea
。
我的 JavaScript 可能有错误。
提前致谢!
使用示例中的 isBlockActive 的 Slate 编辑器活动状态始终为 false
我通过将几个 slates 示例组合在一起创建了一个编辑器,即https://www.slatejs.org/examples/richtext和https://www.slatejs.org/examples/links
但是,当我为所有块级节点添加这些活动状态时,它根本不起作用,这意味着我无法打开和关闭列表项,锚链接最终会嵌套等。
损坏的代码似乎是这些行,来自所有示例中的 isBlockActive 函数:
const isBlockActive = (editor, format) => {
const [match] = Editor.nodes(editor, {
match: n => {
console.log('n.type', n.type);
return n.type === format;
},
});
return !!match;
};
match
无论我的光标位于何处,它始终是未定义的。
我目前正在运行所有软件包的最新版本0.58.1
。
下面是我的toggleBlock
函数,我也从使用 isBlockActive 函数来计算切换逻辑的示例中获取。
const toggleBlock = (editor, format) => {
const isActive = isBlockActive(editor, format);
const isList = LIST_TYPES.includes(format);
Transforms.unwrapNodes(editor, {
match: n => LIST_TYPES.includes(n.type),
split: true,
});
Transforms.setNodes(editor, {
type: isActive ? 'paragraph' : isList ? 'list-item' : format,
});
if (!isActive && isList) {
const block = { type: format, children: [] };
Transforms.wrapNodes(editor, block);
}
};
以前有没有人遇到过这个问题,也许代码库与示例不同步并且Editor.nodes
不再推荐?
由于示例使用不同的方法,所有内联格式选项都起作用:
const isMarkActive = (editor, format) => {
const marks = Editor.marks(editor);
return marks ? marks[format] === true : false;
};
如果有帮助,这里还有我的工具栏和 renderElement 功能:
<Slate editor={editor} value={value} onChange={handleChange}>
<div className={styles.toolbar}>
<MarkButton format="bold" icon="bold" />
<MarkButton format="italic" icon="italic" />
<MarkButton format="underline" icon="underline" />
<MarkButton format="code" icon="code" />
<BlockButton format="heading-one" icon="h1" />
<BlockButton format="heading-two" icon="h2" />
<BlockButton format="heading-three" icon="h3" />
<BlockButton format="quote" icon="quote-left" />
<BlockButton format="numbered-list" icon="list-ol" />
<BlockButton format="bulleted-list" icon="list-ul" />
<BlockButton format="break" icon="horizontal-rule" />
<LinkButton />
</div>
...
const Element = ({ attributes, children, element }) => {
switch (element.type) {
case 'quote':
return <blockquote {...attributes}>{children}</blockquote>;
case 'code':
return (
<pre>
<code {...attributes}>{children}</code>
</pre>
);
case 'heading-one':
return <h1 {...attributes}>{children}</h1>;
case 'heading-two':
return <h2 {...attributes}>{children}</h2>;
case 'heading-three':
return <h3 {...attributes}>{children}</h3>;
case 'heading-four':
return <h4 {...attributes}>{children}</h4>;
case 'heading-five':
return <h5 {...attributes}>{children}</h5>;
case 'heading-six':
return <h6 {...attributes}>{children}</h6>;
case 'list-item':
return <li {...attributes}>{children}</li>;
case 'numbered-list':
return <ol {...attributes}>{children}</ol>;
case 'bulleted-list':
return <ul {...attributes}>{children}</ul>;
case 'link':
return (
<a {...attributes} href={element.url}>
{children}
</a>
);
default:
return <p {...attributes}>{children}</p>;
}
};
解决方案
首先,由于您没有将数据提交给任何其他资源,因此您不应该使用 aform
或submit
按钮。
现在,最简单的解决方案是在构建表之前对输入进行验证。如果输入为空,则不要构建这些行。
最后,不要.innerHTML
在您使用的字符串不包含任何 HTML 时使用。改为使用.textContent
,因为.innerHTML
有性能和安全方面的考虑。
let inputTitle = document.getElementById("inputTitle");
let inputSteps = document.getElementById("inputSteps");
document.querySelector("button").addEventListener("click", function (event) {
// First, just check to see if there was valid input
if(!inputTitle.value || !inputSteps.value){
alert("You must fill in a title and a recipe");
return; // Exit function
}
let titleRow = table.insertRow();
let stepsRow = table.insertRow();
let titleCell = titleRow.insertCell();
let stepsCell = stepsRow.insertCell();
titleCell.textContent = inputTitle.value;
stepsCell.textContent = inputSteps.value;
titleCell.contentEditable = true;
stepsCell.contentEditable = true;
});
<label>Insert Recipe: </label>
<textarea id = "inputTitle" rows="1" cols="50" placeholder="Recipe Title"></textarea>
<textarea id = "inputSteps" rows = "5" cols = "50" placeholder="Recipe Steps"></textarea>
<button type="button">Add Recipe</button>
<table id = "table"></table>
推荐阅读
- azure - Azure ARM 模板 - 参数与属性上的静态值相结合
- r - 在 Windows 10 上 clickElement() 后 RSelenium 崩溃
- java - 递归查找字符串中字符的出现次数(java)
- functional-programming - Scheme中最长的数字子集
- c# - WPF“重叠”滚动查看器
- visual-studio-code - 等到符号提供程序可用
- spring-boot - 如何使用 gradle 下载所有 Spring Boot 依赖项
- google-apps-script - 使用谷歌表格中的命名范围作为自定义公式中的变量
- rxjs - RxJs 窗口:没有得到最后一个可观察的
- asp.net-core - 无法使用 Azure AD 策略进行身份验证:授权失败并被禁止
我刚开始学习 JavaScript 和 HTML5 的基础知识。我正在尝试创建一个食谱应用程序,用户可以在其中添加食谱。这些配方存储在一个数组中,并通过一个带有 for 循环的表循环。用户还可以编辑表格。主要功能之一应该是当表格的一行为空时,它会自动被删除。我尝试display: none
与 CSS 一起使用,但它不起作用。这是我的表格 CSS:
问题描述
我刚开始学习 JavaScript 和 HTML5 的基础知识。我正在尝试创建一个食谱应用程序,用户可以在其中添加食谱。这些配方存储在一个数组中,并通过一个带有 for 循环的表循环。用户还可以编辑表格。主要功能之一应该是当表格的一行为空时,它会自动被删除。我尝试display: none
与 CSS 一起使用,但它不起作用。这是我的表格 CSS:
form.addEventListener("submit", function (event) {
let titleRow = table.insertRow();
let stepsRow = table.insertRow();
let titleCell = titleRow.insertCell();
let stepsCell = stepsRow.insertCell();
titleCell.innerHTML = inputTitle.value;
stepsCell.innerHTML = inputSteps.value;
titleCell.contentEditable = true;
stepsCell.contentEditable = true;
inputTitle.value = inputTitle.defaultValue;
inputSteps.value = inputSteps.defaultValue;
}, false);
td: empty {
display: none;
}
tr: empty {
display: none;
}
<form id="form">
<label>Insert Recipe: </label>
<textarea id = "inputTitle" rows="1" cols="50" placeholder="Recipe Title"></textarea>
<textarea id = "inputSteps" rows = "5" cols = "50" placeholder="Recipe Steps"></textarea>
<button type="submit">Add Recipe</button>
</form>
<table id = "table"></table>
该table
元素指的是 HTML5 表格,inputTitle
指的是一个textarea
,并inputSteps
指的是不同的textarea
。
我的 JavaScript 可能有错误。
提前致谢!
使用示例中的 isBlockActive 的 Slate 编辑器活动状态始终为 false
我通过将几个 slates 示例组合在一起创建了一个编辑器,即https://www.slatejs.org/examples/richtext和https://www.slatejs.org/examples/links
但是,当我为所有块级节点添加这些活动状态时,它根本不起作用,这意味着我无法打开和关闭列表项,锚链接最终会嵌套等。
损坏的代码似乎是这些行,来自所有示例中的 isBlockActive 函数:
const isBlockActive = (editor, format) => {
const [match] = Editor.nodes(editor, {
match: n => {
console.log('n.type', n.type);
return n.type === format;
},
});
return !!match;
};
match
无论我的光标位于何处,它始终是未定义的。
我目前正在运行所有软件包的最新版本0.58.1
。
下面是我的toggleBlock
函数,我也从使用 isBlockActive 函数来计算切换逻辑的示例中获取。
const toggleBlock = (editor, format) => {
const isActive = isBlockActive(editor, format);
const isList = LIST_TYPES.includes(format);
Transforms.unwrapNodes(editor, {
match: n => LIST_TYPES.includes(n.type),
split: true,
});
Transforms.setNodes(editor, {
type: isActive ? 'paragraph' : isList ? 'list-item' : format,
});
if (!isActive && isList) {
const block = { type: format, children: [] };
Transforms.wrapNodes(editor, block);
}
};
以前有没有人遇到过这个问题,也许代码库与示例不同步并且Editor.nodes
不再推荐?
由于示例使用不同的方法,所有内联格式选项都起作用:
const isMarkActive = (editor, format) => {
const marks = Editor.marks(editor);
return marks ? marks[format] === true : false;
};
如果有帮助,这里还有我的工具栏和 renderElement 功能:
<Slate editor={editor} value={value} onChange={handleChange}>
<div className={styles.toolbar}>
<MarkButton format="bold" icon="bold" />
<MarkButton format="italic" icon="italic" />
<MarkButton format="underline" icon="underline" />
<MarkButton format="code" icon="code" />
<BlockButton format="heading-one" icon="h1" />
<BlockButton format="heading-two" icon="h2" />
<BlockButton format="heading-three" icon="h3" />
<BlockButton format="quote" icon="quote-left" />
<BlockButton format="numbered-list" icon="list-ol" />
<BlockButton format="bulleted-list" icon="list-ul" />
<BlockButton format="break" icon="horizontal-rule" />
<LinkButton />
</div>
...
const Element = ({ attributes, children, element }) => {
switch (element.type) {
case 'quote':
return <blockquote {...attributes}>{children}</blockquote>;
case 'code':
return (
<pre>
<code {...attributes}>{children}</code>
</pre>
);
case 'heading-one':
return <h1 {...attributes}>{children}</h1>;
case 'heading-two':
return <h2 {...attributes}>{children}</h2>;
case 'heading-three':
return <h3 {...attributes}>{children}</h3>;
case 'heading-four':
return <h4 {...attributes}>{children}</h4>;
case 'heading-five':
return <h5 {...attributes}>{children}</h5>;
case 'heading-six':
return <h6 {...attributes}>{children}</h6>;
case 'list-item':
return <li {...attributes}>{children}</li>;
case 'numbered-list':
return <ol {...attributes}>{children}</ol>;
case 'bulleted-list':
return <ul {...attributes}>{children}</ul>;
case 'link':
return (
<a {...attributes} href={element.url}>
{children}
</a>
);
default:
return <p {...attributes}>{children}</p>;
}
};
解决方案
首先,由于您没有将数据提交给任何其他资源,因此您不应该使用 aform
或submit
按钮。
现在,最简单的解决方案是在构建表之前对输入进行验证。如果输入为空,则不要构建这些行。
最后,不要.innerHTML
在您使用的字符串不包含任何 HTML 时使用。改为使用.textContent
,因为.innerHTML
有性能和安全方面的考虑。
let inputTitle = document.getElementById("inputTitle");
let inputSteps = document.getElementById("inputSteps");
document.querySelector("button").addEventListener("click", function (event) {
// First, just check to see if there was valid input
if(!inputTitle.value || !inputSteps.value){
alert("You must fill in a title and a recipe");
return; // Exit function
}
let titleRow = table.insertRow();
let stepsRow = table.insertRow();
let titleCell = titleRow.insertCell();
let stepsCell = stepsRow.insertCell();
titleCell.textContent = inputTitle.value;
stepsCell.textContent = inputSteps.value;
titleCell.contentEditable = true;
stepsCell.contentEditable = true;
});
<label>Insert Recipe: </label>
<textarea id = "inputTitle" rows="1" cols="50" placeholder="Recipe Title"></textarea>
<textarea id = "inputSteps" rows = "5" cols = "50" placeholder="Recipe Steps"></textarea>
<button type="button">Add Recipe</button>
<table id = "table"></table>
推荐阅读
- azure - Azure ARM 模板 - 参数与属性上的静态值相结合
- r - 在 Windows 10 上 clickElement() 后 RSelenium 崩溃
- java - 递归查找字符串中字符的出现次数(java)
- functional-programming - Scheme中最长的数字子集
- c# - WPF“重叠”滚动查看器
- visual-studio-code - 等到符号提供程序可用
- spring-boot - 如何使用 gradle 下载所有 Spring Boot 依赖项
- google-apps-script - 使用谷歌表格中的命名范围作为自定义公式中的变量
- rxjs - RxJs 窗口:没有得到最后一个可观察的
- asp.net-core - 无法使用 Azure AD 策略进行身份验证:授权失败并被禁止