使用Javascript选择文本并计算其距离顶部的距离?

8

使用JavaScript可以在网页上查找给定的文本字符串,并计算其距离页面顶部的距离(以像素为单位)。如果可以,请提供一个示例。

3个回答

4

更新:更加健壮。

一个有趣互动的演示: 在这里查看它的运行效果,点击这里

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html>
<head>
    <title>Word Finder Fun</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <style type="text/css">
        body {
            font-size:          16px;
            font-weight:        normal;
            font-family:        "Trebuchet MS", Helvetica, Tahoma, Arial, sans-serif;
            padding:            10px 5%;
            line-height:        1.5;
            min-width:          680px;
        }
        table {
            border:             1px solid black;
            border-collapse:    collapse;
            margin:             1em;
        }
        th, td {
            margin:             0px;
            padding:            0.5ex;
            border:             1px solid black;
        }
        td {
            min-width:          8em;
        }
        th {
            font-weight:        bold;
            background:         wheat;
            text-align:         right;
        }
        caption {
            margin:             0;
            font-size:          1.2em;
            font-style:         italic;
            text-align:         left;
            caption-side:       top;
        }
        form {
            float:              left;
            margin:             2.5em 5em;
        }
        label {
            font-weight:        bold;
            background:         yellow;
        }
        input {
            padding:            0.5ex;
        }
        .FoundText {
            background:         red;
            margin:             0;
            padding:            0;
        }
    </style>


    <!-- jQuery is required. -->
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>

    <script type="text/javascript">
        function jQueryMain ()
        {
            $("#idSearchStr").focus ();             //-- User convenience, set focus to search input.

            $("button").click (SearchPageText);     //-- On button click, search away.

            $("#idForm1").submit (SearchPageText);  //-- Intercept form submit (enter key too).
        }


        function SearchPageText (zEvent)
        {
            /*--- Kill any old spans (otherwise they might interfere with new search).
            */
            var NastyOldSpans        = $("span.FoundText");

            NastyOldSpans.each (function () {var X = $(this);  X.before (X[0].innerHTML); });
            NastyOldSpans.remove();


            var SearchStr           = $("#idSearchStr")[0].value;

            //--- Ignore empty or trivial searches.
            if (!SearchStr  ||  /^\s+$/.test (SearchStr) )
                return false;

            var zAllnodes           = $("body *");
            var iNumNodes           = zAllnodes.length;
            var zRegEx              = new RegExp ('(' + SearchStr + ')', 'ig');
            var bFoundOne           = false;


            /*--- Look for string and wrap it in a span if found.
            */
            for (J=0;  J < iNumNodes;  J++)
            {
                /*-- Get node text in a way that supports both IE and Decent browsers.
                    We do NOT want to use innerHTML here.  We do not want to mess
                    with matches in HTML tags, for now.
                */
                var zNode           = $(zAllnodes[J]);
                var sNodeTxt        = (zAllnodes[J]).innerText  ||  (zAllnodes[J]).textContent;


                if (zRegEx.test (sNodeTxt) )
                {
                    var OldStr      = (zAllnodes[J]).innerHTML;
                    var NewStr      = OldStr.replace (zRegEx, '<span class="FoundText">$1<\/span>');

                    //--- We want only "leaf" nodes (contain no html).  So, if we detect a tag, skip.
                    if (/[<>]/.test (OldStr) )
                        continue;

                    //--- SET with innerHTML, so that new span will take.
                    (zAllnodes[J]).innerHTML    = NewStr;

                    bFoundOne       = true;
                }
            }


            /*--- Grab the string's particulars and update the status table.
            */
            var iNumMatchChars      = 0;
            var iTop                = 'na';
            var iLeft               = 'na';

            if (bFoundOne)
            {
                iNumMatchChars      = SearchStr.length;
                var aStrPosition    = $("span.FoundText:first").offset ();
                iTop                = aStrPosition.top;
                iLeft               = aStrPosition.left;
            }

            var zStatusTable        = $("#idStatTable")[0];
            zStatusTable.rows[0].cells[1].innerHTML = iTop;
            zStatusTable.rows[1].cells[1].innerHTML = iLeft;
            zStatusTable.rows[2].cells[1].innerHTML = iNumMatchChars;

            return false;   //-- Stop form submit
        }


        $(document).ready (jQueryMain);
    </script>
</head>

<body>
    <form id="idForm1" method="post" action="">
    <p>
        <label for="idSearchStr">Enter Search String: </label><input type="text" id="idSearchStr"><br>
        <button type="button">Find in page</button>
    </p>
    </form>

    <table id="idStatTable" summary="Search match results">
        <caption>First Match:</caption>
        <tr>
            <th>Top:</th>
            <td></td>
        </tr>
        <tr>
            <th>Left:</th>
            <td></td>
        </tr>
        <tr>
            <th>Char cnt:</th>
            <td></td>
        </tr>
    </table>

    <p>
        I never spend much time in school but I taught ladies plenty. It's true I hire my body out
        for pay, hey hey. I've gotten burned over Cheryl Tiegs, blown up for Raquel Welch. But when
        I end up in the hay it's only hay, hey hey. I might jump an open drawbridge, or Tarzan from
        a vine. 'Cause I'm the unknown stuntman that makes Eastwood look so fine.
    </p>
    <p>
        Hey there where ya goin', not exactly knowin', who says you have to call just one place
        home. He's goin' everywhere, B.J. McKay and his best friend Bear. He just keeps on movin',
        ladies keep improvin', every day is better than the last. New dreams and better scenes, and
        best of all I don't pay property tax. Rollin' down to Dallas, who's providin' my palace, off
        to New Orleans or who knows where. Places new and ladies, too, I'm B.J. McKay and this is my
        best friend Bear.
    </p>
    <p>
        Top Cat! The most effectual Top Cat! Who's intellectual close friends get to call him T.C.,
        providing it's with dignity. Top Cat! The indisputable leader of the gang. He's the boss,
        he's a pip, he's the championship. He's the most tip top, Top Cat.
    </p>
    <p>
        This is my boss, Jonathan Hart, a self-made millionaire, he's quite a guy. This is Mrs H.,
        she's gorgeous, she's one lady who knows how to take care of herself. By the way, my name is
        Max. I take care of both of them, which ain't easy, 'cause when they met it was MURDER!
    </p>
    <p>
        Mutley, you snickering, floppy eared hound. When courage is needed, you're never around.
        Those medals you wear on your moth-eaten chest should be there for bungling at which you are
        best. So, stop that pigeon, stop that pigeon, stop that pigeon, stop that pigeon, stop that
        pigeon, stop that pigeon, stop that pigeon. Howwww! Nab him, jab him, tab him, grab him,
        stop that pigeon now.
    </p>
</body>
</html>

这个演示非常不错。你提供了一个整洁的例子,让我感到受宠若惊。我打算在一个基本的HTML页面上进行测试。 - user379588
@subwayxpress:谢谢。请注意,我刚刚进行了微调,以确保不匹配HTML标签。 - Brock Adams

1
它会在整个页面主体中搜索字符串,为每个元素添加一个“found”类,并提示其坐标。
不幸的是,我没有看到另一篇文章,但这篇文章稍微短一些。
$(document).ready(function() {
    findText("commodo");
});
function findText(text) {
    var $matchedEl = $('body:contains(' + text + ')');
    var replacedText;
    var re = new RegExp(text, 'ig');
    $matchedEl.each(function() {
        replacedText = $(this).html().replace(re, '<span class="found">' + text + '</span>');
        $(this).html(replacedText);
    });
    $("span.found").each(function() {
        var offset = $(this).offset();
        alert( "top: " + offset.top + "\n left: " + offset.left);
    });
}

还有一些用于搜索的lipsum文本

<div id="wrapper">
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum tincidunt cursus tortor, ut mollis nulla commodo non. Quisque libero mauris, ullamcorper a porttitor nec, blandit eu sem. Vestibulum ac libero mauris, in tincidunt sem. Sed aliquet porta neque ut scelerisque. Aliquam nec aliquam ligula. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse potenti. Duis ut molestie ante. </p>
    <p>Vestibulum ac odio id tortor interdum pharetra sit amet at nunc. Praesent pellentesque justo non massa vulputate vitae consectetur augue venenatis. Cras semper nulla tincidunt dolor sagittis sodales. Aenean malesuada eleifend enim nec accumsan. Morbi ut neque metus. Aenean erat ligula, sagittis vel scelerisque et, placerat vel diam. Nunc hendrerit quam at turpis ultrices imperdiet. Suspendisse sit amet mi sed enim ultrices consectetur. Quisque eu lobortis massa. </p>
    <p>Nulla cursus, metus ut consequat adipiscing, elit nisi semper mi, at commodo orci sapien ullamcorper lorem. Quisque scelerisque felis ut felis ultrices pellentesque. </p>
</div>

谢谢你提供这份代码。然而,在我用Firefox测试时,它在另一个页面上的位置偏移了60到80像素左右。 - user379588
我假设您是从左上角坐标开始测量的。我可能会尝试一下看看发生了什么。或者您已经找到了解决方案吗? - Marko

0

这是一个有趣的想法。无论如何,我在 mootools 中构建了一个迷你类,它确实可以工作。我还没有在更复杂的页面布局中测试过它,但前提是查找所有具有可能有用的 innerHTML 元素,扫描文本以查找匹配项,如果找到,则克隆父元素,同时用 span 替换文本,然后从顶部/左侧等检索 span 的偏移量。这不会修改现有元素的 HTML,并且可扩展。

结果在这里:http://www.jsfiddle.net/dimitar/eBPFb/

源代码如下:

var getTextOffset = new Class({
    Implements: [Options],
    options: {
        selector: "*", // all elements
        filter: "innerHTML", // only those that have this property are worth lookign at
        skip: ["link", "style", "script","head","html","meta","input","textarea","select","body"] // useless tags we don't care about
    },
    initialize: function(text, options) {
        this.setOptions(options);
        if (!text) return; // nothing to do.

        this.elements = document.getElements(this.options.selector).filter(function(el) {
            return this.options.filter in el && !this.options.skip.contains(el.get("tag"));
        }, this);

        if (!this.elements.length)
            return;

        return this.findText(text);
    },
    findText: function(text) {
        var coords = false;
        this.elements.some(function(el) {
            var eltext = el.get("html");
            if (eltext.contains(text)) {
                var c = el.getCoordinates();
                var clone = new Element("div", {
                    "class": "clone",
                    styles: c,
                    html: eltext.replace(text, "<span id='posText'>"+text+"</span>")
                }).inject(document.body, "top");
                coords = document.id("posText").getCoordinates();
                clone.destroy();
            }
        });

        return coords;
    }
});


var pleistoscene = new getTextOffset("Pleistocene");

if (pleistoscene) // found text so highlight it
new Element("div", {
    styles: $merge(pleistoscene, {
        position: "absolute",
        background: "yellow"
    }),
    opacity: .7,
    title: pleistoscene.top + "px top"
}).inject(document.body); // mouseover the yelow element to see offset (pleitoscene.top)

希望这个有意义 - 它很粗糙,但应该能给你一些想法。如果您通过鼠标使用选择进行此操作,则比搜索更容易。还要记住,这将搜索HTML,因此使用标记为a very <a href=''>good</a> yeara very good year进行查找将失败(您可以查询文本属性而不是标记)。

它使用了array.some(),它会在第一个匹配后停止循环。如果您想查找多个实例,则需要重构。

祝好运


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接