编辑文本区域时,如何计算指定字符序列的出现次数



我正在寻找一种方法,可以自动计算文本区域中指定的单词,而无需单击按钮,在这种情况下,如果有更改,可以自动更新。。

这是我迄今为止混乱的代码:

function findWord1() {
var outputDiv = $('#opening-bracket');
var searchText = $('#textarea3').val();
var wordMatch = "[";
outputDiv.empty();
var m = searchText.match(new RegExp(wordMatch.toString().replace(/(?=[.\+*?[^]$(){ }|])/g, "\"), "ig"));
outputDiv.append('<a>' + (m ? m.length : 0) + '</a>');
}
function findWord2() {
var outputDiv = $('#closing-bracket');
var searchText = $('#textarea3').val();
var wordMatch = "]";
outputDiv.empty();
var m = searchText.match(new RegExp(wordMatch.toString().replace(/(?=[.\+*?[^]$(){}|])/g, "\"), "ig"));
outputDiv.append('<a>' + (m ? m.length : 0) + '</a');
}
function findWord3() {
var outputDiv = $('#opening-added-bracket');
var searchText = $('#textarea3').val();
var wordMatch = "[A>";
outputDiv.empty();
var m = searchText.match(new RegExp(wordMatch.toString().replace(/(?=[.\+*?[^]$(){}|])/g, "\"), "ig"));
outputDiv.append('<a>' + (m ? m.length : 0) + '</a');
}
function findWord4() {
var outputDiv = $('#closing-added-bracket');
var searchText = $('#textarea3').val();
var wordMatch = "lt;A]";
outputDiv.empty();
var m = searchText.match(new RegExp(wordMatch.toString().replace(/(?=[.\+*?[^]$(){}|])/g, "\"), "ig"));
outputDiv.append('<a>' + (m ? m.length : 0) + '</a');
}
function findWord5() {
var outputDiv = $('#opening-deleted-bracket');
var searchText = $('#textarea3').val();
var wordMatch = "[D>";
outputDiv.empty();
var m = searchText.match(new RegExp(wordMatch.toString().replace(/(?=[.\+*?[^]$(){}|])/g, "\"), "ig"));
outputDiv.append('<a>' + (m ? m.length : 0) + '</a');
}
function findWord6() {
var outputDiv = $('#closing-deleted-bracket');
var searchText = $('#textarea3').val();
var wordMatch = "lt;D]";
outputDiv.empty();
var m = searchText.match(new RegExp(wordMatch.toString().replace(/(?=[.\+*?[^]$(){}|])/g, "\"), "ig"));
outputDiv.append('<a>' + (m ? m.length : 0) + '</a');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<button onclick="findWord1();findWord2();findWord3();findWord4();findWord5();findWord6();">Count</button>
<table>
<thead>
<tr>
<th scope="col">Items</th>
<th scope="col">Count</th>
</tr>
</thead>
<tbody>
<tr>
<td>[A&gt;</td>
<td><a id="opening-added-bracket"></a></td>
</tr>
<tr>
<td>&lt;A]</td>
<td><a id="closing-added-bracket"></a></td>
</tr>
<tr>
<td>[D&gt;</td>
<td><a id="opening-deleted-bracket"></a></td>
</tr>
<tr>
<td>&lt;D]</td>
<td><a id="closing-deleted-bracket"></a></td>
</tr>
<tr>
<td>[</td>
<td><a id="opening-bracket"></a></td>
</tr>
<tr>
<td>]</td>
<td><a id="closing-bracket"></a></td>
</tr>
</tbody>
</table>
<textarea id="textarea3" rows="5">
[A>
lt;A]
[D>
lt;D]
</textarea>

如果可能的话,我想保留";计数";按钮,这样我仍然可以手动执行,以防代码的其他部分出现故障。。

如果我的代码看起来很糟糕,我很抱歉,但提前感谢您的帮助。

使用keyup只需这样做

function countWordFunc() { 
let myText = document.getElementById("myText").value;
let wordsArr = myText.trim().split(" ")
let countWords = wordsArr.filter(word => word !== "").length

let counter = document.getElementById("counter");
counter.innerHTML = `Total Words: ${countWords}`;
}
<textarea onkeyup="countWordFunc()" id="myText">Hello, World</textarea>
<div id="counter"></div>

OP的代码存在以下问题。。。

基于特定元素ids
  • 代码永远无法转换为可重用代码方面足够通用的代码。

  • 计算单个括号是危险的,尤其是因为它们是其他要匹配的字符序列(OP称之为单词(的一部分。

因此,可以考虑一种尽可能配置和通用的、拙劣的、类似组件的方法,类似于下一个提供的示例代码,其中。。。

  • 例如,可以通过正则表达式模式配置要匹配的项。

  • 还可以像自动计数一样配置组件的UI/UX行为。

  • 每个配置都基于CCD_ 3属性及其对应的HTMLElement.dataset。

  • 由于上述第三个要点,只要正确提供了必要的data-*属性,组件就不知道其标记。

这种方法也可以像我的一条评论一样总结。。。

"通过读取和计算配置设置来初始化类似组件的结构,并在配置设置之后用正确的事件注册计数处理程序。计数处理程序本身就是一个简单的基于正则表达式的模式匹配(与所有其他解决方案不同,它也能正确工作(和计数呈现任务。不需要元素ID,可以自由选择标记,通过标记和数据属性应用配置。不需要为了引入更多的匹配项目/单词而接触JS代码">

function displayItemCount(itemRoot, target) {
const elmPattern =
target && itemRoot?.querySelector('[data-reg-pattern]');
const elmCount =
elmPattern && itemRoot?.querySelector('[data-match-count]');
const regXItem =
elmCount && RegExp(elmPattern.dataset.regPattern, 'g');
if (regXItem) {
elmCount.textContent = (target.value.match(regXItem) ?? []).length;
}
}
function displayItemCountsOfBoundComponentData() {
const { rootNode, countsTarget } = this;
rootNode
.querySelectorAll('[data-item-match]')
.forEach(itemRoot =>
displayItemCount(itemRoot, countsTarget)
);
}
function initializeItemCountsComponent(rootNode) {
const { dataset } = rootNode;
let {
countsTargetSelector = '',
triggerCountsSelector = '',
autoCount = false,
} = dataset;

countsTargetSelector = countsTargetSelector.trim();
triggerCountsSelector = triggerCountsSelector.trim();
const countsTarget = (
rootNode.querySelector(countsTargetSelector || null) ||
document.querySelector(countsTargetSelector || null)
);
if (countsTarget) {
let countsTriggers = rootNode
.querySelectorAll(triggerCountsSelector || null);
if (countsTriggers.length === 0) {
countsTriggers = document
.querySelectorAll(triggerCountsSelector || null);
}
const isAutoCount = (
(countsTriggers.length === 0) || (
(autoCount !== false) && (
(autoCount.trim() === '') ||
(autoCount.trim().toLowerCase() === 'true')
)
)
);
const displayItemCounts =
displayItemCountsOfBoundComponentData.bind({
rootNode,
countsTarget,
});
countsTriggers.forEach(elmNode =>
elmNode
.addEventListener('click', displayItemCounts)
);
if (isAutoCount) {
countsTarget
.addEventListener('input', displayItemCounts);
// trigger component's initial item counts.
displayItemCounts();
}
}
}
function main() {
document
.querySelectorAll('[data-item-counts]')
.forEach(initializeItemCountsComponent);
}
main();
body { margin: 0; }
article { position: relative; display: inline-block; margin: 0 20px 0 0; }
[data-item-counts] { float: left; margin: 0 10px 0 0; }
textarea { margin: 0; }
button { position: absolute; left: 0; top: 175px; }
<article>
<table
data-item-counts
data-counts-target-selector="#textarea3"
data-trigger-counts-selector="#count-textarea3-items"
>
<thead>
<tr>
<th scope="col">Items</th>
<th scope="col">Count</th>
</tr>
</thead>
<tbody>
<tr data-item-match>
<td data-reg-pattern="[A>" title="Opening Added Bracket">[A&gt;</td>
<td data-match-count>.?.</td>
</tr>
<tr data-item-match>
<td data-reg-pattern="<A]" title="Closing Added Bracket">&lt;A]</td>
<td data-match-count>.?.</td>
</tr>
<tr data-item-match>
<td data-reg-pattern="[D>" title="Opening Deleted Bracket">[D&gt;</td>
<td data-match-count>.?.</td>
</tr>
<tr data-item-match>
<td data-reg-pattern="<D]" title="Closing Deleted Bracket">&lt;D]</td>
<td data-match-count>.?.</td>
</tr>
<tr data-item-match>
<td data-reg-pattern="[(?!A|D)" title="Opening Bracket">[</td>
<td data-match-count>.?.</td>
</tr>
<tr data-item-match>
<td data-reg-pattern="(?<!<A|D)]" title="Closing Bracket">]</td>
<td data-match-count>.?.</td>
</tr>
</tbody>
</table>
<textarea
id="textarea3"
cols="16"
rows="12">
[A&gt;&lt;A][D&gt;&lt;D][[]][]&lt;A][D&gt;
[A&gt;&lt;A][D&gt;&lt;D][[]][]&lt;A][D&gt;
... explicitly triggered count.</textarea>
<button id="count-textarea3-items">Count Items</button>
</article>
<article>
<table
data-item-counts
data-counts-target-selector="#textarea54"
data-auto-count
>
<thead>
<tr>
<th scope="col">Items</th>
<th scope="col">Count</th>
</tr>
</thead>
<tbody>
<tr data-item-match>
<td data-reg-pattern="[A>" title="Opening Added Bracket">[A&gt;</td>
<td data-match-count>.?.</td>
</tr>
<tr data-item-match>
<td data-reg-pattern="<A]" title="Closing Added Bracket">&lt;A]</td>
<td data-match-count>.?.</td>
</tr>
<tr data-item-match>
<td data-reg-pattern="[D>" title="Opening Deleted Bracket">[D&gt;</td>
<td data-match-count>.?.</td>
</tr>
<tr data-item-match>
<td data-reg-pattern="<D]" title="Closing Deleted Bracket">&lt;D]</td>
<td data-match-count>.?.</td>
</tr>
<tr data-item-match>
<td data-reg-pattern="[(?!A|D)" title="Opening Bracket">[</td>
<td data-match-count>.?.</td>
</tr>
<tr data-item-match>
<td data-reg-pattern="(?<!<A|D)]" title="Closing Bracket">]</td>
<td data-match-count>.?.</td>
</tr>
</tbody>
</table>
<textarea
id="textarea54"
cols="16"
rows="12"
>[[]][]&lt;A][D&gt;[A&gt;&lt;A][D&gt;&lt;D]
... auto-count while editing.</textarea>
</article>

创建一个函数来调用所有其他函数。这是简化代码的一步。然后,为文本区域的input事件创建一个事件侦听器,并将新函数作为其回调函数。

这个问题本质上是许多其他涉及事件的问题的重复。看见https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events想要获得一些好的信息,如果你有进一步的问题,请在这里搜索更多的答案。

function findAllWords() {
findWord1();
findWord2();
findWord3();
findWord4();
findWord5();
findWord6();
}
document.getElementById('textarea3').addEventListener('input', findAllWords);
function findWord1() {
var outputDiv = $('#opening-bracket');
var searchText = $('#textarea3').val();
var wordMatch = "[";
outputDiv.empty();
var m = searchText.match(new RegExp(wordMatch.toString().replace(/(?=[.\+*?[^]$(){ }|])/g, "\"), "ig"));
outputDiv.append('<a>' + (m ? m.length : 0) + '</a>');
}
function findWord2() {
var outputDiv = $('#closing-bracket');
var searchText = $('#textarea3').val();
var wordMatch = "]";
outputDiv.empty();
var m = searchText.match(new RegExp(wordMatch.toString().replace(/(?=[.\+*?[^]$(){}|])/g, "\"), "ig"));
outputDiv.append('<a>' + (m ? m.length : 0) + '</a');
}
function findWord3() {
var outputDiv = $('#opening-added-bracket');
var searchText = $('#textarea3').val();
var wordMatch = "[A>";
outputDiv.empty();
var m = searchText.match(new RegExp(wordMatch.toString().replace(/(?=[.\+*?[^]$(){}|])/g, "\"), "ig"));
outputDiv.append('<a>' + (m ? m.length : 0) + '</a');
}
function findWord4() {
var outputDiv = $('#closing-added-bracket');
var searchText = $('#textarea3').val();
var wordMatch = "lt;A]";
outputDiv.empty();
var m = searchText.match(new RegExp(wordMatch.toString().replace(/(?=[.\+*?[^]$(){}|])/g, "\"), "ig"));
outputDiv.append('<a>' + (m ? m.length : 0) + '</a');
}
function findWord5() {
var outputDiv = $('#opening-deleted-bracket');
var searchText = $('#textarea3').val();
var wordMatch = "[D>";
outputDiv.empty();
var m = searchText.match(new RegExp(wordMatch.toString().replace(/(?=[.\+*?[^]$(){}|])/g, "\"), "ig"));
outputDiv.append('<a>' + (m ? m.length : 0) + '</a');
}
function findWord6() {
var outputDiv = $('#closing-deleted-bracket');
var searchText = $('#textarea3').val();
var wordMatch = "lt;D]";
outputDiv.empty();
var m = searchText.match(new RegExp(wordMatch.toString().replace(/(?=[.\+*?[^]$(){}|])/g, "\"), "ig"));
outputDiv.append('<a>' + (m ? m.length : 0) + '</a');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<table>
<thead>
<tr>
<th scope="col">Items</th>
<th scope="col">Count</th>
</tr>
</thead>
<tbody>
<tr>
<td>[A&gt;</td>
<td>
<a id="opening-added-bracket"></a>
</td>
</tr>
<tr>
<td>&lt;A]</td>
<td>
<a id="closing-added-bracket"></a>
</td>
</tr>
<tr>
<td>[D&gt;</td>
<td>
<a id="opening-deleted-bracket"></a>
</td>
</tr>
<tr>
<td>&lt;D]</td>
<td>
<a id="closing-deleted-bracket"></a>
</td>
</tr>
<tr>
<td>[</td>
<td>
<a id="opening-bracket"></a>
</td>
</tr>
<tr>
<td>]</td>
<td>
<a id="closing-bracket"></a>
</td>
</tr>
</tbody>
</table>
<textarea id="textarea3" rows="5">
[A>
lt;A]
[D>
lt;D]
</textarea>

试试这个,把函数组合成一个:

let textarea = $('#textarea3');
textarea.on('keyup', _ => counting());
function counting() {
var searchText = $('#textarea3').val();
let words = [];
words['[A>'] = '#opening-added-bracket';
words['<A]'] = '#closing-added-bracket';
words['[D>'] = '#opening-deleted-bracket';
words['<D]'] = '#closing-deleted-bracket';
words['['] = '#opening-bracket';
words[']'] = '#closing-bracket';
for (const word in words) {
var outputDiv = $(words[word]);
outputDiv.empty();
let count = searchText.split(word).length - 1;
searchText = searchText.replaceAll(word,'');
outputDiv.append('<a>' + count + '</a>');
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button onclick="counting();">Count</button>
<table>
<thead>
<tr>
<th scope="col">Items</th>
<th scope="col">Count</th>
</tr>
</thead>
<tbody>
<tr>
<td>[A&gt;</td>
<td><a id="opening-added-bracket"></a></td>
</tr>
<tr>
<td>&lt;A]</td>
<td><a id="closing-added-bracket"></a></td>
</tr>
<tr>
<td>[D&gt;</td>
<td><a id="opening-deleted-bracket"></a></td>
</tr>
<tr>
<td>&lt;D]</td>
<td><a id="closing-deleted-bracket"></a></td>
</tr>
<tr>
<td>[</td>
<td><a id="opening-bracket"></a></td>
</tr>
<tr>
<td>]</td>
<td><a id="closing-bracket"></a></td>
</tr>
</tbody>
</table>
<textarea id="textarea3" rows="5">
[A>
<A]
[D>
<D]
</textarea>

最新更新