I am new to Javascript and this is my first question. I want to make autocomplete suggestions purely in HTML, CSS and JS using below JS code. I have gotten this code from GitHub.
The problem is when I type, it downloads the whole JSON file before showing suggestions. I want to reduce this JSON file by splitting the JSON data to multiple JSON files like states1.json, states2.json, states3.json etc. I have tried but failed as I'm new. Here is the code.
Please answer simply to help me understand.
const matchList = document.getElementById("match-list");
//Search states.json and filter it
const searchStates = async searchText => {
const res = await fetch("./data/States1.json");
const states = await res.json();
//Get Matches to current text input
let matches = states.filter(state => {
const regex = new RegExp(`^${searchText}`, "gi");
return state.wr.match(regex);
});
if (searchText.length === 0) {
matches = [];
matchList.innerHTML = "";
}
outputHtml(matches);
};
//Show Results in HTML
const outputHtml = matches => {
if (matches.length > 0) {
const html = matches
.map(
match => `
<div class="card card-body mb-4">
<h4>${match.wr} <span class="text-primary">${
match.mn
}</span></h4>
</div>`
)
.join("");
matchList.innerHTML = html;
}
};
search.addEventListener("input", () => searchStates(search.value));
Related
I want to create a table of contents from a markdown file in next.js and I want it to be in markdown format as well.
To achieve that I have made this function:
const getMarkdownTOC = (slug) => {
const folder = process.env.PATH_ARTICULOS
const file = `${folder}${slug}.md`
const content = fs.readFileSync(file, 'utf8')
const matterResult = matter(content)
let prevLevel = 99
let spaces = ''
let toc = ''
for (const [, value] of Object.entries(compiler(matterResult.content).props.children)) {
if (value.type !== undefined && value.type.startsWith('h') && !isNaN(value.type[1])) {
const level = Number(value.type[1])
const title = value.props.children[0]
const id = value.props.id
if (level > prevLevel) {
spaces += ' '
} else {
if (level < prevLevel) {
spaces = spaces.slice(0, spaces.length - 2 * (prevLevel - level))
}
}
toc += `${spaces}* [${title}](#${id})\n`
prevLevel = level
}
}
And the function does actually work, it returns a table of contents in markdown format that can be rendered wherever I want.
However, I think there has to be some easier way to achieve that, but I've been searching and haven't found anything. There is a plugin called remark-toc which is almost what I want, but it seems to create the table of contents at the beginning of the document and I want to keep it apart.
Any ideas? Thank you!
I will this typescript object convert:
api:{
accessToken:[user1::aaaaa,user2::bbbbb],
accessSecret:[user1:aaaaa,userb::bbbbb]
}
i will split the string inside the arrays by :: sign.
Finish object should look like this
api:{
accessToken:[user1::aaaaa,user2::bbbbb],
accessSecret:[user1:aaaaa,userb::bbbbb],
user1_access:aaaaa,
user2_access:bbbbb,
user1_secret:aaaaa,
user2_secret:bbbbb
}
What is the best solution without compile errors in typescript, please Help.
Here is a sample which gives you an idea of how to go about it,
const api = {
accessToken:["user1::aaaaa","user2::bbbbb"],
accessSecret:["user1::xxxx","user2::yyyy"]
};
const newApiObj: any = {};
const accessTokenvalues = api.accessToken.map(x => x.split("::")) ?? [];
for(const item of accessTokenvalues){
newApiObj[item[0] + '_access'] = item[1];
}
const accessSecretvalues = api.accessSecret.map(x => x.split("::")) ?? [];
for(const item of accessSecretvalues){
newApiObj[item[0] + '_secret'] = item[1];
}
console.log(newApiObj);
I have a search box that allows user to type in the values they want to search the grid on. Whatever the user types in the search box should be highlighted on the grid if there is any match.
The code i'm using to try and achieve this is below:
const searchTerms = searchTerm.trim().split(' ').filter((item) => item !== '');
let result = rawGridRecord;
searchTerms.forEach((val) => {
const reText = new RegExp(val, 'gi');
result = result.replace(reText, '<span class="text-highlight">$&</span>');
});
The problem i'm having currently is that if there are more than 1 search terms, it starts to match against '<span class="text-highlight">$&</span>' which is now part of the result string. and this causes a behavior that we dont want. The html starts showing as string in the grid.
How is it possible to achieve this functionality so that all the searchTerms can be highlighted properly without creating issues.
const searchTerms = searchTerm.replace('*', '').trim().split(' ').filter((item) => item !== '');
const searchString = '(' + searchTerms.join('|') + ')';
let result = newName;
if (result) {
const reText = new RegExp(new RegExp(searchString), 'gi');
result = result.replace(reText, '<span class="text-highlight">$&</span>');
}
Tried this and it seems to be working better now. Not sure how full proof this is.
I am working on a react native project and I have an html string json api response.
I am using react-native-render-html to render it, and I can get all paragraphs and apply specific things like number of lines ,etc.. . However I want to get only the first paragraph in the response.
str response='<p>text1</p> <p>text2</p> <p>text3</p>';
Is it possible to write a regular expression to get only the content of first paragraph which is for example text1 ?
I don't use React Native but in javascript you could do something like that:
const paragraphs = response.split("</p>")
const firstParagraph = paragraphs[0]+'</p>';
Or with a regex you can do something like that:
// extract all paragraphe from the string
const matches = [];
response.replace(/<p>(.*?)<\/p>/g, function () {
//use arguments[0] if you need to keep <p></p> html tags
matches.push(arguments[1]);
});
// get first paragraph
const firstParagraph = (matches.length) ? matches[0] : ""
Or like that (I think it is the best way in your case)
const response='<p>text1</p> <p>text2</p> <p>text3</p>';
const regex = /<p>(.*?)<\/p>/;
const corresp = regex.exec(response);
const firstParagraph = (corresp) ? corresp[0] : "" // <p>text1</p>
const firstParagraphWithoutHtml = (corresp) ? corresp[1] : "" // text1
Hope it will help
var response='<p>text1</p> <p>text2</p> <p>text3</p>';
var firstParagraphElement=response.split("</p>")[0] //firstparagraphElement="<p>text1"
var paragraphContent=firstParagraphElement.replace("<p>","") //paragraphContent="text1"
javascript split() function reference click
javascript replace() function reference click
In React Native you can also use parse5 to extract a string from HTML code. I have used this code in a project for doing so:
import parse5 from 'parse5'
const isText = (tagName): Boolean => tagName === '#text'
const processNode = (node): String => {
const nodeName = node.nodeName
if (isText(nodeName)) {
return node.value
}
if (!node.childNodes) {
return ''
}
return node.childNodes.map((child, index) => processNode(child)).join(' ')
}
export const htmlToText = (html): String => {
const root = parse5.parseFragment(html)
return processNode(root).replace(/\s+/g, ' ').trim()
}
Here is a simple JEST test for the function above:
test('when full document htmlToText should get text', () => {
const htmlToText1 = htmlToText("<html><head><title>titleTest</title></head><body><a href='test0'>test01</a><a href='test1'>test02</a><a href='test2'>test03</a></body></html>")
expect(htmlToText1)
.toBe(`titleTest test01 test02 test03`);
});
Suppose I have
const bold = content => <b>{content}</b>;
const aside = content => <aside>{content}</b>;
Now, I write:
aside("hello world");
And everything performs correctly.
Next, suppose I want to render a list of components in aside:
const bold = content => <b>{content}</b>;
const aside_items = ???
Such that when I write:
aside_items([bold("hello"), bold("world")]);
The following HTML is produced:
<aside>
<b>hello</b>
<b>world</b>
</aside>
How does one implement const aside_items = ????
Not sure if you are using JSX, but if not you could use Template literals and then just join array items to string.
const bold = content => `<b>${content}</b>`;
const aside_items = content => `<aside>${content.join('')}</aside>`
const items = aside_items([bold("hello"), bold("world")]);
document.body.innerHTML += items;
This will iterate over the items array and return a string of HTML markup:
const aside_items = (items) => {
let arr = [];
for (let i in items) {
arr.push(items[i]);
}
return '<aside>' + arr.join('') + '</aside>';
}