Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/458.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使文本成为“文本”;“更多”;可选的_Javascript_Jquery_Html_Css - Fatal编程技术网

Javascript 使文本成为“文本”;“更多”;可选的

Javascript 使文本成为“文本”;“更多”;可选的,javascript,jquery,html,css,Javascript,Jquery,Html,Css,我在标记中有文本: <p>Hello world... and goodbye mind A B!</p> 你好,世界。。。再见,注意A B 如何增加可选择文本的区域?我知道我可以增加字体大小,这会增加可选择的区域,但是有更好的方法吗 澄清这个问题。例如,在移动屏幕上,我发现很难突出显示像I这样的一个字母的单词,但如果命中检测的区域更广,那么选择它就会容易得多 怎么做?令人费解的谜题 赏金信息 正在寻找工作的跨浏览器解决方案。在发布答案之前,请仔细阅读问题和评论,以避

我在
标记中有文本:

<p>Hello world... and goodbye mind A B!</p>
你好,世界。。。再见,注意A B

如何增加可选择文本的区域?我知道我可以增加
字体大小
,这会增加可选择的区域,但是有更好的方法吗

澄清这个问题。例如,在移动屏幕上,我发现很难突出显示像
I
这样的一个字母的单词,但如果命中检测的区域更广,那么选择它就会容易得多

怎么做?令人费解的谜题

赏金信息 正在寻找工作的跨浏览器解决方案。在发布答案之前,请仔细阅读问题和评论,以避免混淆。User@mmm发布了一个非常接近的问题,但在他的方法中,
标记具有更广泛的命中检测(完美!),它会在单击时自动选择。我需要用户与
标记交互,就像我们与普通基于文本的
标记交互一样。。。但是,使用更大的命中检测器

编辑 进一步澄清。例如,对这个问题的评论选择区域非常大:

你可以在下面找到这个评论。将光标悬停在其上,直到光标变为
cursor:text
。这是默认的选择区域

但我的目标是将其扩展到更大的领域,如下所示:


我假设您有一个文本主体,在该文本主体内是对最终用户相当重要或相关的信息,您希望他们能够轻松地突出显示和复制信息

如果没有找到其他解决方案,这将被视为最后的选择

<p class="surroundingText"> BLAH BLAH BLAH  <span class="importantText"> This is the information you would like users to be able to highlight </span> BLAH BLAH BLAH BLAH ETC ETC ETC </p>

因此,最终结果是只能选择span标记之间的文本

效果被夸大了,但是:


p{
字母间距:2px;
线高:3em;
字距:1.5em;
垂直对齐:中间对齐;
}
这是一条线

这是一条线

这是一条线

这是一条线

这是一条线

这是一条线

这是一条线


根据我的测试,它可以在iphone以及ff和chrome上运行-如果有人可以在android上测试,我将非常感谢反馈

边界显然是可以消除的

此代码使用此答案中的代码(SelectText()函数的一部分):

代码:

函数extendSelection(){

var extendBy=arguments.length您可以按照某人的建议在段落周围添加填充,但也可以使用相同值的负边距来防止影响布局

这里是(双击或长按灰色区域内的任何位置都应选择文本)

相关代码:

HTML:


注意:我没有测试两个区域重叠的情况,但我假设堆叠顺序较高的区域获胜。

一种方法是增加
元素的
行高。
在移动设备上,可以更好地选择文本片段,因为行间距较大。如果在
中定义值>em
,间距始终与
字体大小相关

第二种方法是将文本元素的
字间距
增加到可接受的水平。我建议最大值为
0.2em

HTML:


如果这两种方法不够好,您当然可以为每个单词创建一个绝对定位元素,该元素覆盖文本元素,但不透明度为0。此元素内部的文本应与后面的文本相等,但字体较大。此方法有几个缺点:您需要计算f每个单词,复制文本内容。这是一个相当大的计算,只需要一点点效果。

如果您可以进行一些额外的点击,这里有一种方法可以考虑

  • 用户需要首先单击要选择的文本周围的某个位置
  • 根据点击位置,我们找出被点击的单词
  • 现在,我们使用上一个单词、当前(单击)单词和下一个单词,并在H1内的弹出窗口中显示它(或显示更大区域以使其更具可选择性的任何其他方式)
  • 当用户从此弹出窗口中选择文本时,我们关闭弹出窗口并在用户单击的原始元素中选择适当的文本
  • 以下是我的尝试:

    $('.expandable')。单击(函数(e){
    var clicked=findClickedWord(e.target.childNodes[0],e.clientX,e.clientY);
    如果(单击){
    变量$expanded=$('')
    .appendTo('正文')
    .addClass('扩展')
    .css({
    位置:“绝对”,
    左:单击[3]。左,
    顶部:单击[3]。顶部,
    //宽度:“100px”,
    //高度:“100px”
    })
    .append($(“”).文本(单击[0]);
    var data={originalElem:e.target.childNodes[0],index:clicked[1],start:clicked[2]};
    $expanded.data(“parentData”,数据);
    $expanded.on('mouseup',selectionChanged);
    $expanded.on('touchend touchcancel',selectionChanged);
    //警报(JSON.stringify(单击));
    }
    });
    功能选择已更改(e){
    试一试{
    var$扩展=$(e.target);
    var data=$expanded.parents(“.expanded”).data(“parentData”);
    var selection=window.getSelection();
    if(selection.rangeCount){
    var range1=selection.getRangeAt(0);
    //警报(范围1.startOffset+“:”+范围1.endOffset);
    var range2=document.createRange();
    var originalOffset=data.index>0?data.start[data.index-1]:data.start[0];
    range2.setStart(data.originalElem、originalOffset+range1.startOffset);
    
    .surroundingText {
    
      -webkit-user-select: none;  /* Chrome all / Safari all */
      -moz-user-select: none;     /* Firefox all */
      -ms-user-select: none;      /* IE 10+ */
      user-select: none;         
    }
    
    .importantText {
    
            -webkit-user-select: all;  /* Chrome all / Safari all */
          -moz-user-select: all;     /* Firefox all */
          -ms-user-select: all;      /* IE 10+ */
          user-select: all;
        }
    
    function extendSelection() {
        var extendBy = arguments.length <= 0 || arguments[0] === undefined ? 15 : arguments[0];
    
        var extended = document.getElementsByClassName('extendedSelection');
        [].slice.call(extended).forEach(function (v) {
            var bounds = v.getBoundingClientRect();
            var x = bounds.left;
            var r = textWidth(v.innerHTML, ''+ css(v, 'font-weight') +' ' + css(v, 'font-size') + ' ' + css(v, 'font-family') );
            var y = bounds.top;
            var w = bounds.width;
            var h = bounds.height;
            var element = document.createElement('div');
            element.style.position = 'absolute';
            element.style.height = h + extendBy + 'px';
            element.style.width = r + extendBy + 'px';
            element.style.left = x - extendBy / 2 + 'px';
            element.style.top = y - extendBy / 2 + 'px';
            element.style.border = '1px dotted black';
            document.body.appendChild(element);
            element.addEventListener('click', function (e) {
                SelectText(v);
            });
            element.addEventListener('touchend', function (e) {
                SelectText(v);
            });
        });
    }
    
    function css(element, property) {
        return window.getComputedStyle(element, null).getPropertyValue(property);
    }
    
    function textWidth(text, font) {
        var el = textWidth.canvas || (textWidth.canvas = document.createElement("canvas"));
        var draw = el.getContext("2d");
        draw.font = font;
        var m = draw.measureText(text);
        return m.width;
    };
    
    function SelectText(element) {
        var doc = document,
            text = element,
            range,
            selection;
        if (doc.body.createTextRange) {
            range = document.body.createTextRange();
            range.moveToElementText(text);
            range.select();
        } else if (window.getSelection) {
            selection = window.getSelection();
            range = document.createRange();
            range.selectNodeContents(text);
            selection.removeAllRanges();
            selection.addRange(range);
            selection.setSelectionRange(0, element.value.length)
        }
    }
    
    extendSelection();
    
    <p>normal paragraph</p>
    <hr />
    <p class="fat-fingers">fat fingers paragraph</p>
    
    p {
        //resetting default browser styles for brevity
        //otherwise adjust negative margin value so it's == default margin - padding
        margin: 0;
    }
    
    .fat-fingers {
        padding: 10px;
        margin: -10px;
    }
    
    <p class="extendedSelection">Extended Selection</p>
    
    p.extendedSelection {
       line-height: 2em;
       word-spacing: 0.2em;
    }
    
    $('.expandable').click(function(e){
        var clicked = findClickedWord(e.target.childNodes[0], e.clientX, e.clientY);
      if(clicked){
        var $expanded = $('<span>')
                        .appendTo('body')
                        .addClass('expanded')
                        .css({
                          position: "absolute",
                          left: clicked[3].left,
                          top: clicked[3].top,
                          //width: "100px",
                          //height: "100px"
                        })
                        .append($("<h1>").text(clicked[0]));
    
            var data = {originalElem: e.target.childNodes[0], index: clicked[1], starts: clicked[2]};
    
        $expanded.data("parentData", data);
        $expanded.on('mouseup', selectionChanged);
        $expanded.on('touchend touchcancel', selectionChanged);
    
        //alert(JSON.stringify(clicked));
      }
    });
    
    function selectionChanged(e){
    try {
        var $expanded = $(e.target);
      var data = $expanded.parents(".expanded").data("parentData");
      var selection = window.getSelection();
      if(selection.rangeCount){
        var range1 = selection.getRangeAt(0);
        //alert(range1.startOffset + ":" + range1.endOffset);
    
        var range2 = document.createRange();
        var originalOffset = data.index>0? data.starts[data.index-1] : data.starts[0];
        range2.setStart(data.originalElem, originalOffset + range1.startOffset);
        range2.setEnd(data.originalElem, originalOffset + range1.endOffset);
        selection.removeAllRanges();
          selection.addRange(range2);
      }
     } catch(err){
     alert(err);
     }
      $expanded.parents(".expanded").remove();
    }
    
    function findClickedWord(parentElt, x, y) {
        if (parentElt.nodeName !== '#text') {
            console.log('didn\'t click on text node');
            return null;
        }
        var range = document.createRange();
        var words = parentElt.textContent.split(' ');
        var start = 0;
        var end = 0;
        var starts=[];
        var ends=[];
        for (var i = 0; i < words.length; i++) {
            var word = words[i];
            end = start+word.length;
            starts.push(start);
            ends.push(end);
    
            range.setStart(parentElt, start);
            range.setEnd(parentElt, end);
            // not getBoundingClientRect as word could wrap
            var rects = range.getClientRects();
            var clickedRect = isClickInRects(rects);
    
            if (clickedRect) {
                    var str = (i==0)? word : words[i-1] + " " + word;
                if(i!=words.length-1) str += " " + words[i+1];
                return [str, i, starts, clickedRect];
            }
            start = end + 1;
        }
    
        function isClickInRects(rects) {
            for (var i = 0; i < rects.length; ++i) {
                var r = rects[i]
                if (r.left<x && r.right>x && r.top<y && r.bottom>y)
                {            
                    return r;
                }
            }
            return false;
        }
        return null;
    }