background image event handler - javascript

If a HTML element (e.g. div) has a CSS background image is it possible to assign an event handler that is triggered when the user clicks on the background image, but not any other part of the element?
If so, a JQuery example would be much appreciated.

While it's not possible to detect a click on the background image, you can use some clever JS and CSS wizardry and come up with a masking element over the background image like this: http://jsfiddle.net/ahmednuaman/75Rxu/, here's the code:
HTML:
<div id="bg_img_1"></div>
<div id="bg_img_2">
<div id="hit"></div>
</div>
CSS:
div
{
display: block;
position: relative;
width: 200px;
height: 200px;
background-repeat: no-repeat;
background-position: center center;
}
#bg_img_1
{
background-image: url('http://placekitten.com/100/100');
}
#bg_img_2
{
background-image: url('http://placekitten.com/100/100');
}
#hit
{
display: block;
position: absolute;
width: 100px;
height: 100px;
background: #000000;
opacity: .3;
margin: 50px;
}
JS:
function handleClick(e)
{
console.log(e.target.id);
}
$( '#bg_img_1' ).click( handleClick );
$( '#hit' ).click( handleClick );

I think there is a better and simple way to achieve this here is my solution
$(document).ready(function() {
$("*").click(function(event)
{
if(event.target.nodeName == 'BODY')
{
alert('you have just clicked the body background');
}
});

Here is a very basic code that only work in x axis to show it's possible with injection of an img element with background-image url value as it's src and detecting the background image height and width to calculate if click happened on background image or not.
This code needs tons of improvement. It doesn't work in y axis. Also background-position and background-size are not involved. But it's easy to add those futures.
Here is Fiddle:
And here is jQuery code:
$('#d').bind('click', function(e){
var d = $(this),
bg = {};
//insert an image to detect background-image image size
$('body').append(
$('<img/>').attr('src',
d.css('background-image').split('(')[1].split(')')[0]
).attr('class', 'testImage'));
bg.h = $('.testImage').height();
bg.w = $('.testImage').width();
console.log(bg, e.offsetX, $('.testImage').width());
if(e.offsetX > $('.testImage').width()){
$('#l').text('it was NOT on background-image');
}
else{
$('#l').text('it was on background-image');
}
$('.testImage').hide();
})

Related

How to position two elements centered on top of each other?

The problem:
I have a form with a button underneath it to submit (post) from data with jQuery ajax(). I want for the button to be replaced with a spinner (animated png) for the duration of server ajax call. But such a trivial task is impossible in css to do right.
What i have tried:
I have placed button and image inside a bootstrap row. Ox ajax call I have set button display to none and img display to block. But because this two are not of the same size makes the whole page flicker, breaks the positioning of other elements and so on.
Another idea was to try to place both elements on top of each other with absolute positioning. But, stupid as css is I cannot center it on the middle of the row.
Is there a way to position both elements on top of each other so I can control their visibility?
Please bear in mind that I cannot used absolute position in pixel, because this is a web page and I do not not how wide the browser will be, image can change in the future, text in the button can change in the future, all this things affect absolute size.
If there is another solution to my problem which would prevent the page from jumping up and down it would also be great.
EDIT
Link to one of fiddle experiments:
https://jsfiddle.net/ofb2qdt8/
.button {
position: relative;
margin: auto;
height: 50px;
width: 30px;
background: blue;
z-index: 1;
display: block;
}
.spinner {
position: relative;
margin: auto;
height: 30px;
width: 50px;
background:red;
z-index: 2;
}
This renders second element underneath on screen. Not on different z layer.
Experiment 2:
https://jsfiddle.net/ofb2qdt8/
.button {
position: absolute;
margin: auto;
height: 50px;
width: 30px;
background: blue;
z-index: 1;
display: block;
}
.spinner {
position: absolute;
margin: auto;
height: 30px;
width: 50px;
background:red;
z-index: 2;
}
This does not center both elements, and they are pushed to the top of the containing div. The element with less height should be centered.
Check this working demo: https://jsfiddle.net/ofb2qdt8/3/
Add in a few lines of jquery and update your css.
Position your loading div according to button div's position, width, height using jquery.
*Click the button to see loading div, and try to play the margin of the button to any pixel.
###JQUERY
$(document).ready(function () {
$('.c2').each(function () {
$(this).css({
'width': $(this).siblings('.c1').outerWidth(),
'height': $(this).siblings('.c1').outerHeight(),
'top': $(this).siblings('.c1').offset().top,
'left': $(this).siblings('.c1').offset().left
});
});
$('.c2').on('click', function () {
$(this).hide(0);
});
});
###CSS
.c1 {
margin: 100px auto;
width: 100px;
text-align: center;
padding: 5px 10px;
background: blue;
z-index: 1;
}
.c2 {
position: fixed;
text-align: center;
background: red;
z-index: 2;
cursor: pointer;
}
Rough, ready and untested:
HTML
<div>
<input type='submit' />
<img src="spinneyIMage.gif" />
</div>
CSS
div{ text-align: center; }
div img{ display: none; }
jQuery
$('submit').click(function(e){
e.preventDefault();
$(this).hide().next().show();
});
After the Ajax call completes reverse the above jQuery.
As I haven't been able to find a working solution I have reverted to my first idea which I discarded at first. Albeit with a little twist.
HTML
<div class="row>
<div id="container-button" class="col-xs-12>
<button id="button" onclick="button_OnClick(e)">submit form via ajax</button>
<img src="img/spinner.png" sytle="display: none" />
</div>
</div>
JS
function btnContact_OnClick() {
// show the soinner and hide the button
showSpinner();
$.ajax(
{
type: 'POST',
url: "someurl.com/target",
data: $("#form").serialize(),
dataType: "json",
complete: function() { hideSpinner();},
success: onAjaxSuccess,
error : onAjaxError
});
}
function hideSpinner() {
$("#spinner").hide();
$("#button").show();
// make container height non-fixed and content adjustable again
$("#container-button").height('auto');
}
function showSpinner() {
// THis is the trick !!!
// Make the container fixed height as it was before displaying spinner, so it does not change with content (spinner is not the same height as button
$("#container-button").height($("#container-button").height());
$("#button").hide();
$("#spinner").show();
}
This is not the perfect solution but the best I could make.
Drawbacks:
it is not clean, you have to use javasript to fix what is css layout
problem
it still causes a little flicker
the height of container while displaying spinner is dependant on button, this may cause clipping if spinner is too big

javascript window scroll issue

I am working on javascript scroll. I have following html code
JSFIDDLE
<div class="wrapper">
<div class="red div current"></div>
<div class="blue div"></div>
<div class="green div"></div>
<div class="yellow div"></div>
</div>
In above code I have four div tags red, blue, green and yellow. All of them are position in following css.
html, body {
height: 100%;
}
.wrapper {
overflow: hidden;
height: 100%;
}
.div {
position: relative;
height: 100%;
}
.red {
background: red;
}
.blue {
background: blue;
}
.green {
background: green;
}
.yellow {
background: yellow;
}
In above html and css the red div tag is the current one which means user is seeing the red div tag on the screen. Now what I am trying to do is when user scroll over window once, then the next div tag i.e. blue will be animated and moved to the top and will become visible to the user whereas the red div tag will be behind the blue one. This same process goes for both green and yellow.
The problem is that when user scroll once then the div tag should animate however my current javascript code is keep reading the scroll and animating the div tags one after another. What I want is when user scroll once then scroll should be disabled until the blue div tag is animated. Then scroll should be enabled. Again when user scroll second time, the scroll should disable until the green div tag completes its animation. Same goes for yellow.
How can I achieve above?
Here is my javascript
$(window).on("scroll", function () {
var next = $('.current').next();
var height = next.outerHeight();
next.animate({top: '-=' + height}, 500, function () {
$(this).prev().removeClass('current');
$(this).addClass('current');
});
});
Please have a look on update JsFiddle
$(window).on("scroll", function () {
var next = $('.current').next();
var height = $('.current').outerHeight();
$('.current').prevAll().each(function(){
height += $(this).outerHeight();
});
next.animate({top: '-=' + height}, 500, function () {
$(this).prev().css('top','');
$(this).prev().toggleClass('current');
$(this).toggleClass('current');
});
});
The main reason your example wasn't working as expected is because you were relatively positioning the divs, and not moving them to the correct spot.
Working JSFiddle:
http://jsfiddle.net/seanjohnson08/rVVuc/6/
.wrapper {
overflow: hidden;
height: 100%;
position: relative;
}
.div {
position: absolute;
height: 100%;
width: 100%;
top: 100%;
}
.current{
top: 0;
}
If you are looking for a way to limit the amount of scroll events fired, try throttling: http://benalman.com/projects/jquery-throttle-debounce-plugin/. My solution doesn't require this, because no matter how many times it is firing the scroll event, it only ever tells jquery to animate to top:0, there's no chance of it animating past that.

How to make onclick event to div background image?

I created a div in html and assigned a background image to it, and i want to make an onclick event to that photo and don't know how, that's the div :
.add_btn {
background-color: #099;
position: absolute;
height: 35px;
width: 200px;
background-image: url(img/add.png);
background-repeat: no-repeat;
background-position: center center;
top: 265px;
You didn't give any information about your DOM except that you have an element with that class. It's hard to give a good answer but I'll try.
The following code will attach a function to the onclick events of all the elements with the add_btn class.
document.getElementsByClassName("add_btn").onclick =
function () {
alert("Hello");
};
Background image click is not possible. Because you have a foreground layer.
But you can use this JQuery for foreground image click...
$('.className > .Inner_Classname2= > img').click(function(e) {
alert("Ok");
});

How to add flag in a web based exam?

I want to add a simple flag that changes its color when clicked (e.i. transparent flag changes to red when flagged) for the web based exam I'm working on. Could someone help or give me a script on this.
Have a picture of a transparent flag and a flagged flag side-by-side in one picture (for example, the transparent one at {0, 0} and the red one at {0, 22} assuming a size of 22x22 pixels) and switch between them with JavaScript and CSS:
(In the CSS file)
.flag {
background-image: url('flag.png');
display: inline-block;
height: 22px;
width: 22px;
}
.flag.active {
background-position: 0 22px;
}
(In the JavaScript file)
function toggleFlag(flag) {
if(/\bactive\b/.test(flag.className)) {
flag.className = flag.className.replace(/(^|\s)active(\s|$)/g, "");
} else {
flag.className = flag.className ? flag.className + ' active' : 'active';
}
}
Just call toggleFlag with the flag when it should be toggled.
The simplest way is to use two images. When it's clicked, you hide one image and show the other. Working demo here: http://jsfiddle.net/jfriend00/yzYJ3/
HTML:
<div id="container">
<img src="http://photos.smugmug.com/photos/344287800_YL8Ha-Ti.jpg">
<img src="http://photos.smugmug.com/photos/344284440_68L2K-Ti.jpg" style="display: none;">
</div>
CSS:
#container {position: relative; height: 66px; width: 100px;}
#container img {position: absolute; top:0; left:0}
JS (jQuery):
var flagged = false;
$("#container").click(function() {
$(this).find("img").toggle();
flagged = !flagged;
});
Have you looked at jQuery and the examples at jQueryUI - http://jqueryui.com/

jquery slideshow using background images

I have a div which currently has a static background image.
I need to create a slideshow of background images for this div.
I am able to achieve this by just setting a timeout and then changing the background image in the CSS but this is not very elegant.
I would ideally like to fade the background images out and in, but the div contains other page elements so I can not alter the opacity in any way.
Does anyone know of a good way to do this using jquery??
Here's some code which fades out/in but fades out the contents of the div too.
$("#slideshow").fadeOut(5000, function(){
$("#slideshow").css('background-image','url(myImage.jpg)');
$("#slideshow").fadeIn(5000);
});
HTML:
<div class="slideshow"></div>
CSS:
.slideshow
{
position: relative;
width: 350px;
height: 150px;
}
.slideshow img
{
position: absolute;
width: 350px;
height: 150px;
z-index:-1;
}
jQuery
var images=new Array('http://placehold.it/250x150','http://placehold.it/250x150/123456','http://placehold.it/250x150/dbca98');
var nextimage=0;
doSlideshow();
function doSlideshow()
{
if($('.slideshowimage').length!=0)
{
$('.slideshowimage').fadeOut(500,function(){slideshowFadeIn();$(this).remove()});
}
else
{
slideshowFadeIn();
}
}
function slideshowFadeIn()
{
$('.slideshow').prepend($('<img class="slideshowimage" src="'+images[nextimage++]+'" style="display:none">').fadeIn(500,function(){setTimeout(doSlideshow,1000);}));
if(nextimage>=images.length)
nextimage=0;
}
jsfiddle Demo
How about adding a thumbs pagination list, to update the background image on click, and then, a second or two, and it starts fading in and out with the next bg img automatically?
HTML:
<div class="slideshow">
<h1>Text</h1>
<input type="button" value="Hello" />
</div>
<ul>
<li><img src="http://placehold.it/50x50"></li>
<li><img src="http://placehold.it/50x50/123456"></li>
<li><img src="http://placehold.it/50x50/dbca98"></li>
</ul>
CSS:
.slideshow
{
position: relative;
width: 350px;
height: 150px;
}
.slideshow img
{
position: absolute;
width: 350px;
height: 150px;
z-index:-1;
}
ul {position: absolute; top: 125px; left: 75px;}
li {
float: left;
border: 1px solid #000;
margin: 15px;
}
Javascript:
var images=new Array('http://placehold.it/250x150','http://placehold.it/250x150/123456','http://placehold.it/250x150/dbca98');
var nextimage=0;
doSlideshow();
function doSlideshow()
{
if($('.slideshowimage').length!=0)
{
$('.slideshowimage').fadeOut(500,function(){slideshowFadeIn();$(this).remove()});
}
else
{
slideshowFadeIn();
}
}
function slideshowFadeIn()
{
$('.slideshow').prepend($('<img class="slideshowimage" src="'+images[nextimage++]+'" style="display:none">').fadeIn(500,function(){setTimeout(doSlideshow,1000);}));
if(nextimage>=images.length)
nextimage=0;
}
See it all together at http://jsfiddle.net/tatygrassini/R4ZHX/75/.
Instead of just changing the background image, you could first call
fadeOut()
then change source, and then call
fadeIn()
something like...
$('#image').fadeOut(500, function() {
$(this).attr('src', 'new-image.png')
.load(function() {
$(this).fadeIn();
});
});
To use a variety of images, there are a number of solutions, but you could simply iterate through a list of them.
You can create an positioned absolutely and with a slider plugin change the images contained in the div. Otherwize you have to sprite the background. I achieved this with the Jquery Tools tabs plugin.
$(".slidetabs").tabs(".images > div", {
// enable "cross-fading" effect
effect: 'fade',
fadeOutSpeed: "slow",
// start from the beginning after the last tab
rotate: true
// use the slideshow plugin. It accepts its own configuration
}).slideshow();
Here is a solution that not only addresses your problem, but will also solve some other problems as well. Create another DIV on your DOM as an overlay, and execute your fade functions on this DIV only. It will appear as though the content is fading in / out. This approach is also more performant, as you are only fading a single DIV instead of multiple elements. Here is an example:
$('#containeroverlay').width($('#container').width()).height($('#container').height()).fadeIn('normal', function() {
// Step 1: change your content underneath the hidden div
// Step 2: hide the overlay
$('#containeroverlay').fadeOut('normal');
})
Most importantly, this approach will work in IE6-8 without screwing up the font aliasing of elements you may have on the div.

Categories