Can I search multiple values in a "data-" element? - javascript

I have a simple search input that filters divs as you type so that only those divs with matching data attributes are shown.
This works great, but it only returns exact matches. For example, in the snippet below, I can search for "apple" but "apple california" doesn't show the proper div (even though the data attribute contains both of those values). I think this is because it's only searching for an exact match.
How might I adjust this code to search for multiple values in a "data-" element? Ideally I'd like to have it ignore common words like "and," "in," "near," so that a search for:
Apple in California or iphone near california
would still show the Apple div.
Appreciate any advice, I'm stumped! Here's the snippet:
$('[data-search]').on('keyup', function() {
var searchVal = $(this).val();
var filterItems = $('[data-filter-item]');
if (searchVal != '') {
filterItems.addClass('hidden');
$('[data-filter-item][data-filter-name*="' + searchVal.toLowerCase() + '"]').removeClass('hidden');
} else {
filterItems.removeClass('hidden');
}
});
* {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Helvetica, sans-serif;
}
.hidden {
display: none;
}
input {
background: #cdcdcd;
border: none;
padding: 14px 20px;
}
.items {
margin-top: 25px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="search">
<input type="text" placeholder="search" data-search />
</div>
<div class="items">
<div data-filter-item data-filter-name="apple+iphone+california">Apple</div>
<div data-filter-item data-filter-name="google+nexus">Google</div>
<div data-filter-item data-filter-name="microsoft">Microsoft</div>
</div>
</div>

You can just grab all items and use string.indexOf on each item's data to check the presence of a string in a string.
$('[data-filter-item][data-filter-name]').each(function(element){
var isPresent = $(this).data('filter-name').indexOf(searchVal.toLowerCase()) > -1;
if(isPresent){
// do something
} else {
// do something else
}
});

Related

Change class with data-target

I have tried this:
$(".font").click(function() {
var target = $($(this).data("target"));
$("#text").addClass(target);
})
.pap {
font-family: Papyrus;
}
.ar {
font-family: Arial;
}
.hel {
font-family: Helvetica,
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="font" data-target=".pap">Papyrus</button>
<button class="font" data-target=".ar">Arial</button>
<button class="font" data-target=".hel">Helvetica</button>
<div id="text" class="ar">Text</div>
Unfortunately, it doesn't work to change the classes by clicking a button. Is it just a little mistake or does this logic not work at all?
Three problems:
Wrapping $(this).data("target"),
Including class selector . in target dataset: data-target=".pap",
Adding class rather than replacing class:
$(".font").click(function() {
var target = $(this).data("target"); // no double $ wrap
// replace class because the first class listed takes precedence
$("#text").attr('class', target);
})
.pap {
font-family: Papyrus;
}
.ar {
font-family: Arial;
}
.hel {
font-family: Helvetica,
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- notice no "dot" classname -->
<button class="font" data-target="pap">Papyrus</button>
<button class="font" data-target="ar">Arial</button>
<button class="font" data-target="hel">Helvetica</button>
<div id="text" class="ar">Text</div>

Replace values in an array dynamically

I have a scenario like this. Say: let a = [2,5,6] and let b = [1,2,3,4,5,6,7,8]. Array b is displayed in boxes and revealed when one clicks any of the boxes. What I am trying to do is, when one clicks on any box and the value is the same as any value in array a, I replace the value with other unique values and if they're not the same I display as it is.
e.g. If I click a box that has a value of 2 or 5 or 6 i replace the values with the other values.
A minimal example is:
new Vue({
el: "#app",
data: {
a: [2,5,6],
b: [1,2,3,4,5,6,7,8]
},
methods: {
replaceNumber() {
// function to replace the values
}
}
})
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
.numbers {
display: flex;
}
li {
list-style-type: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<h2>Numbers:</h2>
<br/>
<ul class="numbers">
<li v-for="num in a">
{{num}}
</li>
</ul>
<br/>
<template>
<button #click="replaceNumber" v-for="number in b">
{{ number }}
</button>
</template>
</div>
Use indexOf() to locate the position of the element you want to replace.
Then use splice() together with the index you got to remove that element.
Then use splice() again to insert a new value to the same index.
Check the documentation of each method above to understand their syntax.
You can try with random numbers if found in first array i.e a
var a = [2,5,6]
var b = [1,2,3,4,5,6,7,8]
a.forEach(function(e){
$("#aDiv").append(`<h2>${e}</h2>`);
})
b.forEach(function(e){
$("#bDiv").append(`<h2 class="seconddiv">${e}</h2>`);
});
$(".seconddiv").on('click',function(){
let val= $(this).html();
if(a.includes(parseInt(val))){
var uniqueNo = 0;
do {
uniqueNo=getRandomInt(0,10);
}
while (a.includes(parseInt(uniqueNo)));
$(this).html(uniqueNo);
}
})
let getRandomInt= (x,y)=>x+(y-x+1)*crypto.getRandomValues(new Uint32Array(1))[0]/2**32|0
#aDiv,#bDiv{
color:yellow;
background-color:black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="maindiv">
<div id="aDiv">
</div>
<div id="bDiv" style="margin-top:50px;">
</div>
</div>

Using template strings to append HTML

New to es6, is there a way to append HTML using template literals `` in the DOM without overwriting what was currently posted?
I have a huge block of HTML that I need to post for a list that is being created. Where a user is able to post their input.
Every-time the task is submitted it overwrites the current submission. I need it to append underneath.
fiddle for demonstration purpose.
https://jsfiddle.net/uw1o5hyr/5/
<div class = main-content>
<form class ='new-items-create'>
<label>Name:</label><input placeholder=" A Name" id="name">
<button class = "subBtn">Submit</button>
</form>
</div>
<span class="new-name"></span>
JavaScript
form.addEventListener('submit',addItem);
function addItem(event){
event.preventDefault();
let htmlStuff =
`
<div class="main">
<div class="a name">
<span>${name.value}</span>
</div>
<div>
`
itemCreated.innerHTML = htmlStuff;
}
insertAdjacentHTML() adds htmlString in 4 positions see demo. Unlike .innerHTML it never rerenders and destroys the original HTML and references. The only thing .innerHTML does that insertAdjacentHTML() can't is to read HTML. Note: assignment by .innerHTML always destroys everything even when using += operator. See this post
const sec = document.querySelector('section');
sec.insertAdjacentHTML('beforebegin', `<div class='front-element'>Front of Element</div>`)
sec.insertAdjacentHTML('afterbegin', `<div class='before-content'>Before Content</div>`)
sec.insertAdjacentHTML('beforeend', `<div class='after-content'>After Content</div>`)
sec.insertAdjacentHTML('afterend', `<div class='behind-element'>Behind Element</div>`)
* {
outline: 1px solid #000;
}
section {
margin: 20px;
font-size: 1.5rem;
text-align: center;
}
div {
outline-width: 3px;
outline-style: dashed;
height: 50px;
font-size: 1rem;
text-align: center;
}
.front-element {
outline-color: gold;
}
.before-content {
outline-color: blue;
}
.after-content {
outline-color: green;
}
.behind-element {
outline-color: red;
}
<section>CONTENT OF SECTION</section>
You can just use += to append:
document.getElementById('div').innerHTML += 'World';
<div id="div">
Hello
</div>
Element.prototype.appendTemplate = function (html) {
this.insertAdjacentHTML('beforeend', html);
return this.lastChild;
};
If you create the element prototype as per above, you can get the element back as reference so you can continue modifying it:
for (var sectionData of data) {
var section = target.appendTemplate(`<div><h2>${sectionData.hdr}</h2></div>`);
for (var query of sectionData.qs) {
section.appendTemplate(`<div>${query.q}</div>`);
}
}
Depending on how much you're doing, maybe you'd be better off with a templating engine, but this could get you pretty far without the weight.

How do I show and hide certain divs on page?

I am trying to show and hide certain divs within my document.
I have put together code using getElementById and want to apply style.display to each element of array. I am not sure if this is possible.
Currently my code looks like this:
Javascript
<script>
function chart1() {
var show = new array ["#chartdiv1", "#unit-price"];
document.getElementByid("graph-container").show.style.display = "inline";
var hide = new array ["#chartdiv2", "#unit-price-value",
"#chartdiv3", "#unit-price-value"];
document.getElementByid("graph-container").hide.style.display = "none";
};
</script>
HTML
<div id="graph-container">
<!-- Unit Price Dollar -->
<div id="unit-price" style="text-align: center; font-family:'Trebuchet MS', Arial, Helvetica, sans-serif; font-size: 14px; color: #666; clear: both; margin-bottom: 20px;">VPM Global Select Opportunities Fund - Dollar Unit Price
<br>Weekly: 2012/02/03 to 2014/10/24</div>
<div id="chartdiv1" style="width:100%; height:600px;"></div>
<!-- Unit Price Dollar Target Return -->
<div id="unit-price-value" style="text-align: center; font-family:'Trebuchet MS', Arial, Helvetica, sans-serif; font-size: 14px; color: #666; clear: both; margin-bottom: 20px;">Value of $1000 Invested at inception relative to Target Return
<br>Weekly: 2012/02/03 to 2014/10/24</div>
<div id="chartdiv2" style="width:100%; height:600px;"></div>
<!-- Unit Price Rand Versus Inflation -->
<div id="unit-price-rand" style="text-align: center; font-family:'Trebuchet MS', Arial, Helvetica, sans-serif; font-size: 14px; color: #666; clear: both; margin-bottom: 20px;">Value of R1000 Invested at inception relative to Inflation Benchmarks
<br>Weekly: 2012/02/03 to 2014/10/24</div>
<div id="chartdiv3" style="width:100%; height:600px;"></div>
<div style="text-align: center; font-family:'Trebuchet MS', Arial, Helvetica, sans-serif; font-size: 12px; color: #666; clear: both; margin-top: 20px;">
<br>* VPM GSO - VPM Global Select Opportunities Fund</div>
<br>
</div>
<!-- End Graph Container-->
Original Javascript that works in IE11, Safari, Opera, FireFox and Chrome
This is the orignal code I created it worked in all the browsers except IE8-10, maybe someone can guide me on this.
function chart1() {
document.getElementById("chartdiv1").style.display = "inline";
document.getElementById("unit-price").style.display = "block";
document.getElementById("chartdiv2").style.display = "none";
document.getElementById("unit-price-value").style.display = "none";
document.getElementById("chartdiv3").style.display = "none";
document.getElementById("unit-price-rand").style.display = "none";
};
</script>
You help is greatly appreciated.
I think that what you are trying to do is this:
function chart1() {
var show = ["chartdiv1", "unit-price"];
for ( var i = 0; i < show.length; ++i )
document.getElementById(show[i]).style.display = "inline";
var hide = ["chartdiv2", "unit-price-value","chartdiv3", "unit-price-value"];
for ( var i = 0; i < hide.length; ++i )
document.getElementById(hide[i]).style.display = "none";
};
In this way you itearate over the two arrays so that the elements in show are shown and the others are hidden.
The problems were:
the IDs if you use plain js and not css or jQuery are without the #
The correct syntax for array is Array
You have to iterate over the elements in order to hide/show each of them
You have to remove the hide/show after the getElementById selection, because in that way you are accessing to a property inside that Object
You are mixing pure JS and JQuery.
hide() and show() in JQUery
So, for you: $("#graph-container").hide();
style.display = "none"; in pure JS
So, for you: document.getElementByid("graph-container").style.display = "none";
For the difference between hidden and none: What is the difference between visibility:hidden and display:none?
Try using this, it should work.
document.getElementById("graph-container").style.visibility="visible"; //Show the container
var hide = new array ["#chartdiv2", "#unit-price-value","#chartdiv3", "#unit-price-value"];
document.getElementById("graph-container").style.visibility="hidden"; //Hide the container
Try this, using javascript
document.getElementById("<your tag id>").style.visibility = "hidden";
And again to show the element, you can use,
document.getElementById("<your tag id>").style.visibility = "visible";
A small demontration i submitted in Snippet. Check if it helps you.
<html>
<body>
<div id="myP">This is a p element.</div>
<button type="button" onclick="myFunction()">Hide content of div</button>
<button type="button" onclick="myFunction1()">Show content of div</button>
<script>
function myFunction() {
document.getElementById("myP").style.visibility = "hidden";
}
function myFunction1() {
document.getElementById("myP").style.visibility = "visible";
}
</script>
</body>
</html>
Using Jquery, you can use show() and hide() method.
JQuery show and hide method

jquery - showing box with if statement by click on button when field is completed - quiz creation

I'm desperately trying to create something very simple for you!
Here's my problem:
I'd like to create a small quiz in which when someone writes anything in a field (), and then click the button "ok" (not sure if I should use a or a ), then 3 possibilities arise (for each case a box appearing under the field input):
The answer is exact and correctly written: then the text will be "Great job!"
The answer is almost correct, meaning that the word is not correctly written (we can define if necessary "almost answers"): the text will be "Almost there..."
The answer is completely wrong, the text will be "Try again!"
Right now I have that:
<body>
<div>
<table>
<tbody>
<tr>
<td>To whom it belongs?</td>
</tr>
<tr>
<td>
<img src="#" alt="Tim's coat" width="100%"/>
</td>
</tr>
<tr>
<td class="answer-box">
<input type="text" class="field-answer" placeholder="Write it there!">
<button id="showresult" class="button-answer" value="Ok">OK</button>
</td>
</tr>
<tr>
<td>
<div class="res" id="switch">Great job!</div>
<div class="res" id="switch2">Almost there...</div>
<div class="res" id="switch3">Try again!</div>
</td>
</tr>
</tbody>
</table>
</div>
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script type="text/javascript">
var artist = ["abba"];
var almostartist = ["abaa", "aaba", "aabaa"];
$(document).ready(function(){
$('.field-answer').bind('keyup', function(){
if("#showresult").click(function() {
if($.inArray($(this).val().toLowerCase().trim().replace(/[^\w\s\-\_!##\$%\^\&*\\")\(+=._-]/g, ''), artist) >= 0){
$('#switch').show('good');
}
else if($.inArray($(this).val().toLowerCase().trim().replace(/[^\w\s\-\_!##\$%\^\&*\\")\(+=._-]/g, ''), almostartist) >= 0){
$('#switch2').addClass('soso');
if{
$('#switch3').addClass('non');
}
else {
$('#switch3').removeClass('non');
}
});
});
}
</script>
But of course this is not working...
In case, my CSS is here:
.res {
display: none;
color: white;
font-weight: bold;
text-align: center;
background-color: #490058;
height: 75px;
max-width: 100%;
line-height: 70px;
font-size: 140%;
}
.res.good {
display: block;
}
.res.soso {
display: block;
}
.res.non {
display: block;
}
.answer-box {
text-align: center;
}
.button-answer {
border: none;
background-color: #490058;
color: white;
font-size: 120%;
font-weight: bold;
padding: 8px;
left: 260px;
}
.field-answer {
text-align: center;
border: none;
border-bottom: 2px solid black;
background-color: transparent;
max-width: 230px;
height: 40px;
font-size: 20px;
text-transform: uppercase;
outline: 0;
}
Someone could help me to figure that out, please?
I'm quite sure I'm not far, but cannot solve it...
If you need more precisions on stuffs, please don't hesitate! ;)
Thanks guys!
Baptiste
A slightly different approach - no better than any other suggestion - FIDDLE.
JS
var artist = ["abba"];
var almostartist = ["abaa", "aaba", "aabaa"];
$('.field-answer').focus(function(){
$('.res').css('display', 'none');
$(':input').val('');
});
$('#showresult').on('click', function(){
useranswer = $('.field-answer').val();
useranswer = useranswer.toLowerCase().trim().replace(/[^\w\s\-\_!##\$%\^\&*\\")\(+=._-]/g);
if( $.inArray( useranswer, artist ) === 0 )
{
$('#switch1').css('display', 'block');
}
else if ( $.inArray( useranswer, almostartist ) >= 0 )
{
$('#switch2').css('display', 'block');
}
else //if ( $.inArray( useranswer, almostartist ) < 0 )
{
$('#switch3').css('display', 'block');
}
});
your whole function is bound in to 'keyup' event.
keyup event only occurs once when key is released from pressed.
try deleting bind('keyup', function)
I've found a solution to your problems.
Check this Fiddle
In this script every time you click on the button the field text is compared with the values of the array
Depending on the value of the the corrisponding div is showed.
code
<script type="text/javascript">
$(document).ready(function(){
var artist = ["abba"];
var almostartist = ["abaa", "aaba", "aabaa"];
$("#showresult").click(function() {
var text=$('.field-answer').val();
if(artist.indexOf(text) > -1){
$('#switch').show();
}
else if(almostartist.indexOf(text) > -1){
$('#switch2').show();
}
else{$('#switch3').show();}
});
});
</script>
if you want the message appears on keyup you have to use this code
<script type="text/javascript">
$(document).ready(function(){
var artist = ["abba"];
var almostartist = ["abaa", "aaba", "aabaa"];
$(".field-answer").on('keyup',function() {
$('.res').hide()
var text=$('.field-answer').val().toLowerCase();
if(artist.indexOf(text) > -1){
$('#switch').show();
}
else if(almostartist.indexOf(text) > -1){
$('#switch2').show();
}
else{$('#switch3').show();}
});
});
</script>
If you like one of these solutions remember to falg in green my answer ;) thanks.

Categories