Problems with this-parent and this - javascript

I am trying to make a little quiz in jquery. So I'll have several div-blocks with each 2 li-elements (one for yes, one for no). Clicking one of these li-elements updates a variable, gives visual feedback and toggles the display of either the current div and the next div. That's the plan.
I do use this js-code:
var ergebnis = 0;
$(this).click(function () {
console.log(this.className);
if ($(this).hasClass("ja")) {
ergebnis++;
$(".ergebnis").html(ergebnis);
console.log(ergebnis);
} else {
ergebnis = ergebnis + 5;
$(".ergebnis").html(ergebnis);
console.log(ergebnis);
}
//Styles updaten
$("#frage__1 li").not(this).css({
opacity: '0.2',
transition: '1s'
});
$(this).css({
background: 'green',
transition: '1s'
});
$("#frage__1").slideToggle("slow", function () {});
$("#frage__2").slideToggle("slow", function () {});
});
And this html-code:
<!-- Frageblock 1 -->
<div id="frage__1" class="frage">
<h2>1. So you ever wanted to get alongside?</h2>
<ul>
<li class="ja"><h3>Yes</h3><p>Extra Text</p></li>
<li class="nein"><h3>Nope</h3><p>Extra Text 2</p></li>
</ul>
</div>
<!-- Frageblock 2 -->
<div id="frage__2" class="frage">
<h2>2. So you ever wanted to get alongside?</h2>
<ul>
<li class="ja"><h3>Yes</h3><p>Again text</p></li>
<li class="nein"><h3>Nope</h3><p>And another one</p></li>
</ul>
</div>
So you may already see that this is not really functional, as I always need to toggle all div-blocks in the very end of the code by hand; and currently do only get a result from the else-part. The console also logs me "undefined" at the very beginning and I always get my result always updated by 5, no matter what I click.
So I am looking for a solution how to exactly use this.parent() and something like not(this).parent at the very end of the code and what I did wrong at the very beginning with "this"
Thanks so much!

I'd try with these two small changes. First change your selector on the click handler from the following:
$(this).click(function () {
to the one below which uses the li element selector:
$("li").click(function () {
$li = $(this); //save a reference of the clicked li element
also above saves a reference to the clicked li element. With $li you can you to obtain the grandparent div reference in of the two following ways to change css:
$li.parent().parent().css({
background: 'green',
transition: '1s'
});
alternative:
$li.closest("div").css({
background: 'green',
transition: '1s'
});
More info about .parent() and .closest() methods. I hope this helps a bit :-)

Related

How to change the CSS of an HTML element with JavaScript

After reading some questions/answers about this subject I have tried to make it works for me but I can't.
The story line is that I have X elements (so it means no ID just class) and I want to change the background when I click in one.
So with JS I did:
'click .switch' (event) {
event.toElement.closest("li").css('background-color','black');
if(this.stateMachine == 'running'){
Meteor.call("switch", this.nameMachine);
}
},
to get the container (here a <li class="liMachine switch">) but I have this error:
event.toElement.closest(...).css is not a function
Despite the event.toElement.closest returns the right element:
So what am I doing wrong ?
$('.liContainer.switch').on('click', function() {
$(this).toggleClass('active');
});
.active {
background-color: powderblue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="liContainer switch">one</li>
<li class="liContainer switch">two</li>
<li class="liContainer switch">three</li>
</ul>
If $(event.target) works for you then the problem was of course that you did not pass a jQuery object. So you can not use jQuery functions on non jQuery object.
Since you are using Meteor, you may prefer this syntax:
"click .switch": function(event){
$(event.target).css("background-color", "black");
}

css() doesn't get fired with first click

I'm trying to toggle the css of two buttons in a list. If one is clicked, the other one should have no border, and vice versa. Here's my code:
function navigate_menu(event, ec){
$(event).css("border-top", "3px solid rgba(102,205,0, 0.8)");
var search_id=$(event).attr("name");
var chartid = "pie_chart_"+$(event).attr("name");
var editid = "edit_"+$(event).attr("name");
if(ec=="c"){
$(".li-edit").css("border-top", "0px solid rgba(102,205,0, 0.8)");
$("#"+chartid).appendTo($("#chart_"+search_id+"_container"));
$("#"+editid).css("display","none");
$("#"+chartid).css("display","block");
}else{
$(".li-chart").css("border-top", "0px solid rgba(102,205,0, 0.8)");
$("#"+editid).appendTo($("#chart_"+search_id+"_container"));
$("#"+chartid).css("display","none");
$("#"+editid).css("display","block");
}
}
HTML:
+"<ul id=\"navigation_list\">"
+"<li onclick=\"navigate_menu(this,'c')\" class=\"li-chart\" name=\""+search_id+"\">Chart & Legend</li>"
+"<li onclick=\"navigate_menu(this,'e')\" class=\"li-edit\" name=\""+search_id+"\">Edit Chart\\Change Data</li>"
+"</ul>"
So, when I first click, nothing happens, and then after the second it works. Then when I click on the other button, same (first nothing, second works). I thought that maybe on the first click it thinks I click on the parent (ul), but I don't know how would I fix it. And sorry for the pluses, its because this "menu" gets added to multiple elements from a JS function.
I have also tried addClass() and removeClass(), still same outcome.
Thank you!
Give each a li a shared class, e.g. li-item:
<ul id="navigation_list">
<li onclick="navigate_menu(this,'c')" class="li-chart li-item" name="+search_id+">Chart & Legend</li>
<li onclick="navigate_menu(this,'e')" class="li-edit li-item" name="+search_id">Edit Chart Change Data</li>
</ul>
Then use a JQuery .on("click" function to detect the click and apply the border to the clicked and remove from all others:
$(document).ready(function() {
$(document).on("click", ".li-item", function() {
$(this).addClass("border");
$(".li-item").not($(this)).removeClass("border");
})
})
Make a CSS class with the style to apply:
.border {
border: 2px solid blue;
}
Fiddle: https://jsfiddle.net/w9bwq57m/
Create bordered class in your css. Then call this fn somewhere in your click handler by passing element and second argument (no idea how to name it) I just wrote context. Make sure that you have deleted obsolete staff from the code above , which is responsible for border change .
function toggleBorder(element, context){
if(context === 'c'){
if($(".li-chart").hasClass('bordered')){
$(".li-chart").removeClass('bordered');
}
$(".li-edit").addClass('bordered');
}else{
if($(".li-edit").hasClass('bordered')){
$(".li-edit").removeClass('bordered');
}
$(".li-chart").addClass('bordered');
}
}
I would suggest using jquery click instead of onlick on li elements. Also you'd need to add data-key="c" and data-key="e" to the li elements so those values can be passed to the function:
$("#navigation_list li").click(function () {
navigate_menu(this, $(this).data('key'));
});

Alternate colors on click with jQuery

I'm sure there is a simple solution to this, and I'm sure this is a duplicate question, though I have been unable to solve my solution particularly because I don't really know how to phrase it in order to search for other questions/solutions, so I'm coming here hoping for some help.
Basically, I have spans with classes that assigns a background-color property, and inside those spans are words. I have three of these spans, and each time a user clicks on a span I want the class to change (thus changing the background color and inner text).
HTML:
<span class="alternate">
<span class="blue showing">Lorem</span>
<span class="green">Ipsum</span>
<span class="red">Dolor</span>
</span>
CSS:
.alternate span { display : none }
.alternate .showing { display : inline }
.blue { background : blue }
.green { background : green }
.red { background : red }
jQuery:
$(".alternate span").each(function() {
$(this).on("click", function() {
$(this).removeClass("showing");
$(this).next().addClass("showing");
});
});
This solution works great using $.next until I get to the third click, whereafter .showing is removed, and is not added since there are no more $.next options. How do I, after getting to the last-child, add .showing to the first-child and then start over? I have tried various options including if($(".alternate span:last-child").hasClass("showing")) { etc. etc. }, and I attempted to use an array and for loop though I failed to make it work.
Newb question, I know, but I can't seem to solve this so as a last resort I'm coming here.
try this:
$(".alternate span").each(function() {
$(this).on("click", function() {
$(this).removeClass("showing");
if($(this).is(":last-child"))
$(".alternate span:first-child").addClass("showing");
else
$(this).next().addClass("showing");
});
});
http://jsfiddle.net/NPx2x/
Check this, and also it performs faster. .next() returns undefined if no element found.
$(".alternate span").on("click", function() {
$(this).removeClass("showing");
var next = $(this).next();
next.length ? next.addClass("showing") : $("span.blue").addClass("showing");
});

Copy div class from the clicked item and insert into another div

I currently have a list of <li>'s. Each <li> will have a color class defined, example: .color-blue, .color-red, .color-green - like so:
<ul id="listings">
<li class="layer block color-blue" id="item-1"></li>
<li class="layer block color-red" id="item-2"></li>
<li class="layer block color-green" id="item-3"></li>
</ul>
How do I copy/get the color class of the specific <li> item that is clicked?
I have my click listener in place and also know how to get the <li "id"> however not sure on the specific class though.
/* Click listener */
document.getElementById("listings").addEventListener("click", function(e) {
//console.log(e.target.id + " was clicked");
});
Something like this:
document.getElementById("listings").addEventListener("click", function(e) {
var el = e.target;
if (el.tagName == "LI") { // Use only li tags
for (i=0; i < el.classList.length; i++) {
if (~el.classList[i].indexOf('color')) {
var color = el.classList[i];
console.log('color class found: '+color);
break;
}
}
}
});
http://jsfiddle.net/bHJ3n/
You can use (jQuery):
$('ul').find('li.layer block color-blue')
Or
$('ul#listings').find('li.layer block color-blue')
Or... you can not use jQuery as that wasn't in the original question and would be wasteful to include unnecessarily.
Here's a solution that works in vanilla JS:
jsFiddle Example
Essentially because you're lumping the colour among the other classes you have to split them into an array and iterate over them until you find the one that starts 'color-'. I would recommend you use a custom attribute instead, like data-color="blue" as that would mean you could just retrieve it with:
e.target.getAttribute('data-color');
Try
document.getElementById("listings").addEventListener("click", function(e) {
alert(e.srcElement.className);
});
DEMO
UPDATE(since it is not working in Firefox as pointed from Sai):
To work also in Firefox try this:
document.getElementById("listings").addEventListener("click", function(e) {
var target = e.target || e.srcElement;
alert(target.className);
});
DEMO2

Give multiple divs the same function

I want to create multiple thumbnails with the same .class. The thumbnail div contains 3 other divs. The first on is an image, the second one is a description which appear on mouseenter and the third one is a bar which change the opacity.
When the mouse hovers above the .thumbnail both elements should execute their function.
My Problem is that now every thumbnail executes the function, so every thumbnail is now highlighted. How can I change this so only one Thumbnail highlights while hovering above it?
HTML:
<div class="thumbnail">
<div class="thumbnail_image">
<img src="img/Picture.png">
</div>
<div class="thumbnail_describe">
<p>Description</p>
</div>
<div class="thumbnail_footer">
<p>Text</p>
</div>
</div>
jQuery:
$(document) .ready(function() {
var $thumb = $('.thumbnail')
var $thumb_des = $('.thumbnail_describe')
var $thumb_ft = $('.thumbnail_footer')
//mouseover thumbnail_describe
$thumb.mouseenter(function() {
$thumb_des.fadeTo(300, 0.8);
});
$thumb.mouseleave(function() {
$thumb_des.fadeTo(300, 0);
});
//mouseover thumbnail_footer
$thumb.mouseenter(function() {
$thumb_ft.fadeTo(300, 1);
});
$thumb.mouseleave(function() {
$thumb_ft.fadeTo(300, 0.8);
});
});
You code behave like this because you apply the fadeTo function to the $thumb_des and $thumb_ft selectors which contain respectively all the descriptions and footers of the page.
Instead, you should select the description and footer of the thumbnail triggering the mouse event, inside the mousenter or mouseleave functions.
Another thing you could change to optimize your code is to use only once the event listening functions, and perform both actions on the description and on the footer at the same time:
$thumb.mouseenter(function() {
var $this = $(this)
$this.find('.thumbnail_describe').fadeTo(300, 0.8);
$this.find('.thumbnail_footer').fadeTo(300, 1);
});
full working jsfiddle: http://jsfiddle.net/Yaz8H/
When you do:
$thumb_des.fadeTo(300, 0.8);
it fades all nodes in $thumb_des. What you want is to fade only the one that corresponds to the correct node in $thumb.
Try this:
for (i = 0; i < $thumb.length; i++)
{
$thumb[i].mouseenter(function (des) {
return function() {
des.fadeTo(300, 0.8);
};
}($thumb_des[i]));
});
}
You'll want to access the child objects of that particular thumbnail, something like this would work:
$(this).children('.thumbnail_describe').fadeTo(300, 0.8);
Here is a fiddle example.

Categories