admin管理员组

文章数量:1312658

I have a Div which is as big as half of my page using CSS:

<div id="bigdiv">
     CLICK ON THIS TEXT
</div>

I am trying to write a javascript or jquery code which detects click on the text and not the rest of the element. Is there a way to do that?

I have a Div which is as big as half of my page using CSS:

<div id="bigdiv">
     CLICK ON THIS TEXT
</div>

I am trying to write a javascript or jquery code which detects click on the text and not the rest of the element. Is there a way to do that?

Share Improve this question asked Feb 4, 2015 at 23:08 user3311522user3311522 1,6683 gold badges20 silver badges34 bronze badges 7
  • 3 I suspect you'll need to wrap it in an span, if you want to capture clicks. Text content doesn't implement the appropriate interface to trigger events. – Sampson Commented Feb 4, 2015 at 23:08
  • @JonathanSampson yeah, I am trying to find a way to do it without adding a second element (for a case specific reason) – user3311522 Commented Feb 4, 2015 at 23:10
  • Is there something he can do in the event handler that detects whether the position of the click is on the text? – Barmar Commented Feb 4, 2015 at 23:11
  • Is this the only text in the element? Also, how is the text aligned? centered horizontally, vertically, both? – Thijs Riezebeek Commented Feb 4, 2015 at 23:15
  • @ThijsRiezebeek only text in it. styling dynamic. you can choose. – user3311522 Commented Feb 4, 2015 at 23:17
 |  Show 2 more ments

5 Answers 5

Reset to default 9

Since we cannot listen for events directly on the textNodes themselves, we have to take a more creative path to solving the problem. One thing we can do is look at the coordinates of the click event, and see if it overlaps with a textNode.

First, we'll need a small helper method to help us track whether a set of coordinates exists within a set of constraints. This will make it easier for us to arbitrarily determine if a set of x/y values are within the a set of dimensions:

function isInside ( x, y, rect ) {
    return x >= rect.left  && y >= rect.top
        && x <= rect.right && y <= rect.bottom;
}

This is fairly basic. The x and y values will be numbers, and the rect reference will be an object with at least four properties holding the absolute pixel values representing four corners of a rectangle.

Next, we need a function for cycling through all childNodes that are textNodes, and determining whether a click event took place above one of them:

function textNodeFromPoint( element, x, y ) {
    var node, nodes = element.childNodes, range = document.createRange();
    for ( var i = 0; node = nodes[i], i < nodes.length; i++ ) {
        if ( node.nodeType !== 3 ) continue;
        range.selectNodeContents(node);
        if ( isInside( x, y, range.getBoundingClientRect() ) ) {
            return node;
        }
    }
    return false;
}

With all of this in place, we can now quickly determine if a textNode was directly below the clicked region, and get the value of that node:

element.addEventListener( "click", function ( event ) {
    if ( event.srcElement === this ) {
        var clickedNode = textNodeFromPoint( this, event.clientX, event.clientY );
        if ( clickedNode ) {
            alert( "You clicked: " + clickedNode.nodeValue );
        }
    }
});

Note that the initial condition if ( event.srcElement ) === this allows us to ignore click events originating from nested elements, such as an image or a span tag. Clicks that happen over textNodes will show the parent element as the srcElement, and as such those are the only ones we're concerned with.

You can see the results here: http://jsfiddle/jonathansampson/ug3w2xLc/

Quick win would be to have

<div id="bigdiv">
    <span id="text">TEXT HERE</span>
</div>

Script:
$('#text').on('click', function() {
   .....
});

Let's alter the content dinamically - I will make the clicking on lala available:

<div id="gig">
<div id="smthing">one</div>lala
<div id="else"></div>
</div>

Script:

var htmlText = $('#gig').text(); //the big divs text


    var children = $('#gig').children(); //get dom elements so they can be ignored later

    $.each(children, function (index, child) {
        var txt = $(child).text().trim(); 
        if (txt != '') { //if a child has text in him
            htmlText = htmlText.replace(txt, 'xxx'); //replace it in the big text with xxx
        }
    });

    htmlText = htmlText.split("xxx"); //split for xxx make it arrat
    var counter = 0; //the part when the text is added
    $.each(htmlText, function (i, el) {
        htmlText[i] = el.trim();

        if (htmlText[i] != "") { //if there is something here than it's my text
            htmlText[i] = '<span id="text">' + htmlText[i] + '</span>'; //replace it with a HTML element personalized
            counter++; //mark that you have replaced the text
        } else { // if there is nothing at this point it means that I have a DOM element here
            htmlText[i] = $(children[i - counter])[0].outerHTML; //add the DOM element
        }
    });

    if (children.length >= htmlText.length) { //you might have the case when not all the HTML children were added back 
        for (var i = htmlText.length - 1; i < children.length; i++) {
            htmlText[i + 1] = $(children[i])[0].outerHTML; //add them
        }
    }

    htmlText = htmlText.join(""); //form a HTML markup from the altered stuff

    $('#gig').html(htmlText); // replace the content of the big div

    $('#text').on('click', function (data) { //add click support
        alert('ok');
    });

See a working example here: http://jsfiddle/atrifan/5qc27f9c/

P.S: sorry for the namings and stuff I am a little bit tired.

Are you able to do this, is this what you are looking for?

What the code does: It's making only the text inside the div although the div could have other divs as well, makes only the text that has no HTML container like a div a span a p an a or something like that and alters it adding it in a span and making it available for clicking.

EDIT - Solution without adding wrapping element
Doing this without a wrapping element is quite a hassle. I managed to get it to work, however this will only work for one liners that are centered vertically AND horizontally.

To see the HTML and CSS that goes along with this, see the jsFiddle: http://jsfiddle/v8jbsu3m/3/

jQuery('#bigDiv').click(function(e) {
    // Get the x and y offest from the window
    margin_top = jQuery(this).offset().top;
    margin_left = jQuery(this).offset().left;

    // Get the dimensions of the element.
    height = jQuery(this).height();
    width = jQuery(this).width();

    // Retrieve the font_size and remove the px addition
    font_size = parseInt(jQuery(this).css('font-size').replace('px', ''));

    // Retrieve the position of the click
    click_x = e.pageX;
    click_y = e.pageY;

    // These variables will be used to validate the end result
    var in_text_y = false;
    var in_text_x = false;

    // Determine the click relative to the clicked element
    relative_x = click_x - margin_left;
    relative_y = click_y - margin_top;

    // Determine whether the y-coordinate of the click was in the text
    if (relative_y >= (parseFloat(height) / 2) - (parseFloat(font_size) / 2) &&
        relative_y <= (parseFloat(height) / 2) + (parseFloat(font_size) / 2))
        in_text_y = true;

    // This piece of code copies the string and places it in a invisible div
    // If this div has the same font styling and no paddings etc... it can
    // be used to get the width of the text
    text = jQuery(this).text();
    text_width = jQuery('#widthTester').html(text).width();

     // Determine whether the x-coordinate of the click was in the text
    if (relative_x >= (parseFloat(width) / 2) - (parseFloat(text_width) / 2) &&
        relative_x < (parseFloat(width) / 2) + (parseFloat(text_width) / 2))
        in_text_x = true;

    // If the x and y coordinates were both in the text then take action
    if (in_text_x && in_text_y)
        alert('You clicked the text!');
});

Also, this code can be optimized, since the same calculcation is done multiple times, but I thought that leaving the calculcations there better illustrated what was going on.

Solution by adding a wrapping element

If you put a span around the text, then you can add an onClick event handler to the span.

<div id="bigdiv">
     <span>CLICK ON THIS TEXT</span>
</div>

jQuery code

jQuery('#bigdiv span').click(function() {
    jquery(this).remove();
});

If you want to go straight through HTML, you can use

<div id="bigdiv" onclick="myFunction();">

and then simply apply the function afterwards in JS:

function myFunction(){
    //...
}

EDIT: sorry, if you want the text to be affected, put in <p> around the text or <span> ie.

<div id="bigdiv">
    <p onclick="myFuncion();"> TEXT </p>
</div>

本文标签: