Как я могу выполнить эту технику подсветки Javascript? - PullRequest
1 голос
/ 30 марта 2012
<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 Ответ

1 голос
/ 30 марта 2012

Вариант 2 - самое простое решение, и его вполне достижимо при использовании объектов Range и Selection (исключая IE <9, что не имеет значения для <code>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);
        }
    }
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...