I am making a website with a text input box.
I have this piece of code in a JS file:
$(document).ready(function() {
$("#filterTextBox").on("keyup", function () {
var search = this.value;
$(".person").show().filter(function () {
return $(".name", this).text().indexOf(search) < 0;
}).hide();
});
});
With this when I search "hello", it won't find the name "Hello"
Can I make it doesn't matter if it is "Hello" or "hELLo" or whatever?
You Can
Use toLowerCase() to convert all of user inputs to lower case so every time you compare or use a word you already matching the same value if non-casing words
For Example
"Hello".toLowerCase() outputs 'hello'
"hELLo".toLowerCase() outputs 'hello'
In your code
Make sure $(".name", this).text() is lowercased before you search for the index of the search value
So you code will be something like that
//hide all the elements except for the matches
$(document).ready(function() {
$("#filterTextBox").on("keyup", function () {
var search = this.value.toLowerCase();
$(".person").show().filter(function () {
return $('.name', this).text().toLowerCase().indexOf(search)<0;
}).hide();
});
});
Thanks #mark.hch for your code https://jsfiddle.net/yd9k12bz/
The vanilla version shows how everything fits together.
const getPeople = () => document.querySelectorAll('.person');
document.addEventListener('keyup', ({ target }) => {
if (target.matches('#search')) {
const searchFor = target.value.toLowerCase();
if (searchFor.length > 0) {
getPeople().forEach(p => {
if (p.innerText.toLowerCase().includes(searchFor)) {
p.classList.remove('hide');
} else {
p.classList.add('hide')
}
});
} else {
// Show all
getPeople().forEach(p => p.classList.remove('hide'));
}
}
})
.hide {
display: none;
}
<div class="person">Paul T</div>
<div class="person">John B</div>
<div class="person">David C</div>
<div class="person">Lisa A</div>
<div class="person">Claire W</div>
<div class="person">Paul W</div>
<div class="person">John F</div>
<div class="person">David S</div>
<div class="person">Lisa R</div>
<div class="person">Claire B</div>
<input type="text" id="search">
Related
I want to read the html from a site and then split it into nodes. I tried this code:
function load() {
$(document).ready(function () {
$.get("https://example.com/index.html", function (data) {
const loadpage = async function() {
var nodes = [...data.childNodes].slice(-3);
var cont = document.getElementById("container");
var msg = nodes;
});
if(cont.innerHTML='') {
cont.insertAdjacentHTML('afterbegin', msg);
} else {
cont.innerHTML=msg;
}
};
loadpage();
});
});
}
load();
html looks like this:
<main>
<div class="msg">something</div>
<div class="msg">something</div>
<div class="msg">something</div>
<div class="msg">something</div>
<div class="msg">something</div>
<div class="msg">something</div>
</main>
the expected output should be:
<div class="msg">something</div>
<div class="msg">something</div>
<div class="msg">something</div>
since I want only the last 3 nodes.
Thank you.
It is not necessary to use async await here and you are doing it wrong
Please read How to return values from async functions using async-await from function?
Your load is also wrong and too complex. You should not add a window event handler in a function and the test to insert after if cont is empty is not useful. Your test is also not a comparison (== '' or === '') but an assignment (= '').
Add the data to a partial element and slice the result
$(document).ready(function() {
const cont = document.getElementById("container");
$.get("https://example.com/index.html", function(data) {
const div = document.createElement('div')
div.innerHTML = data; // assuming HTML string?
[...div.querySelectorAll('.msg')]
.slice(-3)
.forEach(div => cont.innerHTML += div.outerHTML);
});
});
This js code is supposed to change the the value of class attribute 'skills__open' to 'skills__close' when the 'skills__header' div is clicked. It changes the 'skills__open' to 'skills__close' on the first click, but after the first click, it is not working.
Js
const skillsContent = document.getElementsByClassName('skills__content'),
skillsHeader = document.querySelectorAll('.skills__header')
function toggleSkills(){
let itemClass = this.parentNode.ClassName
for(i=0; i < skillsContent.length; i++){
skillsContent[i].className = 'skills__content skills__close'
}
if(itemClass === 'skills__content skills__close'){
this.parentNode.className = 'skills__content skills__open'
}
}
skillsHeader.forEach((el) =>{
el.addEventListener('click', toggleSkills)
});
Html
<div class="skills__content skills__open">
<div class="skills__header">
</div>
<div class="skills__content skills__close">
<div class="skills__header">
</div>
<div class="skills__content skills__close">
<div class="skills__header">
</div>
css
.skills__open .skills__list{
height: max-content;
margin-bottom: var(--mb-2-5);
}
.skills__open .skills__arrow{
transform: rotate(-180deg);
}
nothing significant
try that:
const skillsContents = document.querySelectorAll('.skills__content');
skillsContents.forEach( skc =>
{
skc
.querySelector('.skills__header')
.addEventListener('click', () =>
{
skillsContents.forEach( el =>
{
if (skc===el) el.classList.replace('skills__close','skills__open')
else el.classList.replace('skills__open','skills__close')
})
})
});
Is there a way to output the text from html using Cheerio which includes some html tags? I know that the .html() outputs the full html, but I only want the text using .text() but with all H tags and breaks?
Example:
<div class="className"><h1>Something here</h1></br><p>Next line text</p></div>
Should output:
<h1>Something here</h1></br>Next line text
Code what I have now:
const $ = await fetchHTML(thisEntry.link);
const content = $(`div[class='${feedDiv}']`).text()
Which only outputs the text of the div without any alinea breaks or H1 tags. The .text() outputs also <img> tags by default.
UPDATE
I am trying to do a trimmed function as discussed in the comments, but still not working... Am I overlooking something?
async function fetchHTML(url) {
const { data } = await axios.get(url);
return cheerio.load(data, { decodeEntities: false });
}
async function createFeed(feedConfig, entries) {
const $ = await fetchHTML(thisEntry.link);
$(function () {
function clean(o, h) {
var results = '';
if (h == undefined) {
results = o.text().trim();
} else {
$(o)
.children()
.each(function (i, el) {
if (h.indexOf($(el).prop('nodeName').toLowerCase()) >= 0) {
console.log('Found', $(el).prop('nodeName'));
results += $(el).prop('outerHTML');
} else {
console.log($(el).text().trim());
results += $(el).text().trim();
}
});
}
return results;
}
$(".className").html(clean($(".className"), ["h1", "br"]));
});
console.log($.text().trim());
}
Console outputs nothing
You can make your own Trim style function. Feed in the object and the Elements you want to keep.
Example:
$(function() {
function clean(o, h) {
var results = "";
if (h == undefined) {
results = o.text().trim();
} else {
$(o).children().each(function(i, el) {
if (h.indexOf($(el).prop("nodeName").toLowerCase()) >= 0) {
console.log("Found", $(el).prop("nodeName"));
results += $(el).prop("outerHTML");
} else {
console.log($(el).text().trim());
results += $(el).text().trim();
}
});
}
return results;
}
$(".className").html(clean($(".className"), ["h1", "br"]));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="className">
<h1>Something here</h1>
</br>
<p>Next line text</p>
</div>
There is a pitfall here in that if there is raw text, it might also get stripped away.
Basically what I need to do is wrap this code output
<a id="show_selected">Click to Show</a>
<div id="selected"></div>
<script type="text/javascript">
function showSelect(){
$("#show_selected").bind("click", function (e) {
e.preventDefault();
$('#selected').text($("#fvip").mapster("get"));
});
}
showSelect();
</script>
which is right now is just plain
<div id="selected">001,002,003,004</div>
to become
<div="selected">
<div class="something">001</div>
<div class="something">002</div>
<div class="something">003</div>
<div class="something">004</div>
</div>
how can I do that? Is that possible? Many thanks
EDIT with brk 's help below:
I try incorporate it in my code like this:
function showSelect(){
$("#show_selected").bind("click", function (e) {
e.preventDefault();
$('#selected').text($("#fvip").mapster("get"));
let wrapContainer = ""
let stringArray = $("#selected").text().trim().split(' ');
$("#selected").empty()
stringArray.forEach(function(item, index) {
let wrapContainer = $('<div class="test">' + item + '</div>');
$("#selected").append(wrapContainer)
});
});
}
showSelect();
but what I'm getting is:
<div id="selected">
<div class="test">001,002,003,004</div>
</div>
where am I doing wrong?
You can get the text and split it. Then loop over that and put that inside a div . Then append the div to the parent element
let wrapContainer = ""
let stringArray = $("#original").text().trim().split(' ');
$("#original").empty()
stringArray.forEach(function(item, index) {
let wrapContainer = $('<div class="test">' + item + '</div>');
$("#original").append(wrapContainer)
});
.test {
color: green
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="original">001 002 003 004</div>
I have a textbox that matches the word written to id's of hidden containers and fades them in after pressing enter, everything works great except of when i added a button to make the same action...I can't seem to make the button work.
jsFIDDLE
HTML
<input type="text" value="Type the desired page" id="search" class="txtfield" onBlur="javascript:if(this.value==''){this.value=this.defaultValue;}" onFocus="javascript:if(this.value==this.defaultValue){this.value='';}" autocomplete="off"/>
<input type="button" class="btn"/>
<div class="clear"></div>
<div id="content">
<div id="home">home
<br /><i>home content</i>
</div>
<div id="about">about
<br /><i>about content</i>
</div>
<div id="portfolio">portfolio
<br /><i>portfolio content</i>
</div>
<div id="hire">hire me
<br /><i>hire me content</i>
</div>
<div id="contact">contact
<br /><i>contact content</i>
</div>
</div>
Script
var substringMatcher = function (strs, q, cb) {
return (function (q, cb, name) {
var matches, substrRegex;
// an array that will be populated with substring matches
matches = [];
// regex used to determine if a string contains the substring `q`
substrRegex = new RegExp(q, 'i');
// iterate through the pool of strings and for any string that
// contains the substring `q`, add it to the `matches` array
$.each(strs, function (i, str) {
$("#search").val("");
if (substrRegex.test(str) || q.slice(0, 1) === str.slice(0, 1)) {
// the typeahead jQuery plugin expects suggestions to a
// JavaScript object, refer to typeahead docs for more info
matches.push(name(str));
}
});
cb(matches);
}(q, cb, function (n) {
return {
"content": n
}
}));
};
var _matches = $.map($("#content div"), function (v, k) {
return [v.id]
});
var template = {
"content": _matches
};
var search = $('#search').val().toLowerCase();
$("#content div:gt(0)").hide(0);
$('#search').focus().keyup(function (e) {
var search = $(this);
var _search = search.val();
if (e.which === 13){
substringMatcher(template.content, _search, function (d) {
$("#" + d[0].content)
.delay(500)
.fadeIn(500)
.siblings()
.fadeOut(500);
search.val("")
})
}
});
Here's a solution
http://jsfiddle.net/35r0m6rc/12/
This part got changed:
$('#search').focus().keyup(function (e) {
var search = $(this);
var _search = search.val();
if (e.which === 13){
show_page(_search);
}
});
$('.btn').click(function(){
show_page($('#search').val());
});
function show_page(_search) {
substringMatcher(template.content, _search, function (d) {
$("#" + d[0].content)
.delay(500)
.fadeIn(500)
.siblings()
.fadeOut(500);
search.val("")
})
}
I made a func to show the page, used by both RETURN and the button.