I’ve already spent hours looking at as many online resources and stackoverflow questions as I can find but for some reason I just can’t figure this out.
I’m attempting to use CSS and image sprites to make a link display as an image that changes once it is hovered over and once it has been clicked. I’ve played round with CSS and looked at JavaScript for far too long now and I just need some direction on how to get it working.
I’ve managed to make it change once its hovered over however what i really need to do is have the image change once it is clicked. So the begin with it displays the play button and when its clicked it displays a pause button, click it again and it displays the play button etc.
From what i can gather i will need to use JavaScript and an onclick event. However I’m not sure how this would work or how to use it with image sprites.
My CSS so far looks like this
.testclass .stratus {
background-position: -1px -1px;
width: 21px;
height: 21px;}.
.testclass .stratus:hover {background-position: -1px -29px; width: 21px; height:
21px;}.
However this only effects the play button and when it is hovered over. Now i need a way to display the pause button when the play button is clicked and vice versa.
Image sprites URL.
http://www.danceyrselfclean.com/wp-content/uploads/2012/12/sprites.png
URL of page im trying to get this to work on.
http://www.priceofmilk.co.uk/uncategorized/ddd-2
Can this be achieved using CSS and HTML or will I also need to use some JavaScript? Any assistance would be much appreciated.
I made a simple example. I use background colors and an anchor but you can easy implement this in your situation.
update
Updated the code so it uses your images.
HTML
<a class="play_pause">PLAY</a>
CSS
.play_pause {
display: block;
width: 24px;
height: 23px;
text-indent: -99999px;
background: url(http://www.danceyrselfclean.com/wp-content/uploads/2012/12/sprites.png);
cursor: pointer;
}
.playing {
background-position: -27px 0;
}
.playing:hover {
background-position: -27px -28px !important;
}
.play_pause:hover {
background-position: 0 -28px;
}
And the JS:
$(document).ready(function() {
$(".play_pause").click(function() {
$(this).toggleClass('playing');
});
});
JsFiddle example
If you only wanted to detect the first click, you could do this in pure CSS by giving the link an id and using the :target pseudoclass (e.g. a#theid:target {...})
But since you need to detect a second click, you'll need to use JS to toggle between CSS classes. The basic way is to use an event handler:
document.getElementById('theid').onclick = function(){
this.className = this.className=='play' ? 'pause' : 'play';
};
You will have to use JavaScript to accomplish the switching, there is no way to accomplish such logic with pure CSS.
The easiest way to go would be to have two classes play and pause. Through CSS you declare which part of the sprite you want to show for each of those classes. Then you attach a click-event listener to the element with JavaScript, and in the click-event callback you remove class play from the element and apply class pause instead, and vice versa.
MDN has a good article on how to attach event-listeners to an element. And this SO question discuss how you can add/remove classes on an element.
That is simple where have you read?
jQuery('.testclass .stratus').click(function{
jQuery(this).toggleClass('played');
})
css:
.played{
background-position: -1px -29px;
}
Example using .querySelectorAll and .addEventListener, with your current sprite. No jQuery is used.
var elm = document.querySelectorAll('.testclass .stratus'), i = elm.length, e;
while (e = elm[--i])
e.addEventListener('click', function () { // this fn generates the listener
var pause = false; // captured in scope, not global
return function () { // this is the actual listener
this.style.backgroundPositionX = (pause = !pause)?'-20px':'0px';
}
}(), false); // the () invokes the generator
Related
I want to toggle background-color and slideToggle on click. I also want a hover-over effect on all buttons. My hover-over effect stops working after the first click. I also haven't figured out a good way to toggle background-color as you will see by my code.
Here is my jsfiddle. This JavaScript code doesn't work if the same button is clicked twice:
$('#11').show().css({'background-color':'#cccccc'});
$('#22,#33,#44,#55,#66').show().css({'background-color':'white'});
Also, if you have any suggestions on how to make my JavaScript code cleaner/shorter, I'd like to see them.
With a little clean up you can simplify this whole thing a lot:
jquery
$(document).ready(function(){
$('.button')
.on('click', function () {
$('.button').not(this)
.removeClass('selected')
$('p.displayed').not($(this).next().next())
.slideUp()
.removeClass('displayed')
$(this)
.toggleClass('selected')
.next(/*br*/).next(/*p*/)
.slideToggle()
.addClass('displayed')
})
});
css
button.selected {
background-color: #ccc;
}
src: https://jsfiddle.net/yLr5equc/14/ (sorry, at first I forgot to hide the previous slideDown.. this is resolved now)
"Also, if you have any suggestions on how to my my javascipt
cleaning/shorter, I'm happy to listen. "
You don't need to repeat $(document).ready(function(){} every time for every new function/object. One $(document).ready(function(){} can store all your javascript/jquery code. That will shorten your code alot and make it less messy.
Like I did here: https://jsfiddle.net/yLr5equc/3/
Because the style defined in CSS has been overridden by jQuery-added inline style, therefore in .button:hover, add !important to background-color to make it the highest priority.
.button:hover {
background-color: #e6e6e6 !important;
cursor: pointer;
}
Updated solution: https://jsfiddle.net/yLr5equc/17/
No more !important as I answered above. I created the class .selected for .button and toggle it instead of inserting the style inline.
.button.selected {
background-color: #ccc;
}
I also have refactored the scripts, now shorter and work more effectively.
$(document).ready(function() {
$(".button").on("click", function() {
var $this = $(this),
$next = $(this).next(".slide");
if($next.hasClass("opening")) {
$this.removeClass("selected");
$next.slideUp("fast").removeClass("opening");
} else {
$this.addClass("selected");
$this.siblings().removeClass("selected");
$next.slideDown("fast").addClass("opening");
$next.siblings(".slide").slideUp("fast").removeClass("opening");
}
});
});
I'm trying to make a blink effect on click (instantly set background and then fade out) but on second click removeClass is not removing it. Where is a mistake?
JS:
$('div').click(function() {
$(this).css({transition: '0s'}).addClass('qwe')
.delay(1).queue(function() {
$(this).css({transition: '2s'}).removeClass('qwe');
});
});
CSS:
div{
height: 100px;
width: 100px;
background: gray;
}
.qwe {
background: green;
}
Fiddle
The browsers are built to optimize consequent style changes by coalescing them. In case of CSS transitions they do it a bit over-zealously.
Currently there's no 'clean' way around it, the best you can do in current browsers is force restyle via window.getComputedStyle(document).color or similar before the applying the changes that would invoke transition (removeClass in your case).
See
Clean way to programmatically use CSS transitions from JS? for more information.
Solved it using jQuery UI
$('div').click(function() {
$(this).addClass('qwe').switchClass('qwe', '', 1000);
});
I have a very large and complicated jQuery plugin which I will avoid posting here for simplicity's sake. My problem is very simple, and I will reduce it only to the relevant code:
I have a click event attached to a set of buttons:
$("ul.tick-boxes button").click(function(event) {
event.preventDefault();
$("ul.product-grid").addClass("loading");
$(this).toggleClass("active");
$theElement.trigger("filterOptionsChanged");
});
If you go to this link, you can see these in action in the left sidebar:
http://mazer.com/collections/refrigerator?preview_theme_id=22019779
Here is the css that produces a check-mark when you click the buttons:
ul.tick-boxes button.active .tick-box::after {
content: "\e603";
font-family: "custom-icons";
color: #51425d;
top: 2px;
left: 2px;
font-size: 0.75rem;
position: absolute;
}
If your computer is as slow as mine, then when you click these filter options, it takes a second or so to "tick" the "tick-box". If you can't see it, try unticking it, which for me takes noticeably longer. The time-point where the "tick" visibly renders is always simultaneous with the product-grid rebuilding and rendering. I haven't posted the code for manipulating the product-grid, but you can know that the line $theElement.trigger("filterOptionsChanged") triggers a lot of array and object processing to build a document fragment of the new product list, and updates the DOM at the end. I understand this can take a second, that is not my problem. But what I don't understand is why my "tick-boxes" are waiting until after the code of that event is finished to render. According to my css, all I need is a class active on the button, and that code is fired one line above triggering the "filterOptionsChanged" event, so it should fire before any product grid changes happen.
Now. If I open up my inspector in chrome, I can actually see the active classes toggling instantaneously on click, before the product grid updates. However, the css which adds the tick doesn't catch the active class on the element until after my "filterOptionsChanged" code completes.
My first attempt to solve the problem will be posted below. I read a good bit about the "expensiveness" of css pseudo-selectors. That essentially to a browser, it is like a dom manipulation every time an ::after element is created. So I then write this css:
ul.tick-boxes button .tick-box::after {
content: "\e603";
font-family: "custom-icons";
color: #51425d;
top: 2px;
left: 2px;
font-size: 0.75rem;
position: absolute;
opacity: 0;
}
ul.tick-boxes button.active .tick-box::after {
opacity: 1;
}
So now an ::after element always exists from the beginning, any rendering costs are paid for at the outset, so my thought was, now when I click this button, the tick is already there, we are just giving it an opacity of 1. Didn't fix the delay.
Now, I try removing the "filterOptionsChanged" event trigger entirely. This makes my whole sorting plugin stop working, but I don't care at this point, because I want to understand what is causing the problem. When I do remove that event trigger, the buttons and css render snappy. No more problems.
I have a vague thought that, ok, if a click event can be snappy without that event trigger, I need a way of seperating the two. First add the active class, then trigger "filterOptionsChanged". I think, ok, jQuery Deferreds. Here is that code:
$("ul.tick-boxes button").click(function(event) {
event.preventDefault();
var showLoading = jQuery.Deferred();
$("ul.product-grid").addClass("loading");
$(this).toggleClass("active");
showLoading.resolve();
$.when(showLoading).done(function() {
$theElement.trigger("filterOptionsChanged");
});
});
So showLoading is a blank Deferred, I then add my classes for the tick boxes to show, then I resolve the deferred. Now I say, when showLoading is done, then do the whole product-grid manipulation. Don't do these at the same time, javascript, wait for one to finish, then do the other. Still no avail. Any ideas?
According to this, all function calls in JavaScript block the UI until they complete; I'd wager that this includes the original function call to start the click event. A cheap solution might be to replace the trigger with something like:
setTimeout(function() { $theElement.trigger("filterOptionsChanged"); }, 200);
Which will hopefully delay the trigger long enough for the browser to repaint the UI (you could/should add a little loading icon in the original function, then remove it in the timeout). You could also take a look at web workers, which look like they're pretty much threads.
Try this,
CSS:
ul.tick-boxes button.active .tick-box::after {
content: "\e603";
font-family: "custom-icons";
color: #51425d;
top: 2px;
left: 2px;
font-size: 0.75rem;
position: absolute;
}
JS:
$("ul.tick-boxes button").click(function(event) {
event.preventDefault();
$("ul.product-grid").addClass("loading");
$(this).toggleClass("active").fadeIn(10, function () {
$theElement.trigger("filterOptionsChanged");
});
});
Using callback to delay the triggering. See if this work for you.
i have multiple images, on hover on particular image i want to apply on that image only, it should not effect on other image.
More Explanation:
In this example(http://codepen.io/anon/pen/AnsqI), suppose i have multiple images & want to apply the certain effect on only on that image where i hove my mouse.
I am using class attribute...
<script>
$(function() {
//For grid view hover effect
$('.grid_content').hide()
$('.grid_container').hover(
// Over
function() {
$('.grid_content').fadeIn();
}
,
// Out
function() {
$('.grid_content').fadeOut();
}
);
//--js for grid view hover effect ends here
});
</script>
Something i have to apply like $this , i tried like($this.$('.grid_content').fadeOut();)but it did not work.
Somebody please help me.
Use this:
$('.container').hover(function(){
$('.content',this).fadeToggle();
});
Check this Demo http://codepen.io/anon/pen/BxbID
You could consider using CSS and the opacity attribute (or display). You could progressively enhance the hover effect with CSS3's transition property as well. There isn't necessarily a need for JS here, and I only added five lines of CSS (unprefixed) to achieve the same effect.
.content {
width: 100%;
height: 100%;
background: rgb(255,255,255,0.9);
padding: 5px 15px 10px 15px;
box-sizing: border-box;
opacity: 0;
transition: opacity .2s linear; /* CSS3 progressive enhancement */
}
.content:hover {
opacity: 1;
}
Depending on how you organize your HTML, you may need to make modifications, but the concept is the same.
Check out the demo: http://jsfiddle.net/NeEuP/1/
There are 2 ways to do this. You can either reference it using the this javascript keyword and surrounding it in a jQuery function:
$('.grid_container').hover(function(){
$(this).fadeIn();
, function(){
$(this).fadeOut();
});
Or you can:
$('.grid_container').hover(function(e){
$(e.currentTarget).fadeIn();
, function(e){
$(e.currentTarget)$(this).fadeOut();
});
... basically you're getting element through the event object. I personally prefer this method, because it's more flexible it doesn't depend on the actual scope (this depends on scope).
I'm trying emulate the MS-DOS command prompt on my website. I don't need to accept keystrokes, but I'd like to append data at the bottom and optionally scroll upwards.
At first I looked at the asp:TextBox and asp:Label, but the flicker of using postbacks seemed to be too much. I'm now considering DIV tags and Javascript where I simply update the InnerHTML property, but there too I get flicker, and have issues with scrolling.
What solution would you recommend in this situation? Essentially I'm trying to count to infinity, with a 1 sec delay, only need the most current 300 or so entries, with the most current entry at the bottom of the screen.
Is this even possible with JS/CSS?
Do you wish to make it a little more stylous ? :)
see this page...
http://www.klaus.dk/Some_unknown_page
or this one
http://www.harryovers.com/404.html?aspxerrorpath=/Account/LoginPartial
here is the javascript source code.
http://code.google.com/p/c64-404-page/
With a little change, you can append your text on this code :)
I just built something very similar using jQuery. You can use the append method to add content to the bottom of your DIV. You can then set the scrollTop attribute to keep things scrolled to the bottom as follows:
$("#someDiv").attr({ scrollTop: $("#someDiv").attr("scrollHeight") });
I think "DOS-style window" is a bit misleading considering all you want to do is append text to a div and make sure it stays scrolled to the bottom.
function addLine(text) {
var box = document.getElementById('DOSBox') //teehee
var line = document.createElement('p');
line.innerHTML = text;
box.appendChild(line);
box.scrollTop = box.scrollHeight;
}
And style it as such
#DOSBox {
overflow: auto;
display: block;
height: 400px; width: 500px; /* or whatever */
/* and if you want it to look DOS-like */
background: #000;
color: rgb(192, 192, 192);
font-family: fixedsys;
}
#DOSBox p {
margin: 0;
}