我怎么可能完成这个Javascript突出显示技术?

时间:2012-03-30 09:01:57

标签: javascript uiwebview

<div id="content" contenteditable="false" style="margin:-0.2em 1em; font-family:New Century Schoolbook; font-size:20; color:black; line-height:170%">
        <span style="margin-left:1.7em">Jenny was cute!</span>
        <span style="margin-left:1.7em">She looked happy with the instructor.</span>
        <span style="margin-left:1.7em">Can we meet her again?</span><br>
        <span style="margin-left:18em">Sakura</span>
    </div>

这是我创建的一些HTML,以满足客户的需求。每个边缘之间的边距是这样我可以在每个句子之间插入一个单独的图像(当图像在HTML中时,用户选择变得非常奇怪)。用户需要能够为iBook应用程序中的部分选择,突出显示和添加备忘录。但是,与iBook应用程序不同,它需要使用格式化文本。因此,它需要在同一视图中可选择,可编辑,并支持粗体,斜体和下划线。这是我提出的Javascript(HTML和Javascript的结果不符合标准,但我不在乎,因为这不会是一个网页而且我厌倦了):

function addHighlight(className, id)
{
    var html = '';
    var sel = window.getSelection().getRangeAt(0);
    var container = document.createElement('JimSpan');
    container.id = id;
    container.className = className;
    container.appendChild(sel.extractContents());

    var arrElements = document.getElementsByTagName('span');
    for(i = 0; i < arrElements.length-1; i++)
    {
        if(!arrElements[i].innerText.match(/\S/))
        {
            arrElements[i].parentNode.removeChild(arrElements[i]);
        }
    }

    sel.insertNode(container); 

    return 'js: ADDED HIGHLIGHT';
}

我必须使用“JimSpan”而不是“Span”的原因是因为用户还需要能够在页面未显示时删除注释,这意味着我必须使用正则表达式手动编辑它。由于有很多跨度,我不知道我的实际结束时间。这适用于一个例外。如果用户选择一个元素的全部和另一个元素的一部分,结果是:

<div id="content" contenteditable="false" style="margin:-0.2em 1em; font-family:New Century Schoolbook; font-size:20; color:black; line-height:170%">
    <jimspan id="memo0" class="pinkHilite"><span style="margin-left:1.7em">Jenny was cute!</span>
    <span style="margin-left:1.7em">She</span></jimspan><span style="margin-left:1.7em"> looked happy with the instructor.</span>
    <span style="margin-left:1.7em">Can we meet her again?</span><br>
    <span style="margin-left:18em">Sakura</span>
</div>

正如你在中间看到的那样,分裂导致句子她看起来很高兴,导师被分成两个跨度,每个都有左边缘,我留下了一个巨大的在句子中间的差距。我会接受以下任何一种情况:

1)一种方法让我产生以下(技术上无效,但显示正常)HTML(我不介意用正则表达式编辑当前范围,如果有办法的话):

<div id="content" contenteditable="false" style="margin:-0.2em 1em; font-family:New Century Schoolbook; font-size:20; color:black; line-height:170%">
    <jimspan id="memo0" id="pinkHilite"><span style="margin-left:1.7em">Jenny was cute!</span>
    <span style="margin-left:1.7em">She</jimspan> looked happy with the instructor.</span>
    <span style="margin-left:1.7em">Can we meet her again?</span><br>
    <span style="margin-left:18em">Sakura</span>
</div>

2)强制用户选择仅包含1个跨度内部的方法(选择必须更改,而不仅仅是受影响的高亮区域)。

请帮助我保持理智 - _ _-;

1 个答案:

答案 0 :(得分:1)

选项2是最简单的解决方案,并且可以使用RangeSelection对象完全实现(排除IE&lt; 9,这对于UIWebView无关紧要但可以对某人有用想在浏览器中做类似的事情)。以下将选择限制为包含用户开始选择的点的元素(注意:为了便于说明,它仅适用于基于鼠标的选择):

现场演示:http://jsfiddle.net/U4smu/

代码:

function isOrIsDescendantOf(node, ancestor) {
    while (node) {
        if (node === ancestor) {
            return true;
        }
        node = node.parentNode;
    }
}

function selectionIsBackwards(sel) {
    var range = document.createRange();
    range.setStart(sel.anchorNode, sel.anchorOffset);
    range.setEnd(sel.focusNode, sel.focusOffset);
    var backwards = range.collapsed;
    range.detach();
    return backwards;
}    

document.onmouseup = function() {
    var sel = window.getSelection();
    var containerEl = sel.anchorNode;
    if (containerEl ) {
        if (containerEl .nodeType == 3) {
            containerEl = containerEl.parentNode;
        }

        if (!isOrIsDescendantOf(sel.focusNode, containerEl)) {
            var backwards = selectionIsBackwards(sel);
            var range = document.createRange();
            if (backwards) {
                range.setStart(containerEl, 0);
                range.setEnd(sel.anchorNode, sel.anchorOffset);
            } else {
                range.setStart(sel.anchorNode, sel.anchorOffset);
                range.setEnd(containerEl, containerEl.childNodes.length);
            }
            sel.removeAllRanges();
            sel.addRange(range);
        }
    }
};