检测单击元素的内部文本而不将文本包装在第二个元素中

时间:2015-02-04 23:08:13

标签: javascript jquery html

我有一个Div,它使用CSS大到我页面的一半:

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

我正在尝试编写一个javascript或jquery代码来检测单击文本而不是元素的其余部分。有没有办法做到这一点?

5 个答案:

答案 0 :(得分:8)

由于我们无法直接在textNodes上监听事件,因此我们必须采取更具创造性的途径来解决问题。我们可以做的一件事是查看click事件的坐标,看看它是否与textNode重叠。

首先,我们需要一个小辅助方法来帮助我们跟踪一组约束中是否存在一组坐标。这将使我们更容易随意确定一组x / y值是否 一组维度:

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

这是相当基本的。 xy值将为数字,rect引用将是一个对象,至少有四个属性,其中的绝对像素值代表矩形的四个角。

接下来,我们需要一个循环遍历textNodes的所有childNode的函数,并确定是否在其中一个上面发生了click事件:

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;
}

完成所有这些后,我们现在可以快速确定textNode是否直接位于所单击的区域下方,并获取该节点的值:

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

请注意,初始条件if ( event.srcElement ) === this允许我们忽略源自嵌套元素的点击事件,例如图像或span标记。在textNodes上发生的点击会将父元素显示为srcElement,因此这些是我们唯一关注的内容。

您可以在此处查看结果:http://jsfiddle.net/jonathansampson/ug3w2xLc/

答案 1 :(得分:1)

编辑 - 不添加包装元素的解决方案
没有包裹元素这样做是非常麻烦的。我设法让它工作,但是仅适用于垂直和水平居中的一个衬垫

要查看与此相关的HTML和CSS,请参阅 jsFiddle:http://jsfiddle.net/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!');
});

此外,这个代码可以进行优化,因为同样的计算是多次完成的,但我认为将计算结果更好地说明了发生了什么。

添加包装元素的解决方案

如果在文本周围放置一个span,则可以向span添加onClick事件处理程序。

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

jQuery代码

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

答案 2 :(得分:1)

快速获胜将是

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

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

答案 3 :(得分:1)

让我们改变内容 - 我将点击lala:

<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');
    });

请参阅此处的工作示例:http://jsfiddle.net/atrifan/5qc27f9c/

P.S:抱歉这些事情和事情我有点累了。

你能做到这一点,这是你在找什么?

代码的作用:   它只生成div中的文本,虽然div也可以有其他div,只使得没有HTML容器的文本像div一样跨越ap或a类似的东西,并改变它在一个范围内添加它并使它成为可点击。

答案 4 :(得分:-4)

如果您想直接浏览HTML,可以使用

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

然后在JS中简单地应用该函数:

function myFunction(){
    //...
}

编辑:抱歉,如果您希望文本受到影响,请在文本周围加<p><span>

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