void DOMSelection::addRange(Range& range)
{
    if (!m_frame)
        return;

    FrameSelection& selection = m_frame->selection();
    if (selection.isNone()) {
        selection.moveTo(&range);
        return;
    }

    RefPtr<Range> normalizedRange = selection.selection().toNormalizedRange();
    if (!normalizedRange)
        return;

    if (range.compareBoundaryPoints(Range::START_TO_START, *normalizedRange, IGNORE_EXCEPTION) == -1) {
        // We don't support discontiguous selection. We don't do anything if r and range don't intersect.
        if (range.compareBoundaryPoints(Range::START_TO_END, *normalizedRange, IGNORE_EXCEPTION) > -1) {
            if (range.compareBoundaryPoints(Range::END_TO_END, *normalizedRange, IGNORE_EXCEPTION) == -1) {
                // The original range and r intersect.
                selection.moveTo(range.startPosition(), normalizedRange->endPosition(), DOWNSTREAM);
            } else {
                // r contains the original range.
                selection.moveTo(&range);
            }
        }
    } else {
        // We don't support discontiguous selection. We don't do anything if r and range don't intersect.
        ExceptionCode ec = 0;
        if (range.compareBoundaryPoints(Range::END_TO_START, *normalizedRange, ec) < 1 && !ec) {
            if (range.compareBoundaryPoints(Range::END_TO_END, *normalizedRange, IGNORE_EXCEPTION) == -1) {
                // The original range contains r.
                selection.moveTo(normalizedRange.get());
            } else {
                // The original range and r intersect.
                selection.moveTo(normalizedRange->startPosition(), range.endPosition(), DOWNSTREAM);
            }
        }
    }
}
Exemple #2
0
JSValue* jsRangePrototypeFunctionCompareBoundaryPoints(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
{
    if (!thisValue->isObject(&JSRange::s_info))
        return throwError(exec, TypeError);
    JSRange* castedThisObj = static_cast<JSRange*>(thisValue);
    Range* imp = static_cast<Range*>(castedThisObj->impl());
    ExceptionCode ec = 0;
    Range::CompareHow how = static_cast<Range::CompareHow>(args[0]->toInt32(exec));
    Range* sourceRange = toRange(args[1]);


    KJS::JSValue* result = jsNumber(exec, imp->compareBoundaryPoints(how, sourceRange, ec));
    setDOMException(exec, ec);
    return result;
}
Exemple #3
0
void DOMSelection::addRange(Range* newRange) {
    DCHECK(newRange);

    if (!isAvailable())
        return;

    if (newRange->ownerDocument() != frame()->document())
        return;

    if (!newRange->isConnected()) {
        addConsoleError("The given range isn't in document.");
        return;
    }

    FrameSelection& selection = frame()->selection();

    if (newRange->ownerDocument() != selection.document()) {
        // "editing/selection/selection-in-iframe-removed-crash.html" goes here.
        return;
    }

    // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
    // needs to be audited.  See http://crbug.com/590369 for more details.
    // In the long term, we should change FrameSelection::setSelection to take a
    // parameter that does not require clean layout, so that modifying selection
    // no longer performs synchronous layout by itself.
    frame()->document()->updateStyleAndLayoutIgnorePendingStylesheets();

    if (selection.isNone()) {
        selection.setSelectedRange(EphemeralRange(newRange), VP_DEFAULT_AFFINITY);
        return;
    }

    Range* originalRange = selection.firstRange();

    if (originalRange->startContainer()->document() !=
            newRange->startContainer()->document()) {
        addConsoleError(
            "The given range does not belong to the current selection's document.");
        return;
    }
    if (originalRange->startContainer()->treeScope() !=
            newRange->startContainer()->treeScope()) {
        addConsoleError(
            "The given range and the current selection belong to two different "
            "document fragments.");
        return;
    }

    if (originalRange->compareBoundaryPoints(Range::kStartToEnd, newRange,
            ASSERT_NO_EXCEPTION) < 0 ||
            newRange->compareBoundaryPoints(Range::kStartToEnd, originalRange,
                                            ASSERT_NO_EXCEPTION) < 0) {
        addConsoleError("Discontiguous selection is not supported.");
        return;
    }

    // FIXME: "Merge the ranges if they intersect" is Blink-specific behavior;
    // other browsers supporting discontiguous selection (obviously) keep each
    // Range added and return it in getRangeAt(). But it's unclear if we can
    // really do the same, since we don't support discontiguous selection. Further
    // discussions at
    // <https://code.google.com/p/chromium/issues/detail?id=353069>.

    Range* start = originalRange->compareBoundaryPoints(
                       Range::kStartToStart, newRange, ASSERT_NO_EXCEPTION) < 0
                   ? originalRange
                   : newRange;
    Range* end = originalRange->compareBoundaryPoints(Range::kEndToEnd, newRange,
                 ASSERT_NO_EXCEPTION) < 0
                 ? newRange
                 : originalRange;
    const EphemeralRange merged =
        EphemeralRange(start->startPosition(), end->endPosition());
    TextAffinity affinity = selection.selection().affinity();
    selection.setSelectedRange(merged, affinity);
}
Exemple #4
0
JSValue* JSRangePrototypeFunction::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
{
    if (!thisObj->inherits(&JSRange::info))
      return throwError(exec, TypeError);

    Range* imp = static_cast<Range*>(static_cast<JSRange*>(thisObj)->impl());

    switch (id) {
    case JSRange::SetStartFuncNum: {
        ExceptionCode ec = 0;
        Node* refNode = toNode(args[0]);
        bool offsetOk;
        int offset = args[1]->toInt32(exec, offsetOk);
        if (!offsetOk) {
            setDOMException(exec, TYPE_MISMATCH_ERR);
            return jsUndefined();
        }

        imp->setStart(refNode, offset, ec);
        setDOMException(exec, ec);
        return jsUndefined();
    }
    case JSRange::SetEndFuncNum: {
        ExceptionCode ec = 0;
        Node* refNode = toNode(args[0]);
        bool offsetOk;
        int offset = args[1]->toInt32(exec, offsetOk);
        if (!offsetOk) {
            setDOMException(exec, TYPE_MISMATCH_ERR);
            return jsUndefined();
        }

        imp->setEnd(refNode, offset, ec);
        setDOMException(exec, ec);
        return jsUndefined();
    }
    case JSRange::SetStartBeforeFuncNum: {
        ExceptionCode ec = 0;
        Node* refNode = toNode(args[0]);

        imp->setStartBefore(refNode, ec);
        setDOMException(exec, ec);
        return jsUndefined();
    }
    case JSRange::SetStartAfterFuncNum: {
        ExceptionCode ec = 0;
        Node* refNode = toNode(args[0]);

        imp->setStartAfter(refNode, ec);
        setDOMException(exec, ec);
        return jsUndefined();
    }
    case JSRange::SetEndBeforeFuncNum: {
        ExceptionCode ec = 0;
        Node* refNode = toNode(args[0]);

        imp->setEndBefore(refNode, ec);
        setDOMException(exec, ec);
        return jsUndefined();
    }
    case JSRange::SetEndAfterFuncNum: {
        ExceptionCode ec = 0;
        Node* refNode = toNode(args[0]);

        imp->setEndAfter(refNode, ec);
        setDOMException(exec, ec);
        return jsUndefined();
    }
    case JSRange::CollapseFuncNum: {
        ExceptionCode ec = 0;
        bool toStart = args[0]->toBoolean(exec);

        imp->collapse(toStart, ec);
        setDOMException(exec, ec);
        return jsUndefined();
    }
    case JSRange::SelectNodeFuncNum: {
        ExceptionCode ec = 0;
        Node* refNode = toNode(args[0]);

        imp->selectNode(refNode, ec);
        setDOMException(exec, ec);
        return jsUndefined();
    }
    case JSRange::SelectNodeContentsFuncNum: {
        ExceptionCode ec = 0;
        Node* refNode = toNode(args[0]);

        imp->selectNodeContents(refNode, ec);
        setDOMException(exec, ec);
        return jsUndefined();
    }
    case JSRange::CompareBoundaryPointsFuncNum: {
        ExceptionCode ec = 0;
        Range::CompareHow how = static_cast<Range::CompareHow>(args[0]->toInt32(exec));
        Range* sourceRange = toRange(args[1]);


        KJS::JSValue* result = jsNumber(imp->compareBoundaryPoints(how, sourceRange, ec));
        setDOMException(exec, ec);
        return result;
    }
    case JSRange::DeleteContentsFuncNum: {
        ExceptionCode ec = 0;

        imp->deleteContents(ec);
        setDOMException(exec, ec);
        return jsUndefined();
    }
    case JSRange::ExtractContentsFuncNum: {
        ExceptionCode ec = 0;


        KJS::JSValue* result = toJS(exec, WTF::getPtr(imp->extractContents(ec)));
        setDOMException(exec, ec);
        return result;
    }
    case JSRange::CloneContentsFuncNum: {
        ExceptionCode ec = 0;


        KJS::JSValue* result = toJS(exec, WTF::getPtr(imp->cloneContents(ec)));
        setDOMException(exec, ec);
        return result;
    }
    case JSRange::InsertNodeFuncNum: {
        ExceptionCode ec = 0;
        Node* newNode = toNode(args[0]);

        imp->insertNode(newNode, ec);
        setDOMException(exec, ec);
        return jsUndefined();
    }
    case JSRange::SurroundContentsFuncNum: {
        ExceptionCode ec = 0;
        Node* newParent = toNode(args[0]);

        imp->surroundContents(newParent, ec);
        setDOMException(exec, ec);
        return jsUndefined();
    }
    case JSRange::CloneRangeFuncNum: {
        ExceptionCode ec = 0;


        KJS::JSValue* result = toJS(exec, WTF::getPtr(imp->cloneRange(ec)));
        setDOMException(exec, ec);
        return result;
    }
    case JSRange::ToStringFuncNum: {
        ExceptionCode ec = 0;


        KJS::JSValue* result = jsString(imp->toString(ec));
        setDOMException(exec, ec);
        return result;
    }
    case JSRange::DetachFuncNum: {
        ExceptionCode ec = 0;

        imp->detach(ec);
        setDOMException(exec, ec);
        return jsUndefined();
    }
    case JSRange::CreateContextualFragmentFuncNum: {
        ExceptionCode ec = 0;
        String html = args[0]->toString(exec);


        KJS::JSValue* result = toJS(exec, WTF::getPtr(imp->createContextualFragment(html, ec)));
        setDOMException(exec, ec);
        return result;
    }
    case JSRange::IntersectsNodeFuncNum: {
        ExceptionCode ec = 0;
        Node* refNode = toNode(args[0]);


        KJS::JSValue* result = jsBoolean(imp->intersectsNode(refNode, ec));
        setDOMException(exec, ec);
        return result;
    }
    case JSRange::CompareNodeFuncNum: {
        ExceptionCode ec = 0;
        Node* refNode = toNode(args[0]);


        KJS::JSValue* result = jsNumber(imp->compareNode(refNode, ec));
        setDOMException(exec, ec);
        return result;
    }
    case JSRange::ComparePointFuncNum: {
        ExceptionCode ec = 0;
        Node* refNode = toNode(args[0]);
        bool offsetOk;
        int offset = args[1]->toInt32(exec, offsetOk);
        if (!offsetOk) {
            setDOMException(exec, TYPE_MISMATCH_ERR);
            return jsUndefined();
        }


        KJS::JSValue* result = jsNumber(imp->comparePoint(refNode, offset, ec));
        setDOMException(exec, ec);
        return result;
    }
    case JSRange::IsPointInRangeFuncNum: {
        ExceptionCode ec = 0;
        Node* refNode = toNode(args[0]);
        bool offsetOk;
        int offset = args[1]->toInt32(exec, offsetOk);
        if (!offsetOk) {
            setDOMException(exec, TYPE_MISMATCH_ERR);
            return jsUndefined();
        }


        KJS::JSValue* result = jsBoolean(imp->isPointInRange(refNode, offset, ec));
        setDOMException(exec, ec);
        return result;
    }
    }
    return 0;
}