Change elements/classes in/with jquery - javascript

I'm new in jQuery and used it right now for a navigation, that slides in and out in mobile or small views. That works fine and correct, but I'm using a plus-icon to open a submenu, that changes into a minus-icon, when the submenu is opened.
But it doesn't change back into the plus-icon, when the submenu is closed.
The code is the following:
$(document).ready(function() {
$('<span class="menu-expander"><span class="plusicon horizontal"></span><span class="plusicon vertical"></span></span>').insertAfter('.level_2');
$('#menu-toggle').click(function() {
$(this).next('#navigation-main').slideToggle();
});
$('.menu-expander').click(function() {
$(this).prev('.level_2').slideToggle();
$(this).children('span.plusicon.vertical').toggleClass('plusicon vertical');
});
});
I think the "interesting" part might be the second function, the first is still for a hamburger-icon, that opens the navigation, that works (okay, it doesn't show a sliding animation, what the second one do... no idea, why it don't works...).
So the second part is for the plus. When I click on the plus, the submenu slides in and the plus changes to the minus, but when I click back to the the minus it doesn't change back to the plus.
Has somebody any idea why it doesn't work or can explain me, how I can do it work?
Regards,
Markus

The problem is that your selector is trying to find a span with both plusicon and vertical classes but after the first call to this:
$(this).children('span.plusicon.vertical').toggleClass('plusicon vertical');
wich removes said classes, it is not able to find your target span.
To work around this you could assign an id (iconId on the next example) or another class to your icon so it can be allways found
$('<span class="menu-expander"><span id="iconId" class="plusicon horizontal"></span><span class="plusicon vertical"></span></span>').insertAfter('.level_2');
...
$('.menu-expander').click(function() {
$(this).prev('.level_2').slideToggle();
$(this).children('#iconId').toggleClass('plusicon vertical');
});

Do this :
$('.menu-expander').click(function() {
$(this).prev('.level_2').slideToggle();
var $icon = $(this).children('#ID OF ELEMENT'); // Would be easier to add an ID to your element whcih you want to alter - limits the error possibilties :)
if($icon.hasClass("CLASS YOU WANT TO GET RID OF"){
$icon.removeClass("CLASS YOU WANT TO GET RID OF");
$icon.addClass("THE CLASS YOU NEED");
else{
$icon.addClass("THE CLASS YOU WANT TO ADD");
}
});
I am at work now so pardon any typing errors.
You basically need to check whether the class that changes the icon to a MINUS symbol is still active - if so you change it back.

I hope it will help.
Points:
to find element good to use find();
better toggle 1 class to show hide element like "show" in example;
With elements inserted with js code better use .on() (for future);
$(document).ready(function() {
$('<span class="menu-expander"><span class="plusicon horizontal">horizontal</span><span class="plusicon vertical show">vertical</span></span>').insertAfter('.level_2');
$('#menu-toggle').click(function() {
$('#navigation-main').slideToggle();
});
$('.menu-expander').click(function() {
$(this).prev('.level_2').slideToggle();
$(this).find('.plusicon').toggleClass('show');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<style>
.plusicon {display:none}
.show {display:block!important}
</style>
<ul>
<li id="menu-toggle" class="level_2">Toggle</li>
</ul>
<ul id="navigation-main">
<li>test</li>
</ul>

Related

Toggle Resource Groups not working 100% of time

I created something where only 1 resourceGroup can be expanded at a time. When another one is toggled open, the other one closes. However, this only works like 95% of the time. When I toggle them quickly, it might not work and two get opened. Can anyone figure out why and how to fix this?
$(document).on('click','.fc-icon-minus-square:not(.open_now)',function(e){
if($('.fc-icon-minus-square:not(.open_now)').length > 1){
$('.fc-icon-minus-square:not(.open_now)').addClass("open_now");
$('.fc-icon-minus-square').click();
}
else{
$('.fc-icon-minus-square').not(this).addClass("open_now");
$('.fc-icon-minus-square').not(this).click();
$(this).removeClass("open_now");
$('.open_now').click();
$(this).addClass("open_now");
}
})
https://codepen.io/adam-silver/pen/rNWLvYv?editors=001
I'd try to simplify the code and use an optional bit of CSS as well.
On-click:
Remove all open_now classes (don't check if the clicked element has open_now)
Add open_now class to the clicked element
Something like:
$('.fc-icon-minus-square').removeClass("open_now");
$(this).addClass("open_now");
And in the CSS, I'd go with (optional, if you don't want the opened to be clicked):
.open_now {
pointer-events: none;
}

How to change menu color using javascript

I'm trying to make a static side menu a little more dynamic by adding some effects to it.
From the code below I want "First Heading" and "Second Heading" to be distinct from their nested li's. I'm looking to have a background colour and a particular text (say red) and for these styles to be permanent. On the other hand, the nested li's (A1-B3) should have no background and the text should change from something like grey if not active to green if the link is selected.
<ul class="sideNav">
<li class="first active"><a>First Heading</a>
<ul>
<li class="first"><a>A1</a></li>
<li><a>A2</a></li>
<li class="last"><a>A3</a></li>
</ul>
</li>
<li class="last active"><a>Second Heading</a>
<ul>
<li class="first"><a>B1</a></li>
<li><a>B2</a></li>
<li class="last"><a>B3</a></li>
</ul>
</li>
</ul>
I've had a look on the forums and while this () seems to be similar to my requirements, my total lack of js/jquery knowledge is really hampering me.
Any guidance would be appreciated
::Edit::
This () might close to what I'm looking for (it's less complicated than the example in the previous link) but it doesn't quite cove what I need. So any help would still be welcomed.
You can just use CSS:
ul.sideNav li a {
color: red;
}
ul.sideNav li ul li a {
color: grey;
}
If you want to change the colors of certain things, you should use CSS conditionals really. For example, if I want my list items to be x color when moused over, y color default, and z color when clicked... my CSS would look like this:
ul.sideNav:link,li.sideNav:link
{
color:y;
}
ul.sideNav:active,ul.sideNav:visited,li.sideNav:visited,li.sideNav:active
{
color:z;
}
ul.sideNav:hover,li.sideNave:hover
{
color:x;
}
You can apply these to any tag, such as the anchor (), and there are a variety of different condtionals to use.
I'd highly suggest reading up on HTML, DOM, CSS, and JavaScript at W3Schools, they have a lot of good guides to get you going.
Please note this is not a direct answer to the question but I feel it would be useful for the OP and hopefully others
Whilst I most definitely aggree that in your case you can most simply use css to style your elements (please see #lennart's answer for example of child selection) there may be occassions when you need to be more dynamic when applying style, you can of course use jquery's .css() and similar functions, perhaps indeed use plain old javascript however this usually leads to dom traversal which can be fiddly even with jquery, the second option would be to dynamically add stylesheets which can also be quite effective, a third option would be to change/manipulate the <style> tag, for example you may have style defined in some json data where we can be a bit creative and build a string of css and add this to the <style>
// turn #accordion into a simple accordion menu
// adds style to the head from json data
$(document).ready(function() {
// hide <ul> nested in accordion
$('#accordion').find('ul').hide();
// add click event to accordion .heading
$('#accordion').find('.heading').click(function(e) {
// do not follow anchor
e.preventDefault();
// slide up any open sections
if(!($(this).hasClass('open'))) {
$('.open').removeClass('open').next().slideUp();
}
$(this).addClass('open').next().slideToggle();
});
// a function that parses json and
// appends it to <style>
function addStyleFromJson(json) {
// turn json into normal string
var style = JSON.stringify(json);
// remove apostrophes, colons before {, opening and closing {}
style = style.replace(/(")|(:(?=\{))|(^\{)|(\}$)/g, '');
// remove commas after }
style = style.replace(/(\}|\;),/g, function($0, $1){
return $1 ? $1 + '' : $0;
});
// prepend this style with any style declared in <head>
style = $('style').text() + style;
// append style element to head
$('style').text(style);
}
// load some style
$.ajax({
url: 'http://dl.dropbox.com/u/47426368/somejson.js',
dataType: 'jsonp',
jsonp: false,
jsonpCallback: 'myCallback',
cache: true,
success: addStyleFromJson
});
});
in this demonstration we turn html into an accordion style menu then load some json from a remote location and parse this into the <style> tag (presuming it is already there). As I have previously stated this may not be the best option and there are many options so as I said in my comment you must really learn this stuff in order to use it, it is no different from riding a bike or doing maths there is no magic just (hard)work and dedication :-), i hope that this demonstrates how you can use several technologies relatively simply to create something a bit more dynamically which I think was one of the reasons javascript came about
here is a demo

Changing multiple div background onclick , onmouseout and onmouseover

I'm working in a project here for over 30 hours and I might not be thinking straight.
Here's my situation. I have basically 4 divs that changes they background in diferents ways depending on the mouse action.
Lets call those divs here as div_1, div_2, div_3 and div_4.
When the user pass the mouse over the bottons on the menu the div_1 and div_2 should change they background to the background related to the button.
When the user click on a botton all the 4 divs should change they background and keep it even if the user move the mouse elsewhere.
And the last situation that you need to imagine is the one where the user clicked on one botton and after he pass the mouse over another botton. On this case, the div_1 and div_2 will still change but if the user remove the mouse from the menu div_1 and div_2 should return to the background related to the same background as div_3 and div_4.
I would appreciate if someone could help me to realize whats wrong with my code. Tnx.
Here is my code:
<ul>
<li id="menu-a1" onclick="Menu('a1','click');" onmouseover="('a1','over');" onmouseout="Menu('a1','out');" > Menu_a1 </li>
<li id="menu-a2" onclick="Menu('a2','click');" onmouseover="('a2','over');" onmouseout="Menu('a2','out');" > Menu_a2</ </li>
<li id="menu-a3" onclick="Menu('a3','click');" onmouseover="('a3','over');" onmouseout="Menu('a3','out');" > Menu_a3</ </li>
</ul>
<div id=div_1></div>
<div id=div_2></div>
<div id=div_3></div>
<div id=div_4></div>
heres my java script:
function Menu(where, action) {
switch (action) {
case 'click':
if ($('#menu-'+where).hasClass('active')) {
ClearMenu();
$('#menu-'+where).removeClass('active');
} else {
$('#menu-'+where).addClass('active');
ClearMenu();
ActiveMenu(where);
}
break;
case 'over':
ActiveMenu(where);
OverMenu(where);
break;
case 'out':
ActiveMenu(where);
break;
default: break;
}
}
function ClearMenu(){
// Removing Classes
$('#div_1').removeClass('a1 a2 a3');
$('#div_2').removeClass('a1 a2 a3');
$('#div_3').removeClass('a1 a2 a3');
$('#div_4').removeClass('a1 a2 a3');
function OverMenu(where){
$('#div_1').addClass(where);
$('#div_2').addClass(where);
}
function ActiveMenu(where){
// Adding Classes
$('#div_1').addClass(where);
$('#div_2').addClass(where);
$('#div_3').addClass(where);
$('#div_4').addClass(where);
}
and here is my css:
#div_1.a1 {background:url(background_div1_a1.jpg)}
#div_1.a2 {background:url(background_div1_a2.jpg)}
#div_1.a3 {background:url(background_div1_a3.jpg)}
#div_2.a1 {background:url(background_div2_a1.jpg)}
#div_2.a2 {background:url(background_div2_a2.jpg)}
#div_2.a3 {background:url(background_div2_a3.jpg)}
#div_3.a1 {background:url(background_div3_a1.jpg)}
#div_3.a2 {background:url(background_div3_a2.jpg)}
#div_3.a3 {background:url(background_div3_a3.jpg)}
#div_4.a1 {background:url(background_div4_a1.jpg)}
#div_4.a2 {background:url(background_div4_a2.jpg)}
#div_4.a3 {background:url(background_div4_a3.jpg)}
In your OverMenu function, you've got 'where' in quotes, presumably you want to reference the function parameter and not a string? Get rid of the quotes here.
Also, your CSS is wrong: you can't just give it a filename and expect it to know what to do, you have to set the background-image property:
#div_1.a1 { background-image: url(background_div1_a1.jpg); }
Also, in the onmouseover bits in your HTML, you're not actually calling a function. Presumably you want Menu in here.
UPDATE:
I would use jQuery for this. I've done an example on jsFiddle - http://jsfiddle.net/GrahamClark/gLGUQ/4/ - hopefully this is enough to get you started.

Facing weird problem while adding and removing class

i have below function which is being used to initialize a widget.
jQuery.fn.initPortlet = function( parent_component ,header , component ){
var o = $(this[0])
this.addClass("ui-widget ui-widget-content ui-corner-all")
.find(header)
.addClass("headertitle")
.addClass("align_center")
.addClass("defaultheadercolor")
.prepend('<span class="ui-icon ui-icon-minusthick"></span>')
.end()
.find(component);
};
what it does is append a minus icon at the top left corner of the widget.
i have some ajax call because of that this function get called multiple time and append a minus icon multiple times.
i am tring to re-write this function in such a way, so that how many time it's get called, append only one minus icon into header.
i tried fallowing approach but it didn't work.
var $minusthick = $('span.ui-icon ui-icon-minusthick');
$('div.div_header').find($minusthick).remove().prepend('<span class="ui-icon ui-icon-minusthick"></span>').end();
what i am tring is remove all span with class name span.ui-icon ui-icon-minusthick and finally append a minus icon, but it's not worked for me.
Edit
i am calling this function in this way-
$('.div_portlet').initPortlet('.div_portlet','.div_header','.div_content')
$('.div_portlet_inner').initPortlet('.div_portlet_inner','.div_header_inner','.div_content_inner');
html corresponding to this is-
html:
<div class="div_portlet" id="LINEITEM_HEADER" >
<div class="div_header"><%=hu.getFrameURL(82,83)%> Line Item Header Information</div>
<div class="div_content" id="LINEITEM_HEADER_CONTENT">
</div>
</div>
for second call html will remain same just classes will get change from div_portlet to div_portlet_inner, in the same way for other class.
i have written this function in a js file.
any help or suggestion so that i can achieve my goal will be highly appreciated.
Please guys help me out i got stuck at this point.
Thanks in advance!!!!!
Not sure what variable o is being used for - but the general point of my alteration below is to check to see if the class has been applied already, using the jQuery hasClass() function.
jQuery.fn.initPortlet = function( parent_component ,header , component ){
var o = $(this[0])
if (!this.hasClass('ui-widget'))
{
this.addClass("ui-widget ui-widget-content ui-corner-all")
.find(header)
.addClass("headertitle")
.addClass("align_center")
.addClass("defaultheadercolor")
.prepend('<span class="ui-icon ui-icon-minusthick"></span>')
.end()
.find(component);
}
};
ʞɔɐɯɹoↃɔW sǝɯɐſ gave a good solution to this problem, but here is an explanation why your attempt didn't work:
The first part of the selector 'span.ui-icon ui-icon-minusthick' is looking for a span with class ui-icon, as you intended, but the second part looks for an element of type <ui-icon-minusthick> which obviously doesn't exist. To select an element with multiple class names, add them all to the same selector just like you would in CSS:
$('span.ui-icon.ui-icon-minusthick')
Of course, the rest of you code would be a no-op since find($minusthick) will do nothing and therefore the rest of the jQuery chain will have no context in which to operate. This would (I think) work as you expected:
$('div.div_header').find('span.ui-icon.ui-icon-minusthick').remove().end().prepend('<span class="ui-icon ui-icon-minusthick"></span>');
The extra end() call returns the jQuery object to the first selector, in this case div.div_header and there is no need for the final end().

Getting my head around jQuery

OK, I'm designing a site and thought I'd stick some jQuery in as I really need so js experience.
Page with my problem is here: http://new.focalpix.co.uk/moreinfo.php
JS in question is:
$(document).ready(function(){
$(".answer").css("display","none");
$("#maincontent a.animate").click(function() {
$("#maincontent .answer").slideUp('slow');
var id = $(this).attr('href');
$(id).slideDown('slow');
return false;
});
});
This works fine, but if you click on a link where the answer has already slid down, then it slides up, then back down again.
I'm not sure on the cleanest way to stop this happening - any ideas?
You should be using the .slideToggle() effect.
$(document).ready(function() {
$(".answer").css("display","none");
$("#maincontent a.animate").click(function() {
$("#maincontent .answer").slideToggle('slow');
});
});
First, I'd suggest the following structure for your faq's:
<div id="faq">
<div class="qa" id="faq_greenandflies">
<span class="q">What is green and flies</span>
<div class="a">
Super Pickle!
</div>
</div>
<div class="qa" id="faq_redandbadforteeth">
<span class="q">What is Red and bad for your teeth</span>
<div class="a">
a Brick
</div>
</div>
<!--
More FAQ's here
-->
</div>
and then defining your jQuery as follows:
<script type="text/javascript">
$(function(){
// hide all answers
$('div#faq .qa .a').hide();
// bind a click event to all questions
$('div#faq .qa .q a').bind(
'click',
function(e){
// roll up all of the other answers (See Ex.1)
$(this).parents('.qa').siblings().children('.a').slideUp();
// reveal this answer (See Ex.2)
$(this).parents('.qa').children('.a').slideDown();
// return true to keep any other click events
return true;
});
// check location.hash to see if we need to expand one (direct link)
$(location.hash).find('.q a').click();
});
</script>
Explanation:
(Ex.1)
this is the link that was clicked
get the element that contains this and has a class of 'qa' (the box that contains both question and answer)
select all of its siblings. (we now have all qa's as a jQ object)
hide the answers
(Ex.2)
this is the line or link that was clicked
get the element that contains this and has a class of 'qa' (the box that contains both question and answer)
reveal the answer
A working demo is here.
This does several things for you:
If a user deep-links to an answer, the answer is automatically revealed
If a user clicks on one answer, all other answers are hidden
You can give your divs proper ids, so which helps search engine optimization of links to individual answers
Use slideToggle() like Soviut said, but just as a tip -- you can declare the display property in the actual CSS file instead of declaring it inside the javascript. jQuery will pick up on the fact that it is hidden in the stylesheet and still perform the appropriate slide function.
You can also use $(".answer").hide();
Instead of setting the display CSS property. Just thought I would let you know.
try using the one method, something like:
$(selector).one('effect', 'data for effect', callback function);
it makes sure an effect only happens once per element.

Categories