jQuery change css of an element when another element becomes active - javascript

I am trying to change the background colour of a label adjacent to an input element when the input becomes 'active'.
This will need to work for both clicking to the input and tabbing between input elements.
I was able to get this to work if the user clicked the input, but my solution didn't work if the user tabbed into an input element. I was also having to repeat the code for each input element. Considering I am likely to have quite a few input elements, I figured there must be a more graceful way?
Here is a link with the basic HTML + CSS.
http://jsfiddle.net/xXqhH/

Assuming I've understood what you're trying to do correctly, just bind event handlers to the focusin and focusout events. You can use prev to find the immediately preceding sibling, and css to set a CSS property:
$("input").focusin(function() {
$(this).prev("label").css("background-color", "red");
}).focusout(function() {
$(this).prev("label").css("background-color", "gray");
});
Here's an updated fiddle.

I lied in my comment - I am going to write this from scratch. I assume the problem you had where it was working with clicking, but not with tabbing, was due to using the .click() jQuery function. Using .focus() instead, along with a CSS class, should provide the desired result:
jQuery code:
$('input:text').focus(function(e) {
$('label').removeClass('active');
$(this).prev('label').addClass('active');
});
Extra CSS:
label.active {
background: red !important;
}
Working Demo

Related

Element with display:none is not counted as hidden by jQuery

I have an element which has display:none initially. When I click a button, a jQuery event is triggered, and my script toggles the element's display attribute between block and none when the button is clicked.
I am trying to make it so the background of the element's parent changes color depending on whether or not the element is hidden.
$("#button").on('click', function(){
if($(".hidden-content").is(":hidden")) {
$(".other-element").css("background-color","rgba(20,20,20,.9)");
} else {
$(".other-element").css("background-color","rgba(20,20,20,0)");
}
})
For some reason, when I click the button to toggle the dropdown, the jQuery treats the .hidden-content like it's not hidden, even though when I inspect the element, it says
.other-element { display: none };
Does anyone know why this could be? Since the hiddenness is toggled using jQuery, it may not actually change .hidden-content's own css, but I don't see why that should be a problem on the very first click.
The easiest solution is to add a CSS class to the element whose background-color property you want to change. Check it out:
In your click function, you can use jQuery's .toggleClass() method to add and remove a CSS class every time the button is clicked. In your CSS, you can then override the default background color with the new class selector. There's an example below. It sounds like you have your own method of hiding and showing the content, so for this example I'm just going to use jQuery's .toggle() function to do that bit.
I've created a working example on CodePen for you as well :)
$('#button').on('click', function() {
// The important part: add and remove the CSS class to change colors!
$('#parent-element').toggleClass('content-on');
// Hide and show the content element. You can do this differently of course:
$('.content').toggle();
});
And your CSS would look something like this:
#parent-element {
background-color: rgba(20,20,20,.9);
}
#parent-element.content-on {
background-color: rgba(20,20,20,0);
}

jQuery: Get elments with custom attribute that has hidden child, add live hover function

I wanted to get all elements that has a specific attribute and has a child of a specific type that is hidden. To do this, I wrote this selector:
$("*[custom-attr]:has('span:hidden')")
In addition to this, I wanted to add a live function on hover. For example like this:
$("*[custom-attr]:has('span:hidden')").live("hover", function() { /* do something */ });
I thought this was working properly, since I got the visual result I wanted. However, when using Firebug, I noticed that it was probably not perfect. When moving the mouse within the body, even if not hovering the elements that were meeting the selection, Firebug indicates that the HTML elements hovered are affected (they appear as yellow in Firebug HTML tab). See attached image:
Why is this and how can I avoid it?
I noticed that a similar selector did not cause the same behavior, like this one to get elements without the span child:
$("*[custom-attr]:not(:has('span'))").live("hover", function() { /* do something */ });
Thanks.
Try using natural browser selectors and that way avoid jQuery adding temporary attributes. For your case, instead of has() you can use:
$("[custom-attr]").on("mouseenter", function() {
if ( $(this).find('span:hidden').length ) {
/* your code */
};
});
Since you're getting the visual results you are expecting, it sounds like it's working. I think Firebug simply highlights elements that have recently had something change on itself or, if collapsed in the HTML view like on your screenshot, somewhere among its children. This highlighting will happen both when e.g. an attribute is change and when the change is reverted on e.g. mouseleave, and the highlighting will stay for some time after the change has occurred.
That said, it's also a good idea, as Kartikeya mentioned in a comment, to switch from .live(), which is deprecated, to .on().

Using `.toggle()` rather than applying a class to show content

I'm working on a simple website to use at a conference and I'm looking for some help understand the implications of two ways to achieve an effect:
Using .toggle() to show or hide content
This is the method I started with because it is an intuitive action to tap an element to have it's content appear. However, a problem arises when I try to limit one open div at a time.
Summary I'm having trouble limiting the number of opened elements.
Applying an active class with jQuery
Using this method, I can display the hidden content by selecting the child element (see code below), but this stops the user from closing the content by tapping it again. Because I'm expanding divs horizontally, this isn't ideal because of the scroll space that's added.
Summary: How do you close the active div on a second click with this method?
CodePen Demo - Staged site
Relevant Code
This method is using CSS to apply the active class. It works, but like I said above, I'm having a hard time removing the active class from an element tapped again. Use the demo linked above to see how the toggle action works on the page (uncomment lines 8 and 9).
$(".title").click(function() {
//remove active class from other elements
$('.post').removeClass('active');
// Bind to the div
$post = $(this);
// Set active class on .post to control scroll position
$post.parent().toggleClass('active');
// Toggles the hidden .content div
//$post.next().toggle(250);
$('html, body').animate({scrollLeft: $('.active').offset().left},500);
});
The accompanying .active CSS:
.post .content {
display:none;
}
.active {
margin-top:-120px;
}
/* Shows the content div rather than toggling with jQuery */
.active > .content {
display:block;
}
Is there a way I can allow both behaviors (tap to open/close, one open div at a time)? Which method is best suited for that?
You certainly can use toggle() while hiding the other ones. Try something like this:
$(".title").click(function() {
$('.post').not($(this).parent()).hide();
$(this).toggle();
$('html, body').animate({scrollLeft: $(this).parent().offset().left},500);
});
Update: changed .not(this) to .not($(this).parent()) as .title is always child of .post.
Slightly optimised version of #Daniel's solution
$('.title').click(function() {
var clickedPost = $(this).parent('.post')
clickedPost.toggle().siblings('.active').hide();
$('html, body').animate({scrollLeft: clickedPost.offset().left},500);
});
Local var: If you access this, or any other DOM element more than once inside a scope, it's always more efficient to assign it to a local var than wrap it in a JQ object multiple times.
SIblings selector: I don't have a benchmark for this, but running a selector on a subset of the DOM rather than the whole DOM seems intuitively faster. This is more best practice than a large performance hit, but all the little functions add up too.
Chaining JQuery functions: Most JQ functions that act on a JQ element return that element. I can't say that this is more efficient but it's certainly more concise, but this all depends on personal preference.
With very little code you can do this with toggle.
$(".title").click(function() {
$(".post").hide();
$(this).children(".post").toggle();
});
I made it as simple as possible to show the functionality which you could then extend on.
Here is a jsfiddle
EDIT update after comment
I have edited it to now only show 1 at a time and if the 1 currently being shown is clicked it hides it
I also elected to use slideUp() and slideDown() as it seemed to better suit your needs
$(".title").on("click", function(){
if($(this).children(".post").is(":visible")){
$(this).children(".post").slideUp();
}else{
$(".post").not($(this).parent()).slideUp(500);
$(this).children(".post").slideDown(500);
}
});
updated jsfiddle

Forcing an element to :hover with JavaScript when dragging an element over it. No jQuery

I've found a couple of search results here but they're all for jQuery and the couple I looked at weren't applicable to my case.
This is a small project and I've avoided using jQuery so far. I want to keep it like that as to not need the library.
Basically, I'm dragging an <article> element to a <div> element. The div has the background-image of a closed trashbin. In the CSS it is set to display the same, but open, trashbin when :hover is triggered.
Now, when I pull my article element to the div, the :hover effect isn't being triggered.
How do I do this?
All required elements are set draggable and the needed event listeners have been added, Console.log confirms they work.
You can define a CSS class called 'open_trash' and set the background image of a open trash there and then you can use javascript to change the class of the dragged element on mousedown like this
document.getElementById("draggedItem").className = "open_trash";
You can set the class name to either an empty string or something else onmousedown.

How do I hide an element with the same markup via jquery?

I have two custom dropdown lists that have the same markup. I need to have only one show at a time. Right now, I'm able to open both at the same time. Both should also close when I click off the list.
The same markup for both lists is required, so I can't use unique ID's or additional classes to make this happen.
Here is a link to my fiddle example: http://jsfiddle.net/dg7Lc/29/
Any help would be greatly appreciated, thanks!
-D
Consider adding a data attribute such as 'active' via jquery when you click on one of them, then hide all those that have that attribute.
$('.custom-select').eq(0).hide() will hide the first one.
Use .show() instead of .hide() to show (obviously) and change the index to (1) to get the second one.
First thought would be if you could wrap a span or div around either or both and use that to get around the "same markup" limitation. Other than that, though, I'd suggest using order in page - use .next() and .prev() to get between them, and something like
$("div.custom-select").get(0)
or
$("div.custom-select").get(1)
to select them from outside.
edit: if you can run them off of something like an onmouseover, onchange, or whatnot, it's even easier - the one that's changing will be passed into the function as the "this" parameter. Just hide both, and show this, or show both and hide this.
edit2: similarly, once you have one of them hidden properly - well, that one will be hidden, and respond to the ":hidden" selector. Use that to distinguish between them (and save the distinction as a jquery variable) before you go showing or hiding anything else
Hide the first:
$('.custom-select').first().hide();
Hide the second:
$('.custom-select').last().hide();
And then put these lines of code where needed.
http://jsfiddle.net/dg7Lc/31/
Basically, closing the others:
$('.custom-select').not(this).find('ul').slideUp('fast');
And for closing when clicking outside the box, I used this piece of code but it's a bit dirty:
$("body").click(function(e) {
var should = true;
for($e = $(e.target); should && $e.length; $e = $e.parent()) {
should = !$e.is(".custom-select");
}
if(should) {
$('.custom-select').find('ul').slideUp('fast');
}
});
You can bind a click to the document, that looks to see if they clicked on the custom-select or the document outside it and hides any open lists as it should:
$(document).click(function(ev){
if(!$(ev.target).is('.custom-select span')){ $('.custom-select').find('ul').slideUp('fast'); }
});
Updated JSFiddle

Categories

Resources