hasClass() is not working for a given element - javascript

I am testing using jasmine-karma at the moment.
There is one testing scenario:
One element is clicked and highlighted
After it is clicked and highlighted, it will have a new class attribute, its html will be changed from <a xlink:href="#" data-lrn-index="0" role="checkbox" aria-label="Response area" aria-checked="false"> to <a xlink:href="#" data-lrn-index="0" role="checkbox" aria-label="Response area" aria-checked="true" class="lrn-selected">
I have managed to locate this element with this jQuery, $("a[data-lrn-index='0']"), but this jQuery will return false, $("a[data-lrn-index='0']").hasClass("lrn-selected")
From this element HTML, it clearly shows it has a class = ("lrn-selected"), why cannot jQuery return true?

jQuery hasClass() determine whether any of the matched elements are assigned the given class.
The .hasClass() method will return true if the class is assigned to an
element, even if other classes also are. For example, given the HTML
above, the following will return true:
Things to check:
Make sure there is no other javascript error
Make sure your code is working to apply addClass() function.
Use debugger and check developer toolbar to debug the function which is applying this class
Please check below example:
$("a[data-lrn-index='0']").click(function () {
if ($(this).hasClass('lrn-selected')) {
$(this).html('Yes, I had that class');
$(this).removeClass('lrn-selected');
}
else {
$(this).html('Class removed');
$(this).addClass('lrn-selected');
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Toggle click for class availability:</p>
Click here to check class

Related

Jquery else if statement not working to toggle class no-scroll-1

Hi I'm really sorry for asking such a basic question, but i've tried a couple of things and my else if is still not working.
so I'm trying create this if else function:
first part
when any of the .mega-menu-link (parent) is clicked
the function will look for a class called .show in one of its child called .megamenu-item (child)
second part
when any of the .mega-menu-link is clicked, but after searching classList, .megamenu-item does not have .show I would like to enable scrolling on the HTML tag.
I have managed to get first part working but second part seems to get ignored, this is what i have so far
...
...
<li class="nav-item mega-menu-link">
<span id="headingThree">
<a href="" class="nav-link mega-menu-a" data-bs-toggle="collapse" data-bs-target="#megamenu3" aria-expanded="false" aria-controls="megamenu3">
Partners<i class="fa-regular fa-angle-down"></i>
</a>
</span>
<div class="megamenu-item accordion-collapse collapse in" id="megamenu3" aria-labelledby="headingThree" data-bs-parent="#MegaMenuDestop">
<div class=" shadow megamenu bg-white ">`</div>
</div>
</li>
...
..
$(document).ready(function () {
$.fn.classList = function() {return this[0].className.split(/\s+/);};
$(".mega-menu-link").click(function() {
if($(this).children(".megamenu-item").classList(".show")) {
$("html").addClass("no-scroll-1");
console.log("no scroll");
}
else if(!$(this).children(".megamenu-item").classList(".show")){
$("html").removeClass("no-scroll-1");
console.log("scroll");
}
});
});
What I was trying to get across in my comment is that the extension to the jQuery prototype you added does not behave in a compatible manner to the way you are trying to use it.
$.fn.classList = function() {return this[0].className.split(/\s+/);};
This returns the class names on the applicable element split into an array. For example, if called on an element that looks like <div class="megamenu-item accordion-collapse collapse in">, it will return the array: ["megamenu-item", "accordion-collapse", "collapse", "in"]. Invoking this method with an argument, as in .classList(".show") does nothing to change what is returned because the method body does nothing with argument passed to it.
jQuery's .hasClass method seems to have the behavior you desire. However, I would recommend a different approach.
All you need to do is toggle the "show" class on the .megamenu-item child of the clicked parent. jQuery has a .toggleClass method for that:
$(this).find('.megamenu-item').toggleClass("show");
I think the second part of your post wants to disable scrolling by adding a class to the <html> element when any .megamenu-item has the "show" class.
If this is the case, it won't be enough just to look at the .megamenu-item child of the .mega-menu-link that was clicked. Instead, you would need to look at all .mega-menu-link elements to determine if have the "show" class. This could be done with the selector: .mega-menu-link .megamenu-item.show. And we would use the length of that result set to determine if the "no-scroll-1" class should be applied to <html>.
The resultant code looks like:
$(".mega-menu-link").click(function() {
$(this).find(".megamenu-item").toggleClass("show");
const canScroll = $(".mega-menu-link .megamenu-item.show").length === 0;
$('html').toggleClass("no-scroll-1", !canScroll);
});
I have created a fiddle for reference.

Paper Toolbar javascript not reacting

I have a Polymer paper-toolbar element that takes some custom attributes like background-color and titles. It contains a.o. a search button and is called in various other elements.
The problem is that only the element where it is first called will display the search box when toggled while in other elements it does not.
This is the code for the toolbar:
<template>
<paper-toolbar class$="{{toolbarSize}}" style$="background-color:{{toolbarColor}};">
<span class="title"><p>{{topTitle}}</p></span>
<div id="searchbox">
<input-search placeholder="Search …"></input-search>
</div>
<paper-icon-button id="searchicon" icon="search" on-tap="openSearch"></paper-icon-button>
<span class="middle title"><h1>{{middleTitle}}</h1></span>
<span class="bottom title"><p class="subtitle">{{bottomTitle}}</p></span>
</paper-toolbar>
</template>
<script>
Polymer({
is: 'tool-bar',
properties: {
topTitle: String,
middleTitle: String,
bottomTitle: String,
toolbarSize: String,
toolbarColor: String
},
openSearch: function() {
var sb = document.getElementById("searchbox");
console.log(sb);
if (sb.hasAttribute("hidden")) {
sb.removeAttribute("hidden");
} else {
sb.setAttribute("hidden", true);
}
}
});
</script>
This is the code that calls in in various other elements:
<paper-scroll-header-panel>
<div class="paper-header staticpage">
<tool-bar
toolbar-color="var(--sc-gold-500)"
toolbar-size="tall"
middle-title="Titletext"
bottom-title="Subtitle text">
</tool-bar>
</div>
<page-view></page-view>
</paper-scroll-header-panel>
When I open the site and click on the search icon, it indeed toggles the searchbox just fine. But when I go to any other page (a different element that calls the same toolbar with different attributes), it does not toggle the toolbar any more.
This looks to me like a bug but if anybody has a solution or explanation for this behavior, I'd be very grateful. I have tried it with various other input-elements and it has the same result.
Output of the Console.log:
The console.log seems to indicate that everything is fine.
On the first page (where the element hides/unhides correctly):
First click: <div id="searchbox" class="style-scope tool-bar" hidden="true">
Second click: <div id="searchbox" class="style-scope tool-bar">
Then I move to another page/element and it gives exactly the same results, except that the element does not hide, even when the attribute hidden="true". When I look at the inspect element however, it does not show the attribute hidden="true".
However, when I click it so the console.log says that hidden="true", and then I move back to the first page/element, the searchbox is indeed hidden on that first page.
Because Polymer is based on Shadow-DOM, standard DOM selectors (such as document.getElementById('someId')) are ill-advised will lead to unexpected results. This is because a custom element will insert duplicate IDs into the DOM.
To overcome this, you must use Polymer's element selector method instead: Polymer.dom(this.root).querySelector('#someId'). This can be conveniently shortened to this.$$.someId. (where this is the custom element)
The Fix
For your code as above, change the openSearch function to the following:
openSearch: function() {
this.toggleAttribute('hidden', true, this.$.searchbox);
}
Thanks #Kuba for pointing out my initial error.
Fix Explanation
Element Selection
this.$ is an object of element IDs for the current custom element (this) when it was stamped onto the page. Therefore, this.$.searchbox gets the element's handle for this custom element's 'searchbox' element. This is in comparison to document.getElementById(...), which will only get the first element with id="searchbox" it finds on the page, not necessarily the one belonging to the current custom element.
Attribute Toggling
Polymer adds some special methods to it's element handles (that come from PolymerBase) for custom elements. One of these is the PolymerBase.toggleAttribute(String name [, Boolean value, Element node]) method (link to docs). To use this method with a polymer element, you call it on the element's reference from this.$ or this.$$.
For elements of a custom element, use:
this.toggleAttribute('hidden', true, this.$.someElementId)
If the target element is a custom element loaded by polymer, you can also use:
this.$.someElementId.toggleAttribute('hidden')
this.$.someElementId.toggleAttribute('hidden', true)
As a side note: Please rename your toolbar to vims-toolbar or similar to follow the custom elements naming scheme of <namespace>-<element-name>.
Further reading: PolymerBase docs

toggle div to show hide

I have a simple block of code to hide/show two divs. It works great, the only issue I have is that I need to return the display value to the #MSOZoneCell_WebPartWPQ2 back to table. I have set it to none in the css initially. The last line doesn't seem to take effect.
here is the code:
$(function() {
$('#swap').click(function() {
$('#MSOZoneCell_WebPartWPQ2').toggle();
$('#example_wrapper').toggle();
$('#MSOZoneCell_WebPartWPQ').css('display') == 'table';
});
});
You're using == operator
Try this:
$(document).ready(function(){
$('#swap').click(function() {
$('#MSOZoneCell_WebPartWPQ2').toggle();
$('#example_wrapper').toggle();
$('#MSOZoneCell_WebPartWPQ').attr('style','display:table;');
});
});
you should use .css( propertyName, value )
Set one or more CSS properties for the set of matched elements.
so your last line should be
$('#MSOZoneCell_WebPartWPQ').css('display', 'table');
when you call .css( propertyName )
$('#MSOZoneCell_WebPartWPQ').css('display);
you are Getting the value of said property not setting it
Get the computed style properties for the first element in the set of
matched elements.
Update 1:
please note that Jquery's .show(), .hide() and .toggle() will only work with elements with block display property.
so one way to avoid changing the display property back and forth is to wrap the wanted elements in a div (container) and .toggle() it.
I have created a JSFiddle, I warped each div in a container div with a calss called "toggle" and set initial display value of one of them to "none" using style attribute.
<div class="toggle" style="display:none">
now I toggle between them using this
$('.toggle').toggle();
Update 2:
you can also use .toggleClass() here's another JSFiddle
Add this to your CSS
#example_wrapper.hiddenDiv, #MSOZoneCell_WebPartWPQ2.hiddenDiv {
display: none;
}
add a class to the div you want initially hidden
<div id="MSOZoneCell_WebPartWPQ2" class="hiddenDiv">
toggle the class using this
$(function() {
$('#swap').click(function() {
$('#MSOZoneCell_WebPartWPQ2').toggleClass("hiddenDiv");
$('#example_wrapper').toggleClass("hiddenDiv");
});
});
in this example I'm using a class called "hiddenDiv", if you change it make sure the class name is the same in CSS, HTML and JS.
you are sure you need "==" to set the value? or one "="
Firstly == is an equality check. You should use = to set a value.
Secondly, the css() method setter accepts two parameters. The rule to set and the value itself. Try this:
$('#MSOZoneCell_WebPartWPQ').css('display', 'table');

When a Div class is clicked, alert it's inner content's Div Class

How do i even put these, let me try. In the following sets of codes, i want to click 'parentclass' and have an alert value of 'child1' and when i click the class below it which is 'Parent 2' have an alert fire with a value of 'child2'
So this must alert the content of that class only and not the entire class.
Here's some Javascript in Jquery.
var childclass = $('.childclass').html();
$('.parentclass').click(function(e) {
alert (childclass)
});
$('.childclass').click(function(e) {
e.stopPropagation()
e.preventDefault()
});
And HTML
<a href="" onClick="return false">
<div class='parentclass'>
Parent 1
<div style="display:none" class="childclass">child1</div>
</div>
</a>
<a href="" onClick="return false">
<div class='parentclass'>
Parent 2
<div style="display:none" class="childclass">child2</div>
</div>
</a>
This line var childclass = $('.childclass').html(); doesnt make sense as it doesn't know which element in particular you mean. The result of that will just be child1child2 which is just a concatenation of the .html() of all the elements with class childclass. This is obviously not what you want.
Therefore you should dynamically find the child with a class of childclass upon receiving the click event.
$('.parentclass').click(function(e) {
alert($(this).find('.childclass').html())
});
Also, you should know that your child class event handler is useless as we don't care if the event gets propogated downwards. If you DID care, then your e.stopPropagation() and e.preventDefault() should be in the event handler of the parent class.
You need to fetch the html of the clicked parent element within the click handler
$('.parentclass').click(function (e) {
alert($(this).find('.childclass').html())
});
$('.childclass').click(function (e) {
e.stopPropagation()
e.preventDefault()
});
Demo: Fiddle
Several ways you can go about this.
First, if your HTML will not be dynamic (elements already exist when page loads), then you can select elements by the parent class name and assign click event as so:
$('.parentclass').click(function(e) {
// the first variable here is selecting the inner elements having class 'childclass'
// keep in mind, if more than one child having that class is present within this parent, it will select all of them
var child = $(this).find('.childclass');
// here we alert the text of the inner child found
// if it is more than one, you will have undesired results. you may want to specify `.first()`
alert(child.text())
})
For newer jQuery you can also use $('.parentclass').on('click', function(e) {.
If you expect any pieces of parentclass to be dynamic, then you'll want to delegate the event based on either a static parent to the parents or document. This can be like so:
$(document).on('click', '.parentclass', function(e) {
alert($(this).find('.childclass').text())
})
Or, if you have a static (already there when page loads) wrapping element, give it an ID like `parentClassWrapper' and assign the click event dynamically as:
$('#parentClassWrapper').on('click', '.parentclass', function(e) {
alert($(this).find('.childclass').text())
})
Some helpful links:
jQuery API
jQuery Selectors
.click()
.on()
Some info on Event Delegation
jquery on vs click methods
jQuery .on('click') vs. .click() and .delegate('click')
jquery .live('click') vs .click()
I made several adjustments to your html that are worth noting. There's no need for the <a> tag. Don't use inline js - onlick in your html. Note that I wrapped the text inside of the div in the <a> tag instead. This markup is more semantic. Also, move your styles to css rather than in the html.
<div class="parent">
<a>Parent 1</a>
<a class="child">child of parent 1 contents</a>
</div>
<div class="parent">
<a>Parent 2</a>
<a class="child">child of parent 2 contents</a>
</div>
css:
.parent > .child { /* good practice: only select an immediate child of the parent */
display: none;
}
The other answers here are using find() to select the child, but I recommend children() instead. For example, if you had additional nested .childs, find() will select them all, but children() will only select direct .childs of the parent, so it is better in this case. I also recommend using the console for debugging rather than alert.
Live demo here (click).
$('.parent').click(function() {
var $child = $(this).children('.child');
var cls = $child.attr('class');
console.log(cls);
$child.show(); //added so that you can click the child
});
$('.child').click(function() {
var html = $(this).html();
console.log(html);
//if you just want the text, use this instead:
var text = $(this).text();
console.log(text);
});

Why this JS id does not work for multiple items

I got a 2 buttons and an image. When ever I press any of the buttons the image fades out. like this demo: http://jsfiddle.net/5wBuV/6/
the problem is that this is working only for the first button and the second one does not work. It might be a simple mistake but I am really beginning in JS.
$("#clickedButton").click( function() {
$("#hide").fadeOut("slow");
});
id of an element must be unique, if you use ID selector jQuery will return only the first element with the id.
In your case if you want to add same event handler to a set of elements, you can use a common class attribute and then use class-selector
<!-- The button -->
<a href="#" class = 'clickedButton'>
<img src="http://www.kwvs.pepperdine.edu/playbutton.png" />
</a>
<a href="#" class = 'clickedButton'>
<img src="http://www.kwvs.pepperdine.edu/playbutton.png" />
</a>
then
$(".clickedButton").click( function() {
$("#hide").fadeOut("slow");
});
Demo: Fiddle
Using id selector will only return zero/ one object.
If you want to refer to more than one object, use class selector. Like:
$('.clickedButton').click(function () {
$('#hide').fadeOut('slow');
});

Categories