Can I rewrite Javascript without using 'this'? - javascript

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');
}

Related

Assigning JQuery On Click Function in For Loop

I have a function that dynamically creates div elements based upon whatever input is given, and lets them choose certain items by clicking on each div. I have it so that if the div is clicked, a function (named checkToggle) is called that makes it looks like it is selected and adjusts some related variables. There is a checkbox in the div element that is toggled by this function (hence its name). Long story short, I had to jump through some hoops to get it to work, most of which I don't even remember. Please don't ask me about that.
The point of this question is this. I initially used the following JavaScript code to run the function when the checkbox was clicked. It was assigned by the main function, which created these div elements using a for loop.
document.getElementById(`${itemID}-checkbox`).onclick = function() {
checkToggle(`${itemID}-checkbox`);
};
This works, but I wanted to try to convert all of my onClick functions to JQuery. Here is the JQuery alternative I created.
$(`${itemID}-checkbox`).on(`click`, function() {
checkToggle(`${itemID}-checkbox`);
});
While the code itself seems to be fine, it does not work. It seems as if JQuery functions cannot be created like this in a for loop or something. It is applied after the element is created and put in its place, so I don't think it has anything to do with the element not being ready. I am also having the same issue with 2 other similar cases. Any idea as of why this isn't working?
Let me know if more information is needed and if so, what kind of information is needed.
You need to update the selector to Target HTML id using the # character. Simply prepend the character to the query:
$(`#${itemID}-checkbox`).on(`click`, function() { checkToggle(`${itemID}-checkbox`); });
It would also apply to DOM methods querySelector or querySelectorAll as well.
Hopefully that helps!

jQuery Select One Element From Class name

I am in a position where I need to use the .slideToggle() function in jQuery, on a regular JavaScript determined element.
I can use this code:
var feedback = document.getElementsByClassName('feedback');
and then a bit later on in a function:
feedback[index].style.display = 'block';
However, what I want to do is use the slideToggle('fast') function on feedback[index], so instead of so brutally changing its display to block, I get a nice jQuery-esque transition.
Obviously this code won't work:
feedback[index].slideToggle('fast');
However this will:
$('.feedback').slideToggle('fast');
but I can't choose which feedback by index to run the slideToggle() function on, it just does them all, which makes sense.
If I could get some code that effectively does this:
$('.feedback')[index].slideToggle('fast');
That would be perfect. I like the fact that I can stick a class on something and iterate through the list of items that appear in .getElementsByClassName('classname'), so I don't have to stick an ID on everything of the same class, and it would be nice if I could choose which $('.feedback') element I am using in the list of all elements returned by this but I cannot figure out how that would work. If I can somehow choose by index which items in a list by class, to run jQuery commands on it would make this a lot simpler as I do not want to stick an ID on each and every item that has the class of feedback.
Thanks a lot.
Try this : You can use eq() to select element with specific index.
$('.feedback:eq('+index+')').slideToggle('fast');
You can use JQuery like this:
$(feedback[index]).slideToggle('fast');
Here you can see demo

Jquery remove function follow up

I submitted this question last week:
chrome not working with jquery remove
and was able to resolve it (stupidity on my part really), however my example was very simple. Currently I'm trying to use .remove to eliminate a complete div from a page before sending an array of inputs to an ajax function. However, I am not able to get .remove to work at all.
Here's my latest try:
http://jsfiddle.net/CJ2r9/2/
I get function not defined on the jsfiddle on multiple browsers. On my application I get absolutely no errors, but nothing works either.
I'm relatively new to javascript scopes, so if the problem is scope-wise then please let me know how I'm screwing up.
I have also tried using the .on jquery function, but it's a bit more confusing considering my div ids are dynamically loaded from the server (jstl, spring MVC, etc). If that's a solution please let me know how I can get on the right track.
Thank you!
The two problems in your jsFiddle are:
Scope: removeElem is not in global scope, since you left the default configuration option to execute the code on DOM ready. You can change it to "no wrap" to make the funciton global.
The elements you want to remove don't exist. The div elements have IDs like "removeXXXp" and in your event handlers you pass "removeXXXs".
Here is an other, simpler solution (in my opinion) for element removal. Given your markup:
<div class="scheduleSet" id="remove315p">
<!-- ... -->
Remove
</div>
You can use .on like so:
$('.schduleSet a.optionHide').on('click', function() {
// traverses up the DOM tree and finds the enclosing .schduleSet element
$(this).closest('.scheduleSet').remove();
});
You don't even need IDs at all.
I made a simple fiddle, the inline onclick doesn't see the function defined in javascript so I get a ReferenceError: myRemove is not defined.
By adding the listener in js, .remove() works fine.
Sorry I don't know what causes the difference in behavior though.
Test it out: http://jsfiddle.net/xTv5M/1/
// HTML5
<div id="removeme">foo bar</div>
<button onclick="myRemove('removeme')">Go</button><br>
<div id="removeMe2">foo bar</div>
<button id="go2">Go Again</button>
// js
function myRemove(name){
$('#'+name).remove()
};
$('#go2').click(function(){ myRemove('removeMe2') });
I see that you are already using jquery. Why dont you do it this way:
<div id="foo">This needs to be removed</div>
Remove
function removeElem(element){
$('#'+element).remove();
}
$(function(){
$("#remove").click(function(){
removeElem($(this).data('remove'));
});
})
Fiddle here: http://jsfiddle.net/vLgpk/
They way this works is, using data-remove (can be anything like data-xyz btw), binds the remove link with the div. You can then read this binding later when remove is clicked.
If you are new to jQuery, and wondering what data-remove is, its just custom attribute that you can add to you code which can be later retrieved using the data() call on the element. Many great frameworks like Bootstrap use this approach.
Advantage of using this approach in my opinion is you can have the remove links anywhere in your UI and they don't need to be related structurally to your divs by siting inside them.

jQuery on mouseout do nothing?

I have some effects in my menu, which works fine, but these effects shouldn't trigger on a menupoint which belongs to class "active". How should I do that? Using eval or similar things?
To sum it up: I want to deny an effect if the trigger has a special class.
In each of your mouse events, use .hasClass() in an if() statement:
$('.selector').mouseout(function() {
if($(this).hasClass('active'))
{
return;
}
// The rest of your code.
});
Here, the if() checks to see whether the element the event was fired on has the class active. If it does, the function returns, not executing any more code inside it.
You haven't given any code or HTML to work with, so this is a general solution. Please update your question with more detail so I can give you a better answer.
In the trigger function, just wrap your code with
if ($(this).not('.active')) {
...
}
JamWaffles and Cito's way works and are the most effective but just as an alternative you could also do it like this, first fetch the class value:
var className = $('.myclass').attr('class');
Then you want to check the value
if (className != 'whatever') {
// animate and stuff etc
}
But like I said, the other methods are better so you might as well use the built in features of jQuery such as hasClass - just showing theres more than one way to tackle problems :)
bind to (not) active like this:
$('.menuitem:not(.active)').live('mouseout',function(){});

JQuery event selector

Say i have 10 small images that i want to use as tooltips.
Im assinging them all the same class, '.helper'
Im selecting helper, then calling
mouseenter(function() { $(".helper").stop(false,true).fadeIn(); })
I then want a div to popup, containing some text. This works fine if there's only one tooltip on the page, but as soon as there is more than one, whenever i hover over one, they all appear at the same time.
Have i got something fundamentally wrong?
Comments appreciated.
Thx
Use this as the selector inside instead of the .helper selector again:
$('.helper').mouseenter(function() {
// "this" now refers to the image that is being hovered...
$(this).stop(false, true).fadeIn();
});
If you're wondering what the problem was, it was that when you called
$(".helper")
within your function, you were getting all the elements with class helper, in stead of just the single element you wanted.

Categories