Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

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.

share|improve this question
1  
Incredibly good and difficult question. – DevlshOne 23 hours ago
Honestly, I think the only way to approach this is the way you don't want to, placing the image OVER the input box (or hanging it off the right edge) and then dynamically dealing with the placement and size of the inputs themselves. – DevlshOne 23 hours ago
the link this way is not working..I do not understand what you are trying to achive – sandino 22 hours ago
@sandino link edited now check – Bingo 22 hours ago
4  
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. – Felix Kling 22 hours ago
show 7 more comments

4 Answers

up vote 5 down vote accepted

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

share|improve this answer
WoW!! it works +1 - will accept it shortly :) after getting few more alternatives – Bingo 21 hours ago
Woowww ...that's what I was talking about...You rock men!! really, I will publish my horrible solution only to note the elegant way you just do it man – sandino 21 hours ago
@Brian Hoover one more ques why it changes the text box width on keypress - I changed it a bit - jsbin.com/ohajoq/1/edit – Bingo 21 hours ago
The CSS was slightly wrong. The class 'none' needs a '.' in front of it. – Brian Hoover 20 hours ago
@BrianHoover how could I miss that (.) even with my 4 eyes, might be the case of working till morning :) – Bingo 10 hours ago
show 1 more comment

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

share|improve this answer
If that's how google resolved this issue I recommend @BrianHoover to work for them...he propused a very simple solution, not css needed, not extra html tags..I am not saying this is not a good solution too – sandino 21 hours ago
Changed it to more javascript based. – Xotic750 14 hours ago
@Xotic750 +1 great you you did it anyhow :) – Bingo 10 hours ago

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

share|improve this answer
haven't implemented your script but it looks promising +1 – Bingo 10 hours ago

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.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.