Jquery custom written selector - javascript

I've been trying to solve the following problem all sorts of ways today. I've spent hours on it and I can't seem to figure out how to do it.
The basic problem is this: I have a bunch of JavaScript logic going on to figure out if the following variables should be a 1 or 0.
1)active
2)alternative
3)classic
4)vintage
etc....
and all these variables act essentially as filters in my design. I need them to determine whether a product should be displayed or not. So once these values are determined, I want to display product styles accordingly (or hide product styles) by appending or removing a CSS class (let's call it .style) . Each product has 1 or multiple of the filters attached to it. So like a pair of shoes might be classic AND alternative, in which case a 1 in either classic OR alternative variables should cause the shoes to display with the style.
What's the best way to do this display aspect? I was thinking of writing a custom selector but I'm having a very hard time figuring out how to write it.
Something like...
if($(".divProducts").hasClass(active) || $(".divProducts").hasClass(alternative) || etc..)
{
....?
}
but I don't get very far this way because first of all, even if the IF statement clause parses correctly, I won't know which product actually returned a 1 in alternative or active or any of the other filters.
This is really hard to explain.
TLDR; Basically I need this:
If ANY of the elements in some div container have ANY of the filters that are of value 1, apply .style to each of those elements.
Help would be hugely appreciated as this is part of a project due tomorrow actually... I didn't expect to have such a hard time with it :\
By the way, the products keep track of filters with classes. So for example
shoes product->
<div class="blah blah vintageFilter blah blah">...</div>
I want to apply .style class to this div IF vintage variable is 1. Make sense?

I think this approach will be more readable and say more managable
switch(true) {
case $('.divProducts').hasClass(active) :
// some action
break;
case $(".divProducts").hasClass(alternative) :
// some action
break;
default :
//some action
}

This should work:
// First clear the .style class from everything
$('.divProducts').removeClass('style');
// Then add it to the selected items
$('.divProducts.active, .divProducts.alternative').addClass('style');

It would be helpful if you had included some HTML, but since you didn't I'm going to assume that you have something that looks like this:
HTML
<fieldset>
<label><input type="radio" name="type" value="active" />Active</label>
<label><input type="radio" name="type" value="alternative" />Alternative</label>
<label><input type="radio" name="type" value="classic" />Classic</label>
<label><input type="radio" name="type" value="vintage" />Vintage</label>
</fieldset>
<div id="result">You picked: <span id="selection"><span></div>
<div class="products">
<div class="vintage classic">Vintage and Classic</div>
<div class="vintage">Vintage</div>
<div class="classic">Classic</div>
<div class="classic alternative">Alternative and Classic</div>
<div class="alternative">Vintage and Classic</div>
</div>
The solution is simple and you don't even need a conditional. The way I would accomplish it is with the following JavaScript:
JavaScript
$("input[name='type']")
.on("click", function()
{
// Clear result showing state
$("#result").removeAttr("class");
// Get selected value
var typeVal = $(this).attr("value");
$("#result").addClass(typeVal);
$("#selection").text(typeVal);
// Remove match class
$(".products div").removeClass("match");
// Show matching products and add match class
$(".products ." + typeVal).addClass("match");
});
With this CSS:
CSS
.active { color: #f00; }
.alternative { color: #0f0; }
.classic { color: #00f; }
.vintage { color: #999; }
.match { background: #ccc; }
Here's a link to the jsFiddle: http://jsfiddle.net/XQVet/3/
Update: Changed it so that elements wouldn't disappear.

Related

How do I removeAttribute() hidden from p2? doesn't seem to do anything as is

I'm trying to change the attribute of an object with removeAttribute to take away the hidden status of it but so far nothing seems to work.
My code seems to have no effect. Am I doing something wrong?
function changePage() {
document.getElementById.("p2");
p2.removeAtribute.("hidden") ;
}
I've also tried it all on one line as well like so
function changePage() {
document.getElementById.("p2").p2.removeAtribute.("hidden") ;
}
I've never seen the use of dots before opening parentheses.
E.g.
document.getElementById.("p2").p2.removeAtribute.("hidden") should be document.getElementById("p2").removeAtribute("hidden")
(You are also referencing the element by id after you just retrieved it, which is unnecessary.)
Your first example didn't work because you retrieved the element and did nothing with it, then tried to access a p2 variable that wasn't declared. Again, you also have the . before parentheses.
Here's the js example:
function changeVisibility()
{
var p2 = document.getElementById('p2');
switch (p2.style.visibility)
{
case 'hidden':
document.getElementById('p2').style.visibility = 'visible';
break;
case 'visible':
document.getElementById('p2').style.visibility = 'hidden';
break;
}
}
<div id="p2" style="visibility:hidden">
test
</div>
<br />
<button onclick="changeVisibility()">
change visibility with basic js
</button>
And here's the jQuery example:
function changePage()
{
$('#p2').toggle();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="p2" style="display:none">
test
</div>
<br />
<button onclick="changePage()">
change visibility with basic js
</button>
The basic JS version uses the visibility style, and you can see that it doesn't collapse the element, it only makes it invisible.
jQuery has a nice built-in .toggle function that changes the display of the element. If it is hidden, it collapses the element. When the element is displayed, it is re-assigned whatever the display style is for that element. Building that in basic js would take a lot more work, as you are then tracking state (if you want to make the method reusable). You can make jQuery work similarly to the basic js version if you use the css properties, but toggle is quite nice and simple.
Your main issue is that you were mixing the getting of the element with methods that are only available on jQuery objects. I suggest reading the jQuery tutorials for basic accessors, which can get elements by id, class name, etc.

How to use the method : $().button('toggle') for this bootstrap 'radio-button list'?

<div class="btn-group btn-group-toggle" data-toggle="buttons">
<label class="btn btn-secondary active">
<input type="radio" name="options" id="option1" autocomplete="off"
checked> Active
</label>
<label class="btn btn-secondary">
<input type="radio" name="options" id="option2" autocomplete="off">
Radio
</label>
<label class="btn btn-secondary">
<input type="radio" name="options" id="option3" autocomplete="off">
Radio
</label>
</div>
$().button('toggle') : Toggles push state. Gives the button the appearance that it has been activated.
Screenshot of image of RadioButtonList. From the left-most button you can see that it looks like it has been clicked when it is clicked.
Screenshot of the Login-page that I am currently making. When I click on either of the 'radio' buttons their appearance does not changed, so I have to use the method $().button('toggle'), but I do not know where or how to use it.
You just need to add the correct selector to the jQuery function. Try using this instead:
$(".btn-group").button("toggle");
And now your code should work.
Hopefully this helps!
I came across this question because I was stumped by a similar use case. It's my first time working with jquery, so I was a little confused by the syntax at first. (tl;dr diff between JS/jquery see 4.)
I wanted to expand on the 1st answer because I would have appreciated someone else doing the same. I was working through this problem on Bootstrap 4.5.3 for a couple hours, completely stumped as to why my radio buttons wouldn't show the toggle effect, before I realized there was a library requirement for the button() method, which I did not see in the docs.
The required library: If you want this feature to work "the bootstrap way", the buttons.js library before invoking the jquery script, which in an npm-installed package is located at node_modules/bootstrap/js/dist/
Load + init example:
<script src="node_modules/bootstrap/js/dist/buttons.js">
$('.btn-group').button('toggle');
</script>
you can disaggregate the jquery and loading the script if that helps you keep things straight (separate <script /> tags for each):
<script src="node_modules/bootstrap/js/dist/buttons.js"> </script>
<script>$('.btn-group').button('toggle');</script>
Selecting the proper element for your use case: A slightly more specific way to target the buttons is explained by TWBS in another bootstrap example for tooltips - this is targeting the children of an element by data attribute: https://getbootstrap.com/docs/4.5/components/tooltips/#example-enable-tooltips-everywhere
$('[data-toggle="button"]').button('toggle');
More about selecting element by data attribute here: Selecting element by data attribute with jQuery
Right target for use case continued: You can attach it to elements in any number of ways, here's an example using the IDs of each button, the # hash symbol denoting an ID selector (the . period symbol denoting a class, just like css) - you simply put them in an array and pass that to the button() method:
$(['#option1', '#option2', '#option3']).button('toggle');
This could be classes (starting with a period, e.g. ['.button-one', '.button-two'], etc.
Big picture: If you're seeing the pattern here, jquery uses these
$(DOM ELEMENT).method(SCOPE) statements, which are a more terse form of the syntax used by JS, which would be a lot more verbose, something like:
let lis = document.getElementsByTagName('li');
let firstLi = lis[0];
firstLi.addEventListener('click', () => console.log('clicked first li'))
So it's basically the same, just way less verbose. Since jquery was developed specifically to handle the DOM, this makes sense.
If you want to achieve the same look without loading the bootstrap buttons.js library, you can attach/remove the .active class, which when attached mutes the appearance of the radio button, to the label of the buttons in question with something like:
$('.btn').on('click', function () {
$(this).siblings('label').removeClass('active');
$(this).addClass('active');
});
Statement exmplained: When an element with the .btn class is clicked, it will remove all .active classes from any sibling elements with the tag type label, and add the .active class to the one you clicked.
If you examine the button.js library, though, you can see that toggle() does quite a bit more stuff behind the scenes than just applying/removing .active (and has many, many, many conditionals for different possible use cases...):
_proto.toggle = function toggle() {
var triggerChangeEvent = true;
var addAriaPressed = true;
var rootElement = $__default['default'](this._element).closest(SELECTOR_DATA_TOGGLES)[0];
if (rootElement) {
var input = this._element.querySelector(SELECTOR_INPUT);
if (input) {
if (input.type === 'radio') {
if (input.checked && this._element.classList.contains(CLASS_NAME_ACTIVE)) {
triggerChangeEvent = false;
} else {
var activeElement = rootElement.querySelector(SELECTOR_ACTIVE);
if (activeElement) {
$__default['default'](activeElement).removeClass(CLASS_NAME_ACTIVE);
}
}
}
if (triggerChangeEvent) {
// if it's not a radio button or checkbox don't add a pointless/invalid checked property to the input
if (input.type === 'checkbox' || input.type === 'radio') {
input.checked = !this._element.classList.contains(CLASS_NAME_ACTIVE);
}
if (!this.shouldAvoidTriggerChange) {
$__default['default'](input).trigger('change');
}
}
input.focus();
addAriaPressed = false;
}
}
if (!(this._element.hasAttribute('disabled') || this._element.classList.contains('disabled'))) {
if (addAriaPressed) {
this._element.setAttribute('aria-pressed', !this._element.classList.contains(CLASS_NAME_ACTIVE));
}
if (triggerChangeEvent) {
$__default['default'](this._element).toggleClass(CLASS_NAME_ACTIVE);
}
}
};
So, probably best just to load button.js...
Side Note: Arrow functions in jquery more often than not wind up targeting the window object, so might be best to avoid unless you know what you're doing.

Using JQuery - on click event

So... I made a page where you can find some products, and each product has a price/description/title. I’m currently trying to change prices, but the thing is I want them to change if you click on a button (which is sales related). I’d like to change the price and add a 20% discount.
I started to do something, which only change the color of the prices from black to red:
$(".row a").click(function(){
$("cat-bonnet").css("color","red");
});
I selected the class of my thing through CSS. But now I don’t know how I am supposed to add the discount. Should I create another code ? How can You do it when clicking on a button ?
Thanks in advance.
$("cat-bonnet") would try to target <cat-bonnet></cat-bonnet> in the DOM.
You must specify that it's:
A class
$(".cat-bonnet")
Or an ID:
$("#cat-bonnet")
Specify the class or the id of cat-bonnet by using . for a class or a # for id:
$(".row a").click(function(e){
$(".cat-bonnet").css("color","red"); // Add '.' here
e.preventDefault(); // stop page from redirecting (to see change effect)
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="row">
<a class="cat-bonnet" href="https://www.google.com">Link</a>
</div>
Well it's fairly easily done with a piece of vanilla javascript:
document.querySelector(".cat-bonnet").innerHTML = newPrice;
newPrice should be your calculated discount. So you should get the price of .cat-bonnet and calculate the 20% discount. This could be done in a variable let = newPrice; or inline.
Jquery is a large library and based on your code above you may be better of with just vanilla javascript. But just adding the above line will do the trick for you.
What does add discount do?
Does it post data to apu endpoint? Or just change the html? Or any other processes?
I would suggest a slightly different setup to your code to make it easier to add more properties if you wish to in future. I've also put down a way to check for various ON actions such as 'mouseenter', 'mouseleave' etc.
Have a look at the code below. I think this will make it a lot easier to read when your projects get bigger.
$(".row a").on('click', () => { // Insert mouseenter, mouseleave etc where click is
$(".cat-bonnet").css({
color: "red",
backgroundColor: "gray"
// Add more properties inside the object here as you wish
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="row">
<a class="cat-bonnet" href="https://www.google.com">Link</a>
</div>

Change css value between two styles on click of same button using javascript

I have an image upon which I want to bring a text on clicking the image. I applied the css display property to none and on click I changed it to block. Now again on clicking I want to change the display to none. How can I do that?
js:-
function showTerms(data){
document.getElementById(data).style.display = 'block';
}
html:-
<div style="display: none;" id="text1111" class="offer_text size-12">
<div class="TC">
<div class="condition">Terms & Condition</div>
</div>
<p></p>
<div><br></div>
<div>- The coupon code is valid for one time use per user account.<br></div>
<p></p>
You can achieve this with a toggle function, like so:
function toggleTerms(data){
document.getElementById(data).style.display = (document.getElementById(data).style.display == 'block' ? 'none': 'block');
}
Generally speaking, do not modify CSS directly in JavaScript (there are of course exceptions, but in this case you shouldn't).
Instead, define a CSS class like so:
.shown {display: block}
Then your JavaScript can be as simple as:
function showTerms(data) {
document.getElementById(data).classList.toggle("shown");
}
* If support for old browsers is needed, you'll need something a little more advanced to check if the class is on and toggle it manually.

Basic Jquery- Fade Out/Fade In

I am building a very basic guessing game using jquery and html. I have 6 checkboxes, and if the right sequence is triggered, a hidden div appears. In order to trigger the div, I need to select 1,2,and 3. If you select 1,2,and 4, you get a secret message (div2), and otherwise nothing happens.
I can do the trigger easily by doing nested clicks:
$("#1").click(function(){
$("#2").click(function(){
$("#3").click(function(){
$("#div1").fadeIn();
});
});
});
html:
<input type="checkbox" id="#1">
<input type="checkbox" id="#2">
<input type="checkbox" id="#3">
<input type="checkbox" id="#4">
<input type="checkbox" id="#5">
<input type="checkbox" id="#6">
<div id="div1" style="width:30px;height:30px;display:none;background-color:blue;"></div>
<div id="div2" style="width:30px;height:30px;display:none;background-color:yellow;"></div>
But I am having trouble making it disappear.
If any one of the three is not pressed, I would like for that div to disappear. So let's say you press 1,2,3, div1 appears, and if you deselect 3, that div1 disappears.
I think I can make the question easier to phrase by phrasing it like this: i want to tell jquery- if one, and two, and three, are not 'all' selected, fade out the div.
Rather than using nested clicks, which will get complicated and confusing, you'd be better off creating a generalised listener that will maintain a list of what has/hasn't been clicked. Not only is this easier to maintain, it is also more optimal than having many click handlers assigned.
Others out there who may wish to optimise further may say correctly that you could write this code to directly generate a checked array, rather than a checked object, the reason I have kept it as an object is to support the possibility of a string-based ident rather than just numerical.
updated code
Previous code was slightly buggy, this version now works correctly when you select more checkboxes than you should.
reasons why
why change to use classes more than ids
Whilst ids are very specific, and will be more optimal for the browser to select by, they generally cause confusion and make things laborious, especially in markup that you wish to duplicate (obviously because ids have to be unique). It is often far better to come up with a solution that can work on a general grouping class, than having to label each element with a sequence i.e. cb1, cb2, cb3. As you can see my markup does label the checkboxes sequentially but the code only worries about the grouping class .cb, leaving the sequential classes really only for css styling.
why add a container div
When working on html5 apps, container divs will help you out 9 times out of 10. If you have a collection of elements that will only ever reside in a close visual formation, you will do yourself a favour by wrapping them. This helps when dynamically generating more elements (you can append your new elements directly to the container), it can help with delegating event listeners, and when targeting the elements via jQuery and CSS.
why use change instead of click for checkboxes
change is the event specifically designed to trigger when a change of value occurs, click is designed to fire when a click occurs. You should use the event that best suits what you want. In this case you only wish to update when a checkbox has changed it's value, which can happen with or without a mouse. True, some browsers fire the click event when using keyboard events, but it is better to be clear.
why use data-ident
ids should be used for quick look-up purposes, classes should be used to classify and group, if you have any other information to add to an element you should use the data- prefix. This means you aren't limited by what characters id and class support, and changing data- values doesn't cause any real internal calculations to fired by the browser i.e. applied classes or element registration.
how this code could be improved
The problem with making code more accessible and readable means that it's easier to work out what the code means, and this is bad for a game that should try and hide the solutions away from it's user-base. If this is just a simple game then there isn't much to worry about, but if you are working with something a bit more serious you should try and find a way to obfuscate the solutions :)
working fiddle:
http://jsfiddle.net/RFK92/
code:
/// your list of what is checked
var checked = {};
var updateDivs = function(){
var ident, show, checklist = [];
/// create a useful string from what has been checked
for ( ident in checked ) {
if ( checked[ident] ) {
checklist.push(ident);
}
}
checklist = checklist.join(',');
if ( checklist == '1,2,3' ) {
show = $('#div1');
}
else if ( checklist == '1,2,4' ) {
/// show something else, or not...
}
/// by using a grouping class you can find all divs that could be affected
$('.only-one-div').not(show).fadeOut();
if ( show ) {
/// and single one out for reveal
show.fadeIn();
}
};
$('.cb').change(function(){
var cb = $(this), ident = cb.data('ident');
/// keep track of what is or not checked
checked[ident] = cb.prop('checked'); /// updated to use prop!
/// update your divs
updateDivs();
});
markup:
<div class="cbs">
<input type="checkbox" class="cb cb1" data-ident="1" />
<input type="checkbox" class="cb cb2" data-ident="2" />
<input type="checkbox" class="cb cb3" data-ident="3" />
<input type="checkbox" class="cb cb4" data-ident="4" />
<input type="checkbox" class="cb cb5" data-ident="5" />
<input type="checkbox" class="cb cb6" data-ident="6" />
</div>
<div id="div1" class="only-one-div">one</div>
<div id="div2" class="only-one-div">two</div>
css:
.only-one-div { display: none; }
I would have a look at binding and unbinding your clicks.
Basically, if they have clicked the first proper click then bind the second proper click.
Any incorrect clicks would have you unbind all the clicks and fadeOut the divs and rebind the first necessary click.
http://api.jquery.com/bind/
http://api.jquery.com/unbind/
http://jsfiddle.net/CEb9x/1/
$('input[type=checkbox]').on('change', function(){
if($('input:checked').length == 3){
if ($('.blue:checked').length == 3) { $("#div1").fadeIn(); $("#div2").fadeOut();}
else if ($('input[name="secret"]:checked').length == 3) { $("#div1").fadeOut(); $("#div2").fadeIn(); }
} else { $("#div1, #div2").fadeOut(); }
});
This should do:
$("#1").click(function(){
checkboxClicked();
});
$("#2").click(function(){
checkboxClicked();
});
$("#3").click(function(){
checkboxClicked();
});
$("#4").click(function(){
checkboxClicked();
});
$("#5").click(function(){
checkboxClicked();
});
$("#6").click(function(){
checkboxClicked();
});
...
...
function checkboxClicked() {
if ($('#1').is(':checked') && $('#2').is(':checked') && $('#3').is(':checked') {
$('#div1').show();
$('#div2').hide();
}
else {
$('#div1').hide();
}
if ($('#1').is(':checked') && $('#2').is(':checked') && $('#4').is(':checked') {
$('#div2').show();
$('#div1').hide();
}
else {
$('#div2').hide();
}
}

Categories