Underscore/jQuery - combine hasClass and map - javascript

In my web page, I have a list of div and depending on the scroll position, one of them has a class 'active'.
I'd like to change the css of the class set to active.
Rather than looping through all the divs, I wanted to use the underscore library but I am not sure I am using it correctly with jQuery:
_.map($('.item'), function(item){
if (item.hasClass('active'))
// some code here
});
When I run this code, I get the following error:
Uncaught TypeError: undefined is not a function
I assume my browser doesnt recognize 'item' as a jQuery object.
How can I fix this?
thanks

Related

byRole is not returning the DOM element

I am migrating some of my unit test cases which were previously written using Jest and Enzyme to React Testing Library. I am using Material UI's Select component and I know that, in order to open the dropdown, we have to trigger the mouseDown event on the corresponding div. Here is how I did it in Enzyme (working):
wrapper.find('[role="button"]').simulate('mousedown', { button: 0 });
I am trying to achieve the same using React Testing Library in the following manner, which is not working:
const { container, getAllByRole, getByRole } = renderComponent(mockProps);
fireEvent.mouseDown(getByRole('button')); // trigger the mouseDown on div having role=button
After this I am trying to access the listbox element which is ul element:
getByRole('listbox')
which throws an error and says:
TestingLibraryElementError: Unable to find an accessible element with the role "listbox"
There are no accessible roles. But there might be some inaccessible roles. If you wish to access them, then set the `hidden` option to `true`. Learn more about this here: https://testing-library.com/docs/dom-testing-library/api-queries#byrole
I have verified and the ul element is visible (neither it nor its parent have display none or visibility hidden)
UPDATE - 1
I have tried all the following approach to wait for element to appear in DOM:
waitFor
findByRole instead of getByRole
in both the case it throws error that
Unable to find role="listbox"
What is wrong?
If the element is not accessible at the first render this error could appear, you can try passing the option hidden to the options key in the second argument of the getByRole, if this not works you can try using findByRole, that method wait for the element, and if you want to be sure of the visibility of the element you can try adding a waitFor inside of the test.
getByRole('listbox', { options: { hidden: true } });
Make sure animations are not compromising your results. If the animations change opacity or display and they did not finish before assertion from jest... it is likely to throw an error.
I found the root cause of this issue. I am using the Select component from MUI in disablePortal mode, which make the menu list to be rendered inside the parent component instead of document body. But while MUI does that, it doesn't remove the aria-hidden attribute from the parent component's div, and because of that testing library is not able to locate the listbox (ul) element inside.
There is an issue reported here:
https://github.com/mui/material-ui/issues/19450
So as a work around, I passed the data-testid to the menu component (MenuListProps) and using it to get the listbox.

Attempting to change CSS using document.getElementById not working?

I'm attempting to change the CSS of a display:none to a display:block using the following command:
document.getElementById["pop-up"].style.display="block";
The problem is, despite defining the pop-up id in the css (see below), and following other instructions similar to this problem, I've not been able to get it to change.
#pop-up {
display: none;
}
What am I doing wrong?
getElementById is a function (not an object where every element with an ID exists as a property).
You need to call it with () and not access properties with []
Make sure you open the Developer Tools in your browser and read the console. It would have told you that document.getElementById["pop-up"] was undefined.
Try replacing the square brackets with parentheses;
document.getElementById("pop-up").style.display="block";

jQuery Waypoints add class when element is scrolled into view

I'm using the Waypoints plugin to check if an element is scrolled into view. I have multiple divs with class item as the user scrolls down the page, I want to add a class "viewed" to each.
$(".item").waypoint(function(){
$(this).addClass("viewed");
console.log("yey");
});
The console.log works, but the .addClass doesn't. Does the plugin not support $(this)?
I finally got it working.
$(".item").waypoint(function(){
$(this[0,'element']).addClass("viewed");
});
The this wasn't pointed at the element, so I needed to target it.
You have to be careful when calling these callback functions, and what this really means. In this instance, its probably referring to your function.
Doesn't the event trigger pass the target in the function as an argument? Try using that. If you want to know what your nested this really is, console.log it.
$(".item").waypoint(function(thing){
$(thing).addClass("viewed");
console.log("yey");
});
The checked answer caused loads of errors in newer version of this plugin.
This is what works for me:
$(".item").waypoint(function() {
$(this.element).addClass("viewed");
});

Can I rewrite Javascript without using 'this'?

I'm very new to JS and I'm having trouble getting this to work.
Here is my code
jQuery('ul.menu li').each(function() {
jQuery(this).removeClass('current-menu-item');
jQuery(this).removeClass('current_page_item');
});
jQuery(this).parents('li').addClass('current_page_item');
jQuery(this).parents('li').addClass('current-menu-item');
Now what this should be doing is remove the highlight from one link on a navigation menu, and highlighting the one thats been clicked (I have an AJAX implementation).
For some reason it isn't doing anything. I have a feeling it is due to 'this' is there another way of structuring this code so I can work out if the code is wrong, which I don't believe it to be, or because of 'this'?
EDIT:
Apologies, it seems I haven't given enough information. I'm using the Twenty Fourteen wordpress theme but I'm serving the pages with AJAX.
http://twentyfourteendemo.wordpress.com/
I have the code being applied globally (I have other code in the same place to toggle the navigation once clicked (on mobile) and that works fine)
I have the menu at the top (without any dropdowns, just links). I can't give a link as it's not external currently. Should my code be working to change this?
As a few people have commented "What is 'this'" I feel I've completely missed something.
You don't need loop each item to do a remove class one by one, this is more easy :
jQuery('ul.menu li').removeClass('current-menu-item').removeClass('current_page_item');
Or (it's the same) :
jQuery('ul.menu li').removeClass('current-menu-item current_page_item');
But I don't understand what is this 'this' :
jQuery(this).parents('li').addClass('current_page_item');
jQuery(this).parents('li').addClass('current-menu-item');
Do you mean :
jQuery('ul.menu li').addClass('current_page_item current-menu-item');
Or if you are on an event listener (like click, as #Daniel Sanchez feel on comment) you just need to do :
jQuery('ul.menu li').click(function(){
// Remove class on each item
jQuery('ul.menu li').removeClass('current-menu-item current_page_item');
// Add class for this one
jQuery(this).addClass('current_page_item current-menu-item');
})
It's not entirely clear what you are trying to do but the code can be simplified somewhat:
jQuery("ul.menu li a").click(function(){
jQuery('ul.menu li').removeClass('current-menu-item current_page_item');
jQuery(this).parent('li').addClass('current_page_item current-menu-item');
});
http://jsfiddle.net/re3hjzyf/
Yes, by replacing this with 'ul.menu li'.
So the code would be like this
jQuery('ul.menu li').each(function() {
jQuery('ul.menu li').removeClass('current-menu-item')
.removeClass('current_page_item');
});
// not sure what the following code is referencing too
// it is outside the bounds of .each() function.
jQuery(this).parents('li').addClass('current_page_item');
jQuery(this).parents('li').addClass('current-menu-item');
what is this
When working with JavaScript and many Object Oriented programming languages the this keyword is used to refer to the current context that the programmer is working with. You're currently referencing to the ul.menu li element so by using this you make a call to the element that is selected in the .each() function.
You can replace it by using the element selector that you used in the each() function.
jQuery('.current-menu-item').removeClass('current-menu-item');
jQuery('.current_page_item').removeClass('current_page_item');
Here I am making the assumption that only one item will ever have those classes as it would denote which menu item is currently selected. The best way to select it is then to search for the class you want to remove. (If those classes always go together, you could also remove both on the same line, although then you might want to consider whether you actually need both.
jQuery('ul.menu li').on("click", function() {
jQuery(this).addClass('current_page_item').addClass('current-menu-item');
}
You can only use "this" as an argument for the selector when "this" has a value (i.e : inside an each loop or inside on.
In this case I am using the on() function to apply the function which adds the class to any of the list items which gets clicked on.
Merging the two you would then end up with :
jQuery('ul.menu li').on("click", function() {
jQuery('.current-menu-item').removeClass('current-menu-item');
jQuery('.current_page_item').removeClass('current_page_item');
jQuery(this).addClass('current_page_item').addClass('current-menu-item');
}

jQuery: Refreshing an element

I'm using this accordion-like script:
jQuery(document).ready(function () {
jQuery(".content").hide();
jQuery(".heading").click(function () {
jQuery(this).next(".content").slideToggle(500)
});
});
But then I add this line in order to reload the element after the content div toggles...
document.getElementsByClassName(transition current).reload();
and as a result, the accordion no longer works... The content class is always being displayed.
Why is this line affecting the behavior of the accordion?
I'm trying to refresh the element while retaining the accordion style divs...
Any ideas?
You need to use event delegation since the elements are created dynamically
jQuery(function ($) {
$(".content").hide();
$(document).on('click', ".heading", function () {
$(this).next(".content").stop(true, true).slideToggle(500)
});
});
Still you might have a problem of all content element getting displayed once the element is reloaded, for hiding those elements you need to use any load callback system provided by the reloader you are using
You've got a syntax error here:
document.getElementsByClassName(transition current).reload();
getElementsByClassName expects a string to be passed (not to mention that the above isn't syntactically correct even if it did expect two arguments). You're trying to pass two variables (which you haven't defined). Pass a string:
document.getElementsByClassName('transition current').reload();
Blast. That doesn't work either! Reading the docs informs us that getElementsByClassName returns an HTMLCollection, which doesn't have the method reload(), resulting in another error. Are you even looking at the console?
You may be assuming that getElementsByClassName returns a jQuery object, in which case you can replace the above with $('.transistion, .current').reload();
Again, let's note that reload() isn't a native jQuery method either. I'm assuming you're bringing it in via a plugin. If I'm wrong, comment below and I'll update the answer.
I was using the isotype jQuery plugin, so the issue was resolved by adding this one line as a callback to "relayout" any changes that were loaded into the DOM.
$('#blog-list').isotope('reLayout');

Categories