Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to bind click event on image added using CSS 'background-image' property in jQuery

Here is my fiddle link

I guess my question is clear by title itself. Still, what I am looking for is an way to bind click event on the image added using css's background-image property.

I know, I could have achieved the similar functionality (of placing image over input field using this way or this way) by simply positioning <img> tag over input box and then handling the required events but that way didn't seem too flexible with input fields of varying width and height or if the wrapping div doesn't have position:relative; as its property.

If adding event on image loaded with background-image is not possible then how to make the later approach more flexible.

Hope I have conveyed my issues clearly.

Thanks.

like image 313
exexzian Avatar asked Jul 10 '13 22:07

exexzian


4 Answers

Something like this appears to also work:

$('.cross').click(function(e) {
  var mousePosInElement = e.pageX - $(this).position().left;
  if (mousePosInElement > $(this).width()) {
     $(this).val(''); 
  }
});

Link to example

like image 92
Brian Hoover Avatar answered Nov 01 '22 11:11

Brian Hoover


So you need to bind the click event to the image but not using an embebed attributte that's really a very good and dificult question by the way.

I know my approach is complicated but is the only I can figure right now.

You can get the image size (widthImage and heightImage) and know the position relatives of one to another (here is a way of calculating a position of an objet relative to anohter:jQuery get position of element relative to another element) you may use it to calculate the position of the input in the whole screen

and try something like this:

$(document).ready(function(){

  $('body').on('click', 'input.cross', function (e) {
        var widthInput = parseInt($(this).css('width'),10);
        var heightInput = parseInt($(this).css('height'),10);

        var position  = $(this).position();
        var top       = position.top;
        var left      = position.left;    

        var sizesRelativesInPercentage = $(this).css('background-size').split(/ +/);

        var widthPorcentage = parseInt(sizesRelativesInPercentage[0],10);
        var heightPorcentage =  parseInt(sizesRelativesInPercentage[1],10);

        var widthImage = (widthInput * widthPorcentage)/100;
        var heightImage = (heightInput * heightPorcentage)/100;

        var xFinalImageFinish= (left+widthInput);
        var yFinalImageFinish = (top+heightInput);


        // Fire the callback if the click was in the image
        if (e.pageX >= xFinalImageStart && e.pageX <= xFinalImageFinish &&
            e.pageY >= yFinalImageStart && e.pageY <= yFinalImageFinish) {

            // Prevent crazy animations and redundant handling
            $(this).off('click');
            alert('click on the image');

            //Do whatever you want
        }
    });
});

This is only an idea...I am trying to make a fiddle about this, hope so :O

like image 21
sandino Avatar answered Nov 01 '22 10:11

sandino


As pointed out by @Felix King

Since the image is not an element in the document, it does not trigger events and you cannot bind a handler to it. You have to use a workaround.

Here is a possible work-around (in jquery, but could just as easily be POJS).

CSS

.wrapper {
    padding: 1px;
    display: inline-block;
    border: 2px LightGray inset;
}
.wrapperFocus {
    border: 2px DarkGray inset;
}
.textInput {
    padding: 0;
    border:none;
    outline: none;
    height: 20px;
    width: 150px;
}
.cross {
    float: right;
    height: 20px;
    width: 20px;
    background-image:url('http://s20.postimg.org/6125okgwt/rough_Close.png');
    background-repeat:no-repeat;
    background-position: center;
    background-size:90%;
    cursor: pointer;
}

HTML

<fieldset class="wrapper">
    <input type="text" class="textInput" /><span class="cross"></span>
</fieldset>
<fieldset class="wrapper">
    <input type="text" class="textInput" /><span class="cross"></span>
</fieldset>
<fieldset class="wrapper">
    <input type="text" class="textInput" /><span class="cross"></span>
</fieldset>
<hr>
<button>submit</button>

Javascript

$(document).on("click", "span.cross", function () {
    $(this).prev().val("");
}).on("focus", "input.textInput", function () {
    $(this).parent().addClass("wrapperFocus");
}).on("blur", "input.textInput", function () {
    $(this).parent().removeClass("wrapperFocus");
});

On jsfiddle

Or if you want to do it without the additional CSS and HTML, then this should be cross-browser (POJS as you already have a jquery example).

CSS

.cross {
    height: 20px;
    width: 150px;
    background-image:url('http://s20.postimg.org/6125okgwt/rough_Close.png');
    background-repeat:no-repeat;
    background-position:right center;
    background-size:10% 90%;
    z-index: -1;
    padding-right: 6%;
}

HTML

<input type="text" class="cross" />
<input type="text" class="cross" />
<input type="text" class="cross" />
<hr>
<button>submit</button>

Javascript

function normalise(e) {
    e = e || window.event;
    e.target = e.target || e.srcElement;

    return e;
}

var getWidth = (function () {
    var func;

    if (document.defaultView.getComputedStyle) {
        func = document.defaultView.getComputedStyle;
    } else if (target.currentStyle) {
        func = function (t) {
            return t.currentStyle;
        }
    } else {
        func = function () {
            throw new Error("unable to get a computed width");
        }
    }

    return function (target) {
        return parseInt(func(target).width);
    };
}());

function isInputCross(target) {
    return target.tagName.toUpperCase() === "INPUT" && target.className.match(/(?:^|\s)cross(?!\S)/);
}

function isOverImage(e) {
    return (e.clientX - e.target.offsetLeft) > getWidth(e.target);
}

function clearCrossInput(e) {
    e = normalise(e);
    if (isInputCross(e.target) && isOverImage(e)) {
        e.target.value = "";
    }
}

document.body.onclick = (function () {
    var prevFunc = document.body.onclick;

    if ({}.toString.call(prevFunc) === "[object Function]") {
        return function (ev) {
            prevFunc(ev);
            clearCrossInput(ev);
        };
    }

    return clearCrossInput;
}());

On jsfiddle

But if you want the cursor to change when hovered over the position then you will need to do some extra work. Like this (you could just as easily do this with jquery too).

Javascript

function hoverCrossInput(e) {
    e = normalise(e);
    if (isInputCross(e.target)) {
        if (isOverImage(e)) {
            e.target.style.cursor = "pointer";
            return;
        }
    }

    e.target.style.cursor = "";
}

document.body.onmousemove = (function () {
    var prevFunc = document.body.onmousemove;

    if ({}.toString.call(prevFunc) === "[object Function]") {
        return function (ev) {
            prevFunc(ev);
            hoverCrossInput(ev);
        };
    }

    return hoverCrossInput;
}());

On jsfiddle

like image 36
Xotic750 Avatar answered Nov 01 '22 11:11

Xotic750


I do something similar by using an <input type="text" ... > immediately followed by an <input type="button">

The button is given a background image and positioned-relative to move it into the text field; essentially...

position: relative;
top: 4px;
right: 1.6em;
height: 16px;
width: 16px;
border: none;

Then I just add a dead-plain click handler to the button, no computations necessary.

The height x width would depend on your image, and you would tweak the top and right to fit your situation.

This fiddle shows it pared down to the bare essentials.

like image 1
Stephen P Avatar answered Nov 01 '22 12:11

Stephen P