Javascript how to use function match()? - javascript

I have a problem with my javascript code in a word search. Let me explain:
I have an HTML page like this:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>xPression Reports</title>
<link href="index.css" rel="stylesheet" type="text/css" />
</head>
<body>
<button>Accueil</button>
<div id="myBtnContainer">
<button class="btn active" onclick="filterSelection('all')">Show all</button>
<button class="btn" onclick="filterSelection('bis')">bis</button>
<button class="btn" onclick="filterSelection('bis.xindd')">bis.xindd</button>
</div>
<div class="container">
<div class=" filterDiv bis" >bis 2017/06</div>
<div class=" filterDiv bis" >bis 2017/07</div>
<div class=" filterDiv bis.xindd" >bis.xindd 2017/06</div>
<div class=" filterDiv bis.xindd" >bis.xindd 2018/01</div>
</div>
<script src="index.js"></script>
</body>
</html>
(I simplified it)
with CSS:
body{
background-color: #d3d3d3;
}
.container {
overflow: hidden;
}
.filterDiv {
float: left;
color: black;
border: 1px solid black;
width: auto;
text-align: center;
margin: 2px;
display: none; /* Hidden by default */
}
/* The "show" class is added to the filtered elements */
.show {
display: block;
}
/* Style the buttons */
.btn {
border: none;
outline: none;
background-color: #f1f1f1;
cursor: pointer;
}
/* Add a light grey background on mouse-over */
.btn:hover {
background-color: #ddd;
}
/* Add a dark background to the active button */
.btn.active {
background-color: #666;
color: white;
}
img {
width:50px;
}
and a javascript:
filterSelection("all")
function filterSelection(c) {
var x, i;
x = document.getElementsByClassName("filterDiv");
if (c == "all") c = "";
// Add the "show" class (display:block) to the filtered elements, and remove the "show" class from the elements that are not selected
for (i = 0; i < x.length; i++) {
w3RemoveClass(x[i], "show");
if (x[i].matches(c) > -1) w3AddClass(x[i], "show");
}
}
// Show filtered elements
function w3AddClass(element, name) {
var i, arr1, arr2;
arr1 = element.className.split(" ");
//alert(arr1);
arr2 = name.split(" ");
//alert(arr2);
for (i = 0; i < arr2.length; i++) {
if (arr1.indexOf(arr2[i]) == -1) {
element.className += " " + arr2[i];
}
}
}
// Hide elements that are not selected
function w3RemoveClass(element, name) {
var i, arr1, arr2;
arr1 = element.className.split(" ");
//alert(arr1);
arr2 = name.split(" ");
//alert(arr2);
for (i = 0; i < arr2.length; i++) {
while (arr1.indexOf(arr2[i]) > -1) {
arr1.splice(arr1.indexOf(arr2[i]), 1);
}
}
element.className = arr1.join(" ");
}
// Add active class to the current control button (highlight it)
var btnContainer = document.getElementById("myBtnContainer");
var btns = btnContainer.getElementsByClassName("btn");
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener("click", function() {
var current = document.getElementsByClassName("active");
current[0].className = current[0].className.replace(" active", "");
this.className += " active";
});
}
Everything works as it should be that when I click on a button, only the frames corresponding to the button are displayed. However for 6 of them do not work for example with bis and bis.xindd, I think it because the js take only "bis" for searching and so when I click on "bis", bis and bis.xindd are displaying.
And I think the mistake comes from this function:
filterSelection("all")
function filterSelection(c) {
var x, i;
x = document.getElementsByClassName("filterDiv");
if (c == "all") c = "";
// Add the "show" class (display:block) to the filtered elements, and remove the "show" class from the elements that are not selected
for (i = 0; i < x.length; i++) {
w3RemoveClass(x[i], "show");
if (x[i].matches(c) > -1) w3AddClass(x[i], "show");
}
}
I saw information on Regex and especially the function ma * tch but I do not see how the used here
thank you in advance for your help

A working solution for your filter list would look like this: https://jsfiddle.net/jkrielaars/szagq5hm/31/
However: Periods in a class name is not a good idea.
Here is why your code is not working:
On https://developer.mozilla.org/en-US/docs/Web/API/Element/matches it states that the argument should be the element selector string. Having a period in your classname is going to mess this up.
You need to add the period to indicate you're dealing with a class, however, since you also have a period in the classname you will have this as a result: ".bis.xindd".
If you see that as a selector string, it means an element with both .bis and .xindd classes. This is not what you are aiming for.
Is you insist on using periods in your classnames, have a look at .classList.contains().
Below you can see how this differs from .matches().
var test1 = document.getElementById('test1')
var test2 = document.getElementById('test2')
console.debug('matches does not work without the class period', test1.matches('bis'));
console.debug('matches does not work without the class period', test2.matches('bis.xindd'));
console.debug('matches does work with the class period', test1.matches('.bis'));
console.debug('matches does not work with a class name with a period in it', test2.matches('.bis.xindd'));
console.debug('test1 should contain bis', test1.classList.contains("bis"));
console.debug('test 2 should contain bis.xindd', test2.classList.contains("bis.xindd"));
console.debug('test2 should not match with just "bis"', test2.classList.contains("bis"));
<div id="test1" class="filterDiv bis">bis 2017/06</div>
<div id="test2" class="filterDiv bis.xindd" >bis.xindd 2017/06</div>

Related

Make same active button after reload

Right now, I have two buttons that each button have different views.
<div style="margin-top:-25px;margin-left:105px;">
<p style="color:black;"><b>View In : </b></p>
<div class="btnContainer" id="btnContainer">
<button class="lists active" onclick="gridView()"> Grid</button>
<button class="lists" onclick="listView()" style="margin-left:-4px;"> List</button>
</div>
</div>
<div class="row" id="pading1">
<!------------- Card Position 1 ----------------->
</div>
<div class="row" id="pading2">
<!------------- Card Position 2 ----------------->
</div>
Here's the css script to styling the button
/* Style the buttons grid */
.lists {
border: none;
outline: none;
padding: 5px 10px;
background-color: #ffffff;
cursor: pointer;
width: 100px;
}
.lists:hover{
background-color: #ddd;
}
.lists.active {
background-color: #01b1ea;
color: white;
}
.btnContainer{
background-color:transparent;
width:200px;
margin-top:-35px;
margin-left:70px;
}
Here's js script to switch the view every page
<!------------------- Switch Padding Button Grid Maps ------------------->
<script>
function listView(){
$("#pading1").hide();
$("#pading2").show();
$(".search-container").hide();
}
function gridView(){
$("#pading1").show();
$("#pading2").hide();
}
var container = document.getElementById("btnContainer");
var btns = container.getElementsByClassName("lists");
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener("click", function() {
var current = document.getElementsByClassName("active");
current[0].className = current[0].className.replace(" active", "");
this.className += " active";
});
}
</script>
Right now, every I reload the page it still going to grid view as I set grid view is the default.
I want to ask, when I in list view and I refresh the web, how to make the button active is still in the list view ?
Thank you
You can do this either by setting a sessionStorage / localStorage or a cookie. This is a working example using sessionStorage:
// Check what type of view we have setup
if(sessionStorage.view == 'list') {
listView();
}
else {
gridView();
}
function listView(){
$("#pading1").hide();
$("#pading2").show();
$(".search-container").hide();
sessionStorage.view = "list";
}
function gridView(){
$("#pading1").show();
$("#pading2").hide();
sessionStorage.view = "grid";
}
var container = document.getElementById("btnContainer");
var btns = container.getElementsByClassName("lists");
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener("click", function() {
var current = document.getElementsByClassName("active");
current[0].className = current[0].className.replace(" active", "");
this.className += " active";
});
}

show/hide elements and switch between them js

I have two elements that are hidden. When button a is clicked, I would like div a to show. When button b is clicked, I would like div a to close and div b to show.
However, if button a is clicked a second time after being shown, I would like it to hide the div again. Same with button b.
Update:
I was able to get the buttons to toggle properly.
However, upon initial loading, I want them to be hidden, or not visible until the button is clicked.
The following is my current javascript
function openFamily(evt, famName) {
var i, x, y, tablinks;
x = document.getElementsByClassName("family");
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
tablinks = document.getElementsByClassName("familytablink");
for (i = 0; i < x.length; i++)
document.getElementById(famName).style.display = "block";
}
I have a CSS element:
.container{
display: none;
}
HTML:
<div>
<div>
<button class="familytablink" onclick="openFamily(event,'zep')">Zephaniah</button>
<button class="familytablink" onclick="openFamily(event,'anna')">Anna</button>
</div>
<div id="zep" class="container mainp-2 family">
filler text
</div>
<div id="anna" class="container mainp-2 family">
filler text
</div>
</div>
Here's an exemple of how you can achieve that
var toggleDivById = function (id) {
var div = document.getElementById(id);
if (div.classList.contains('active')) {
return div.classList.remove('active');
}
div.classList.add('active');
}
var handleToggleClick = function (event) {
var targetId = event.target.dataset.target;
toggleDivById(targetId);
}
document.querySelectorAll('.toggle')
.forEach(function(toggle) {
toggle.addEventListener('click', handleToggleClick)
})
.toggable {
width: 50px;
height: 50px;
background-color: crimson;
border: 2px solid tomato;
visibility: hidden;
transition: all 100ms ease-out;
border-radius: 5px;
box-shadow: 1px 1px 2px indianred;
}
.toggable.active {
visibility: visible
}
<button data-target="a" class="toggle">A</button>
<button data-target="b" class="toggle">B</button>
<hr/>
<div id="a" class="toggable">A</div>
<div id="b" class="toggable">B</div>
In jQuery:
<script type="application/javascript">
$(document).ready(function(){
$("#button1").click(function(){
$("diva").show();
});
$("#button2").click(function(){
$("diva").hide();
$("divb").show();
});
});
</script>
In JS:
<script type="application/javascript">
function myFunction() {
var x = document.getElementById("myDIV");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
</script>
You can use hide and show function in Jquery and use it when a button is clicked something like this :
like
$("selector").click(function(){
$("divid").hide();
$("divid").show();
})

How do I select which div element to show initially when I am filtering divs based on their class name?

I have filtered a set of divs below based on their class name.
This works well when I am selecting a filter button, however initially they all show.
I would like just the "2017" class to show.
Here is the code:
* filter elements*/
filterSelection("all")
function filterSelection(c) {
var x, i;
x = document.getElementsByClassName("filterDiv");
if (c == "all") c = "";
// Add the "show" class (display:block) to the filtered elements, and remove the "show" class from the elements that are not selected
for (i = 0; i < x.length; i++) {
w3RemoveClass(x[i], "show");
if (x[i].className.indexOf(c) > -1) w3AddClass(x[i], "show");
}
}
// Show filtered elements
function w3AddClass(element, name) {
var i, arr1, arr2;
arr1 = element.className.split(" ");
arr2 = name.split(" ");
for (i = 0; i < arr2.length; i++) {
if (arr1.indexOf(arr2[i]) == -1) {
element.className += " " + arr2[i];
}
}
}
// Hide elements that are not selected
function w3RemoveClass(element, name) {
var i, arr1, arr2;
arr1 = element.className.split(" ");
arr2 = name.split(" ");
for (i = 0; i < arr2.length; i++) {
while (arr1.indexOf(arr2[i]) > -1) {
arr1.splice(arr1.indexOf(arr2[i]), 1);
}
}
element.className = arr1.join(" ");
}
// Add active class to the current control button (highlight it)
var btnContainer = document.getElementById("myBtnContainer");
var btns = btnContainer.getElementsByClassName("btn");
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener("click", function() {
var current = document.getElementsByClassName("active");
current[0].className = current[0].className.replace(" active", "");
this.className += " active";
});
}
.container {
overflow: hidden;
}
.myBtnContainer{
margin-top: 30px;
}
.filterDiv {
display: none; /* Hidden by default */
}
/* The "show" class is added to the filtered elements */
.show {
display: block;
}
/* Style the buttons */
.btn {
border: none;
outline: none;
padding: 12px 16px;
background-color: white;
display: inline;
width: 20%;
color: #1d1d1b;
}
.btn:focus,
.btn:hover{
background-color: white;
opacity: 0.4;
color: #1d1d1b;
}
<div id="myBtnContainer">
<button class="btn" onclick="filterSelection('2013')"> 2013</button><button class="btn" onclick="filterSelection('2014')"> 2014</button><button class="btn" onclick="filterSelection('2015')"> 2015</button><button class="btn" onclick="filterSelection('2016')"> 2016</button><button class="btn active" onclick="filterSelection('2017')"> 2017</button>
</div>
<div class="container">
<div class="wine-row filterDiv 2013">
<img class="wine-bottle" src="http://chateau.flywheelsites.com/wp-content/uploads/2018/08/CUV-SASHA_2014.png" />
</div>
<div class="wine-row filterDiv 2014">
<img class="wine-bottle" src="http://chateau.flywheelsites.com/wp-content/uploads/2018/08/CUV-SASHA_2014.png" />
</div>
<div class="wine-row filterDiv 2015">
<img class="wine-bottle" src="http://chateau.flywheelsites.com/wp-content/uploads/2018/08/CUV-SASHA_2014.png" />
</div>
<div class="wine-row filterDiv 2016">
<img class="wine-bottle" src="http://chateau.flywheelsites.com/wp-content/uploads/2018/08/CUV-SASHA_2014.png" />
</div>
<div class="wine-row filterDiv 2017">
<img class="wine-bottle" src="http://chateau.flywheelsites.com/wp-content/uploads/2018/08/CUV-SASHA_2014.png" />
</div>
</div>
All of the years show initial in a list, and it is not until I select a year from the navigation that the items filter, I would like them to be filtered from the start, showing only the 2017 elements.
Well from your HTML file i see that you have already named your class and you added a filterDiv 2017 which is sufficient to filter it. You can also create an ID for each div so that you can change the preferred Div by altering with the ID.

Javascript To Toggle Multiple Buttons

I have some Javascript code that targets multiple buttons. When clicked, the content should appear, which it does. However, i'm struggling to create the code that when the buttons are clicked again, the content is hidden.
I've included the Javascript, content and css for the elements i want to be toggled. Cheers.
Note: Code has to be in Javascript
function openTab(click, openTab) {
var i, content, link;
content = document.getElementsByClassName("content");
for (i = 0; i < content.length; i++) {
content[i].style.display = "none";
}
links = document.getElementsByClassName("links");
for (i = 0; i < links.length; i++) {
links[i].className = links[i].className.replace(" active", "");
}
document.getElementById(openTab).style.display = "block";
click.currentTarget.className += " active";
}
.content {
font-family: 'Lato';
max-width: 100%;
font-size: 20px;
letter-spacing: 4px;
color: #e8eaed;
display: none;
border-top: none;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
<section class = "Container">
<div class="tabs">
<button class="link" onclick="openTab(event, 'About')">About</button>
<button class="link" onclick="openTab(event, 'Hire')">Why You Should Hire Me</button>
<button class="link" onclick="openTab(event, 'Contact')">Contact</button>
</div>
</section>
<section class="Container2">
<div id="About" class="content">About</div>
<div id="Hire" class="content">Hire</div>
<div id="Contact" class="content">Contact</div>
</section>
Declare a variable which represents whether the elements are hidden or not. Also, you could try to use classList to add/remove classes from elements with multiple class names, rather than className string manipulation, if at all possible.
You can use classList.toggle to easily switch classes:
let hidden = false;
function openTab(click, openTabId) {
document.querySelectorAll('.content').forEach(
content => content.style.display = hidden ? 'block' : 'none'
);
document.querySelectorAll('.links').forEach(
link => link.classList.toggle('active')
);
document.getElementById(openTabId).style.display = "block";
click.currentTarget.classList.toggle('active');
hidden = !hidden;
}
Better yet, encapsulate the hidden variable in openTab, since it's not useful in the outer scope:
const openTab = (() => {
let hidden = false;
return (click, openTabId) => {
document.querySelectorAll('.content').forEach(
content => content.style.display = hidden ? 'block' : 'none'
);
document.querySelectorAll('.links').forEach(link => {
if (hidden) link.classList.add('active');
else link.classList.remove('active');
});
document.getElementById(openTabId).style.display = "block";
click.currentTarget.classList.toggle('active');
hidden = !hidden;
}
})();

dynamically Adding and removing elements based on checkbox values with DOM

I'm just trying to dynamically add to a div within a form depending on which checkboxes are checked. So, I am creating the li tag and then they are added as li elements within an ol parent element so its just a list of values. I do not know what is wrong with my code, I'm not sure how to remove the appropriate value if the relevant checkbox is unchecked, and when I uncheck and then recheck a checkbox, it keeps adding the value over and over again.
<!DOCTYPE html>
<html>
<head>
<title></title>
<style>
input {
margin: 18px;
}
#o {
list-style-type: none;
}
.u {
list-style: none;
}
</style>
</head>
<body style="width: 700px">
<div style="float: left; width: 340px; height: 250px; border: 1px solid black; padding: 20px 0 10px 20px;">
<form id="myForm">
<ul class="u">
<li><input id="showAlert1" type="checkbox" name="thing" value="laptop">laptop</li>
<li><input id="showAlert2" type="checkbox" name="thing" value="iphone">iphone</li>
</ul>
</form>
</div>
<div id="myDiv" style="float: right; width: 317px; height: 250px; border: solid black; border-width: 1px 1px 1px 0; padding: 20px 0 10px 20px;">
<ol id="o">
</ol>
</div>
<script>
document.getElementById('myForm').addEventListener('change', function () {
var a = document.getElementsByName('thing');
for (var i = 0; i < a.length; i++) {
if (a[i].checked){
createDynamicElement();
} else if (!a[i].checked){
removeDynamicElement();
}
}
function createDynamicElement(){
var node = document.createElement("LI");
node.setAttribute("id1", "Hey");
var textnode = document.createTextNode(event.target.nextSibling.data);
node.appendChild(textnode);
document.getElementById("o").appendChild(node);
}
function removeDynamicElement() {
document.querySelector("#o li").innerHTML = "";
}
});
</script>
</body>
</html>
It looks like that you are adding an event listener to the form instead of the input elements themselves. I dont think the change event will be fired when an input element in a form changes. (see: https://developer.mozilla.org/en-US/docs/Web/Events/change)
On your event listener, try targeting the input elements themselves.
} else if (!a[i].checked){
removeDynamicElement();
}
...
function removeDynamicElement() {
document.querySelector("#o li").innerHTML = "";
}
Will empty the first or all matches(not sure) but wont remove them. Instead you should give li tags a unique ID and remove them completely via something like:
for (var i = 0; i < a.length; i++) {
if (a[i].checked){
console.log(a[i])
createDynamicElement(a[i].value);
} else if (!a[i].checked){
removeDynamicElement(a[i].value);
}
}
function createDynamicElement(id){
var node = document.createElement("LI");
node.setAttribute("id", id);
var textnode = document.createTextNode(id);
node.appendChild(textnode);
console.log(node)
document.getElementById("o").appendChild(node);
}
function removeDynamicElement(id) {
var target = document.getElementById(id)
target.parentElement.removeChild(target);
}
Or you could clear the ol completely on every change and repopulate it again like:
var a = document.getElementsByName('thing');
document.getElementById("o").innerHTML = null;
for (var i = 0; i < a.length; i++) {
if (a[i].checked){
console.log(a[i])
createDynamicElement(a[i].value);
}
}
function createDynamicElement(id){
var node = document.createElement("LI");
var textnode = document.createTextNode(id);
node.appendChild(textnode);
console.log(node)
document.getElementById("o").appendChild(node);
}
Edit:
A proper FIFO solution:
var a = document.getElementsByName('thing');
for (var i = 0; i < 2; i++) {
var target = document.getElementById(a[i].value);
if (a[i].checked && !target){
createDynamicElement(a[i].value);
} else if ((!a[i].checked) && target){
removeDynamicElement(a[i].value);
}
}
function createDynamicElement(id){
var node = document.createElement("li");
node.setAttribute("id", id);
var textnode = document.createTextNode(id);
node.appendChild(textnode);
document.getElementById("o").appendChild(node);
console.log("a")
}
function removeDynamicElement(id) {
target.parentElement.removeChild(target);
}
});

Categories