Hide filter element - javascript

I'm having trouble hiding relevant data with JS.
In my code I have data-type = "power" and data-type = "grill" which are added to the products.
I want the script to check sort filters and hide those that are not present on the page.
Unfortunately, when I have two cases, it doesn't work as it should.
Grill filters do not appear even though they should.
$('.stat').on('click', function() {
var $stats = $('.stat:checked');
var $items = $('.list .product');
$items.show();
if ($stats.length == 0)
return;
var $vstats = $.map($stats, function(o) {
return $(o).data('id');
});
$stats.each(function() {
var $stat = $(this);
$items.filter(function() {
var $currentitem = $(this).data($stat.data('type'));
if ($currentitem.toString().indexOf(",") > -1) {
var $item = $currentitem.split(",");
var hit = 0;
$item.forEach(function(m) {
if ($vstats.indexOf(m) > -1) {
hit++;
}
});
if (hit > 0) {
return false;
} else {
return true;
}
} else {
if ($vstats.indexOf($currentitem) > -1) {
return false;
} else {
return true;
}
}
}).hide();
})
});
var powers = $('[data-power]').map(function() {
return this.dataset.power;
}).get();
var grills = $('[data-grill]').map(function() {
return this.dataset.grill;
}).get();
$('[data-id]').filter(function() {
return !powers.includes(this.dataset.id)
return !grills.includes(this.dataset.id)
}).closest("label").hide();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="power">
<h2>power</h2>
<div class="checkbox">
<label>
<input data-id="750" data-type="power" class="stat power" type="checkbox">750
</label>
<label>
<input data-id="800" data-type="power" class="stat power" type="checkbox">800
</label>
<label>
<input data-id="1200" data-type="power" class="stat power" type="checkbox">1200
</label>
</div>
</div>
<div class="grill">
<h2>grill</h2>
<div class="checkbox">
<label>
<input data-id="yes" data-type="grill" class="stat grill" type="checkbox">yes
</label>
<label>
<input data-id="no" data-type="grill" class="stat grill" type="checkbox">no
</label>
</div>
</div>
<div class="list">
<div class="col-6 col-lg-3 product" data-power="750" data-grill="yes">
<a href="/href/freh">
<div class="product-page__container product-container text-center">
<div class="product-page__name">
<h2><span class="d-block">Product Name</span> Product 1</h2>
</div>
</div>
</a>
</div>
<div class="col-6 col-lg-3 product" data-power="800" data-grill="yes">
<a href="/href/freh">
<div class="product-page__container product-container text-center">
<div class="product-page__name">
<h2><span class="d-block">Product Name 2</span> Product 2</h2>
</div>
</div>
</a>
</div>
</div>

You have to change your filter function. You are returning two values but it stops on first return.
Change
return !powers.includes(this.dataset.id) and return !grills.includes(this.dataset.id)
to
return !powers.includes(this.dataset.id) && !grills.includes(this.dataset.id);
I hope this will solve you problem.

Related

Disable a button if (length < x)

good evening.
I'm a beginner with JavaScript and I'm trying to recreate a specific webpage. There, exists a button that, if the login form doesn't have at least 11 elements on user and 8 on password, the button is disabled.
How can I do this with HTML and JS?
function blockButtonByUser() {
var cpfleng = document.getElementById('.iptuser').length
console.log(cpfleng)
var btnsubmit = document.getElementById('.btnsubmit')
if (cpfleng < 11) {
btnsubmit.disabled = true;
} else {
btnsubmit.disabled = false;
}
}
function blockButtonByPassword() {
var passwordlength = document.getElementById('.iptpassword').length
console.log(cpfleng)
var btnsubmit = document.getElementById('.btnsubmit')
if (passwordlength < 8) {
btnsubmit.disabled = true;
} else {
btnsubmit.disabled = false;
}
}
<header><img src="assets/white.svg" alt="logo nubank" height="80px"></header>
<div class="container">
<h2>Faça seu login</h2>
<div class="form">
<div class="user">
<label for="cpf" class='lbluser'>CPF</label>
<input type="text" name="cpf" id="cpf" class='iptuser'>
<div class="underline"></div>
</div>
<div class="password">
<label for="password" class='lblpassword'>Senha</label>
<input type="password" name="password" id="password" class='iptpassword'>
<div class="underline"></div>
</div>
<input type="submit" value="CONTINUAR" class='btnsubmit'>
</div>
<div class="footer">
<div class="esqueci">
Esqueci minha senha >
</div>
<div class="naocliente">
Ainda não sou cliente >
</div>
</div>
</div>
Thanks for the help!
Here is something like that using an eventListener:
var cpfOkay = false
var passwordOkay = false;
var btnsubmit = document.getElementsByClassName('btnsubmit')[0];
document.getElementById('cpf').addEventListener('input', function(){
btnsubmit = document.getElementsByClassName('btnsubmit')[0];
cpfOkay = false;
if (event.target.value.length >= 11) {
cpfOkay = true;
}
checkBoth();
})
document.getElementById('password').addEventListener('input', function(){
btnsubmit = document.getElementsByClassName('btnsubmit')[0];
passwordOkay = false;
if (event.target.value.length >= 8) {
passwordOkay = true;
}
checkBoth();
})
function checkBoth() {
btnsubmit.disabled = true;
btnsubmit.style.opacity = 0.5;
if (cpfOkay && passwordOkay) {
btnsubmit.disabled = false;
btnsubmit.style.opacity = 1;
}
}
<header><img src="https://placekitten.com/200/300" alt="logo nubank" height="80px"></header>
<div class="container">
<h2>Faça seu login</h2>
<div class="form">
<div class="user">
<label for="cpf" class='lbluser'>CPF</label>
<input type="text" name="cpf" id="cpf" class='iptuser'>
<div class="underline"></div>
</div>
<div class="password">
<label for="password" class='lblpassword'>Senha</label>
<input type="password" name="password" id="password" class='iptpassword'>
<div class="underline"></div>
</div>
<input type="submit" value="CONTINUAR" class='btnsubmit' disabled style="opacity:0.5">
</div>
<div class="footer">
<div class="esqueci">
Esqueci minha senha >
</div>
<div class="naocliente">
Ainda não sou cliente >
</div>
</div>
</div>
You can add event listeners for input event for both the user and password, and based on requirements you can enable or disable the button. You can refactor your code like this:
var cpf = document.getElementById('cpf')
var password = document.getElementById('password')
var btnsubmit = document.getElementById('btnsubmit')
cpf.addEventListener('input', function (evt) {
if(cpf.value.length < 11 || password.value.length < 8){
btnsubmit.disabled = true;
} else {
btnsubmit.disabled = false;
}
});
password.addEventListener('input', function (evt) {
if(cpf.value.length < 11 || password.value.length < 8){
btnsubmit.disabled = true;
} else {
btnsubmit.disabled = false;
}
});
<header><img src="assets/white.svg" alt="logo nubank" height="80px"></header>
<div class="container">
<h2>Faça seu login</h2>
<div class="form">
<div class="user">
<label for="cpf" class='lbluser'>CPF</label>
<input type="text" name="cpf" id="cpf" class='iptuser'>
<div class="underline"></div>
</div>
<div class="password">
<label for="password" class='lblpassword'>Senha</label>
<input type="password" name="password" id="password" class='iptpassword'>
<div class="underline"></div>
</div>
<input type="submit" value="CONTINUAR" class='btnsubmit' id='btnsubmit' disabled>
</div>
<div class="footer">
<div class="esqueci">
Esqueci minha senha >
</div>
<div class="naocliente">
Ainda não sou cliente >
</div>
</div>
</div>
<script src="main.js"></script>
You have a few issues. One was getElementById on classes. One was no event handler. Lastly, you were trying to get the length on the element, but not the length of the value.
This should work:
document.querySelector('.btnsubmit').addEventListener('click', e =>{
blockButtonByUser();
blockButtonByPassword()
})
function blockButtonByUser(){
var cpfleng = document.querySelector('.iptuser').value.length
console.log(cpfleng)
var btnsubmit = document.querySelector('.btnsubmit')
if (cpfleng < 11) {
btnsubmit.disabled = true;
} else{
btnsubmit.disabled = false;
}
}
function blockButtonByPassword(){
var passwordlength = document.querySelector('.iptpassword').value.length
console.log(passwordlength)
var btnsubmit = document.querySelector('.btnsubmit')
if (passwordlength < 8) {
btnsubmit.disabled = true;
} else{
btnsubmit.disabled = false;
}
}

Save values from dynamic form in ReactJS

I am a beginner in Reactjs and I am not finding the best way to save data from a dynamic form in ReactJS.
This form can only display 10 questions per page and when I move forward I have to save the answers on the current page.
Can anybody help me?
I was thinking of putting an ID on the form and then getting the component data....I have one form per component (inputs).
This is how I try to code my function that will save the answers and how I render the dynamic inputs
save = (currentIndex, pageNumber) => {
let {text="", id=""} = this.form.model;
let answerText = text;
if(Array.isArray(answerText)){
text = JSON.stringify(text);
answerText = answerText.filter(item=>!!item)
if(!answerText.length) answerText = "";
else answerText = text;
}
saveAnswerAction({
answerId : id,
text: answerText,
}).then(()=>{
return refresh();
}).catch(e=>{
console.log(e);
});
}
render() {
if (this.state.answers) {
var questions = this.state.answers.toJSON();
var questionsToRender = [];
var qInit = (this.state.currentPage * this.state.quantityQuestionsPerPage) - this.state.quantityQuestionsPerPage;
var qEnd = this.state.currentPage * this.state.quantityQuestionsPerPage;
if (qEnd > questions.length) {
qEnd = qInit + 1;
}
for (var i = qInit; i < qEnd; i++) {
var readOnly = false;
let QuestionRender = QuestionRenderFactory(questions[i], i, readOnly);
questionsToRender.push(<QuestionRender ref={form=>this.form=form} />)
}
return (
<div>
{questionsToRender}
</div>
)
}
else {
return (
<div>
NO QUESTIONS
</div>
)
}
}
render() {
return (
<div className={"formId_" + formId}>
<p className="question">{questionAnswer.question.text} {questionAnswer.question.required ? <span className="question-required">* </span>: null }</p>
{ questionAnswer.question.help && <div className="help">{questionAnswer.question.help}</div> }
<Form
ref={form => this.form = form}
value={this.state.model}
onChange={model => this.setState({ model })}>
{fields}
</Form>
<br />
</div>
)
}
I will have the HTML rendered:
<div class="content">
<h3 class="title">Form</h3>
<h3 class="subtitle">Fields * are required</h3>
<br>
<div>
<div class="formId_0">
<p class="question">
Question 1<span class="question-required">* </span>
</p>
<div class="help">help</div>
<form novalidate="">
<div class="input-container undefined undefined">
<div class="input-wrapper"><input name="text" class=" invalid-field" placeholder="" id="id_1" value="800b7e6e-ce0c-44bb-a4d8-60cffaacb509"><span class="inputError"><span class="validation-error">invalid field</span></span></div>
</div>
</form>
<br>
</div>
<div class="formId_1">
<p class="question">
question 2<span class="question-required">* </span>
</p>
<div class="help">help 2</div>
<form novalidate="">
<div class="input-container undefined undefined">
<div class="input-wrapper">
<input type="text" name="text" class=" " placeholder="" id="id_2" value="www.test.com">
<span class="inputError">
</span>
</div>
</div>
</form>
<br>
</div>
</div>
<div class="buttons"><a class="btn skyBlue" href="/">Home</a><button class="btn-previous">Previous</button><button class="btn-next">Next</button></div>
</div>
You could use localStorage but I don't know if its efficient, secure, or the best route to go

How to check/uncheck 3 secondary checkboxes according to 1 principal checkbox (19times)?

I have 19 cards of 4 checkboxes: 1 main checkbox (date) and 3 secondary checkboxes (options for that date). I would like the 3 secondary options to be checked when the main one is checked and conversely that they are unchecked when the main one is unchecked.
I would like to use a single function for all 19 cards. However, checkboxes have different ids.
When I click on a main checkbox
I get the id from the main checkbox.
I retrieve the number contained in the id.
I apply it to three values to create the id of 3 secondary checkboxes.
If the main checkbox is checked:
I check the secondary checkboxes.
If the main checkbox is unchecked:
I uncheck the secondary checkboxes.
I tried with "onclick" and "onchange".
function Autocheck(id) {
var clicked_id = id;
var StgNbr = clicked_id.substr(4);
var diner = "Dîner" + StgNbr;
var souper = "Souper" + StgNbr;
var logement = "Logement" + StgNbr;
if (clicked_id.checked = true) {
alert('je suis coché');
var items = document.getElementsByClassName('presence');
for (var i = 0; i < items.length; i++) {
if (items[i].id == diner)
items[i].checked = true;
if (items[i].id == souper)
items[i].checked = true;
if (items[i].id == logement)
items[i].checked = true;
}
} else {
alert('je suis décoché');
var items = document.getElementsByClassName('presence');
for (var i = 0; i < items.length; i++) {
if (items[i].id == diner)
items[i].checked = false;
if (items[i].id == souper)
items[i].checked = false;
if (items[i].id == logement)
items[i].checked = false;
}
}
}
<div class="row">
<div class="col-xs-12 col-sm-6 col-md-3 col-lg-3">
<div class="card">
<label for="date1"><div class="card-media"><input type="checkbox" id="date1" class="date presence" name="Dates" onclick="Autocheck(this.id)"> Mardi 23/07</div></label>
<div class="card-details">
<input type="checkbox" class="presence" name="Dîner" id="Dîner1">
<label for="Dîner1"> Dîner</label><br>
<input type="checkbox" class="presence" name="Souper" id="Souper1">
<label for="Souper"> Souper</label><br>
<input type="checkbox" class="presence" name="Logement" id="Logement1">
<label for="Logement"> Logement</label><br>
</div>
</div>
</div>
<div class="col-xs-12 col-sm-6 col-md-3 col-lg-3">
<div class="card">
<label for="date2"><div class="card-media"><input type="checkbox" id="date2" class="date presence" name="Dates" onchange="Autocheck(this.id)"> Mercredi 24/07</div></label>
<div class="card-details">
<input type="checkbox" class="presence" name="Dîner" id="Dîner2">
<label for="Dîner2"> Dîner</label><br>
<input type="checkbox" class="presence" name="Souper" id="Souper2">
<label for="Souper2"> Souper</label><br>
<input type="checkbox" class="presence" name="Logement" id="Logement2">
<label for="Logement2"> Logement</label><br>
</div>
</div>
</div>
My secondary checkboxes are well cheched but they don't uncheck.
Also : my 'test' alert is always saying that the principal checkbox is checked even if I uncheck it.
Thank you for your help.
Here is a click listener and on click of main checkbox we check/uncheck child check boxes. Is this what you are looking for?
const getParentCard = (e, classToMatch) => {
while( e.classList.contains(classToMatch) === false)
{
e = e.parentNode;
}
return e;
};
document.addEventListener('click', (e) => {
if(e.target.matches('input.date')){
getParentCard(e.target,'card').querySelectorAll('input[type="checkbox"]').forEach(chk => {
chk.checked = e.target.checked;
});
}
});
<div class="row">
<div class="col-xs-12 col-sm-6 col-md-3 col-lg-3">
<div class="card">
<label for="date1">
<div class="card-media">
<input type="checkbox" id="date1" class="date presence" name="Dates"> Mardi 23/07
</div>
</label>
<div class="card-details">
<input type="checkbox" class="presence" name="Dîner" id="Dîner1">
<label for="Dîner1"> Dîner</label><br>
<input type="checkbox" class="presence" name="Souper" id="Souper1">
<label for="Souper"> Souper</label><br>
<input type="checkbox" class="presence" name="Logement" id="Logement1">
<label for="Logement"> Logement</label><br>
</div>
</div>
</div>
<div class="col-xs-12 col-sm-6 col-md-3 col-lg-3">
<div class="card">
<label for="date2"><div class="card-media"><input type="checkbox" id="date2" class="date presence" name="Dates"> Mercredi 24/07</div></label>
<div class="card-details">
<input type="checkbox" class="presence" name="Dîner" id="Dîner2">
<label for="Dîner2"> Dîner</label><br>
<input type="checkbox" class="presence" name="Souper" id="Souper2">
<label for="Souper2"> Souper</label><br>
<input type="checkbox" class="presence" name="Logement" id="Logement2">
<label for="Logement2"> Logement</label><br>
</div>
</div>
</div>
There are two main problems in your code:
if (clicked_id.checked = true) {
performs an assignment instead of a comparison but more importantly, clicked_id is a string and string values don't have a checked property. You'd have to access the checked property of the actual element , by either passing the element as argument to the function (preferred) or do
var element = document.getElementById(clicked_id);
//...
if (element.checked) {
// ...
}
Having said that, a more flexible approach that works with any number of check boxes without having to update the code is as follows:
Find closest common ancestor
Find all check boxes within that ancestor
Example:
function Autocheck(element) {
var ancestor = element.closest('.card');
if (ancestor) {
Array.from(ancestor.querySelectorAll('.presence')).forEach(function(input) {
input.checked = element.checked;
});
}
}
and use it as
<input type="checkbox" id="date1" class="date presence" name="Dates" onclick="Autocheck(this)">

Adding more value to class to filter

This is my main script, that filters div by checkboxes
function change(){
var checkboxes = document.getElementsByClassName('checkbox');
var chekboxInputs = Array.from(checkboxes).map(a => a.querySelector('input'));
var allAreUnselected = chekboxInputs.every(function(elem){
return !elem.checked;
});
if(allAreUnselected){
chekboxInputs.forEach(function(input){
Array.from(document.querySelectorAll("." + input.getAttribute("rel"))).forEach(function(item){
item.style.display = 'block';
});
});
}
else {
chekboxInputs.forEach(function(input){
Array.from(document.querySelectorAll("." + input.getAttribute("rel"))).forEach(function(item){
item.style.display = input.checked ? 'block' : 'none';
});
});
}
}
change();
This is my html file. In this html there are checkboxes and dives
<div class="filter">
<div class="checkbox">
<label><input type="checkbox" rel="canada" onchange="change()"/>Canada</label>
</div>
<div class="checkbox">
<label><input type="checkbox" rel="china" onchange="change()"/>China</label>
</div>
</div>
<div class="result">
<div class="canada">
<h1>Canada</h1>
<h2>Jason</h2>
</div>
<div class="china">
<h1>China</h1>
<h2>Ni</h2>
</div>
</div>
But the script filters only one value(in my case - city). How can I add another filters to class of div. For example
<div class="checkbox">
<label><input type="checkbox" rel="india" onchange="change()"/>India</label>
</div>
<div class="checkbox">
<label><input type="checkbox" rel="programming" onchange="change()"/>Programming</label>
</div>
by the adding another value to class
<div class="india programming">...</div>
Adding multiple CSS classes could work, but your current code will overwrite a previous setting of style.display making it sometimes go from none to block, even though the none setting was the right setting.
Here is the code you could use, based on the first example you gave, and an additional result that has both classes "canada" and "china":
function change(){
let results = Array.from(document.querySelectorAll('.result > div'));
// Hide all results
results.forEach(function (result) {
result.style.display = 'none';
});
// Filter results to only those that meet ALL requirements:
Array.from(document.querySelectorAll('.filter input[rel]:checked'), function (input) {
const attrib = input.getAttribute('rel');
results = results.filter(function (result) {
return result.classList.contains(attrib);
});
});
// Show those filtered results:
results.forEach(function (result) {
result.style.display = 'block';
});
}
change();
<div class="filter">
<div class="checkbox">
<label><input type="checkbox" rel="canada" onchange="change()"/>Canada</label>
</div>
<div class="checkbox">
<label><input type="checkbox" rel="china" onchange="change()"/>China</label>
</div>
</div>
<div class="result">
<div class="canada">
<h1>Canada</h1>
<h2>Jason</h2>
</div>
<div class="china">
<h1>China</h1>
<h2>Ni</h2>
</div>
<div class="canada china">
<h1>China and Canada</h1>
<h2>Ni Jason</h2>
</div>
</div>
Note that I assume the rel attribute can only reference one CSS class.

How to get value that was passed to a bootstrap modal in AngularJS

I'm trying to implement a Todo list using Angular JS and connecting it with MySQL and PHP. I have a working code where the button used to open a modal passes a php variable to that modal. I have placed that value in a hidden input field (int the modal). Now, I want to get that value so I can use it AngularJS because I will pass it again through AJAX in a separate PHP page. The thing is, it always returns undefined. Where am I going wrong with this?
JQuery code to pass the php variable and value to the modal:
<script>
$(document).ready(function(){
$('#editModal').on('show.bs.modal', function (e) {
var id = $(e.relatedTarget).data('id');
$("#new-taskID").val(id); // e.g. 3
});
});
</script>
'EditModal' (the form inside the Bootstrap Modal)
<form class="cmxform" id="editTask" name="dasd" onsubmit="return false" method="post" action="" role="form">
<div class="col-md-12">
<div ng-app>
<div id="todoapp" ng-controller="TodoCtrl">
<div class="form-group form-animate-text" style="margin-top:15px !important;">
<input type="text" class="form-text" id="new-todo" ng-model="todoText" name="allotted_time_edit" ng-keyup="addTodo()" required>
<span class="bar"></span>
<label>What needs to be done?</label>
<input type="hidden" class="form-text" id="new-taskID" value = "" name="new-taskID" required> //the passed value is placed here
</div>
<section id="main" style="display: block;">
<div ng-show="isTodo()">
<input id="toggle-all" type="checkbox" ng-model="markAll" ng-click="toggleMarkAll()"/>
<label for="toggle-all">Mark all as complete</label>
</div>
<ul id="todo-list" class="unstyled">
<li ng-repeat="todo in todos" ng-dblclick="toggleEditMode()">
<div class="view" ng-keyup="editTodo()">
<input type="checkbox" ng-model="todo.done"/>
<span class="done-{{todo.done}}" >{{todo.text}}</span>
</div>
<input class="edit" type="text" ng-model="todo.text" ng-keyup="editOnEnter(todo)"/>
</li>
</ul>
</section>
<footer style="display: block;">
<div class="todo-count">{{remaining()}} of {{todos.length}} remaining</div>
<a id="clear-completed" ng-click="clear()" ng-show="hasDone()">
Clear <span >{{(todos.length - remaining())}} {{itemText()}}</span>.</a>
</footer>
</div>
</div>
</div>
<center>
<button id="send" type="submit" class="btn btn-primary" name="dasd">Update</button>
<button type="button" class="btn btn-danger"data-dismiss="modal">Cancel</button>
</center>
</form>
AngularJS Code
<script>
function TodoCtrl($scope, $http) {
$scope.todos = [];
$scope.markAll = false;
$scope.addTodo = function(item) {
var name = $scope.todoText;
var id = document.getElementById('new-taskID').val;
alert(id); //return undefined
if(event.keyCode == 13 && name){
$http.post("ajax-search/add_checklist.php?item="+name).success(function(data){ $scope.todos.push({text:$scope.todoText, done:false});
$scope.todoText = '';
});
}
};
$scope.isTodo = function(){
return $scope.todos.length > 0;
}
$scope.toggleEditMode = function(){
$(event.target).closest('li').toggleClass('editing');
};
$scope.editOnEnter = function(todo){
if(event.keyCode == 13 && todo.text){
$scope.toggleEditMode();
}
};
$scope.remaining = function() {
var count = 0;
angular.forEach($scope.todos, function(todo) {
count += todo.done ? 0 : 1;
});
return count;
};
$scope.hasDone = function() {
return ($scope.todos.length != $scope.remaining());
}
$scope.itemText = function() {
return ($scope.todos.length - $scope.remaining() > 1) ? "items" : "item";
};
$scope.toggleMarkAll = function() {
angular.forEach($scope.todos, function(todo) {
todo.done =$scope.markAll;
});
};
$scope.clear = function() {
var oldTodos = $scope.todos;
$scope.todos = [];
angular.forEach(oldTodos, function(todo) {
if (!todo.done) $scope.todos.push(todo);
});
};
}
</script>
I really need to get the value but it returns undefined. Your help will be much appreciated. Thank you so much!!

Categories

Resources